Java日志体系框架总结:JUL、JCL、SLF4J、Log4j、Logback、Log4j2

news2024/11/15 15:34:22

概述

日志记录是应用程序运行中必不可少的一部分。具有良好格式和完备信息的日志,可以在程序出现问题时帮助开发人员迅速地定位错误的根源。日志所能提供的功能是多种多样的,包括记录程序运行时产生的错误信息、状态信息、调试信息和执行时间信息等。

System.out.printlnSystem.err.println及异常对象的printStrackTrace方法等,功能有限且混乱,故而需要日志框架。直到JDK1.4才引入java.util.logging包,JUL。

日志框架主要分两类:

  • 真正的日志记录实现,如:log4j、logback;
  • 日志记录相关的封装框架,如:Apache Commons Logging和SLF4J,在日志记录实现的基础上提供一个封装的API层次,对日志记录API的使用者提供一个统一的接口,使得可以自由切换不同的日志记录实现。

注:本文使用的Spring Boot版本为3.2.4。

日志级别Level

JDK的日志API,即java.util.logging.Logging,定义的级别,即java.util.logging.Level,包括OFF、SEVERE、WARNING、INFO、CONFIG、FINE、FINER、FINEST和ALL等。

OFF为日志最高等级,ALL为最低等级。每条日志必须对应一个级别,级别主要用来对日志的严重程度进行分类,同时可用于控制日志是否输出。

Log4j使用的级别则包括:OFF、FATAL、ERROR、WARN、INFO、DEBUG、TRACE和ALL等。用得较多的是:

  • FATAL:导致程序提前结束的严重错误
  • ERROR:运行时异常及预期之外的错误
  • WARN:预期之外的运行时状况,不一定是错误
  • INFO:运行时产生的事件
  • DEBUG:与程序运行时的流程相关的详细信息
  • TRACE:更加具体的详细信息

更进一步,以ERROR、WARN、INFO和DEBUG最为常用。

框架

Java Util Logging

即JUL,自JDK1.4版本引入,故而被称为JDK14Logger。

提供抽象基类Handler,和一系列实现类,如:ConsoleHandler、StreamHandler等。
在这里插入图片描述
提供抽象基类Formatter和2个实现类:
在这里插入图片描述
总结:JUL是JDK标准库一部分,无需额外的配置或依赖;使用logging.properties进行配置,相对复杂;扩展性不够;性能不好。

基本上没有多少应用在使用。

JULI

Java Util Logging Implementation,有些项目里可能会看到tomcat-juli

<dependency>
	<groupId>org.apache.tomcat</groupId>
	<artifactId>tomcat-juli</artifactId>
	<version>10.1.28</version>
</dependency>

主要用于标准Tomcat服务器环境,代替JUL,灵活性更好,功能更丰富,如独立的日志配置文件、按Web应用程序的隔离日志记录等。

作为Tomcat服务器中重要的日志组件,仍在维护和更新,满足用户的需求。

如果是Spring Boot内嵌Tomcat应用,则会看到:

<dependency>
	<groupId>org.apache.tomcat.embed</groupId>
	<artifactId>tomcat-embed-logging-juli</artifactId>
	<version>8.5.2</version>
</dependency>

嵌入式Tomcat使用场景中,开发者倾向于使用更现代的日志框架(如后文即将介绍的Logback和Log4j来代替JUL),因此官方停止维护。

从pom文件看,两者没有什么关系,独立维护的两个项目,拥有不同的GAV;但是通过JD-GUI等工具初步分析,JAR包里的类(类名和数量)一模一样,不过源码包括内部类还是有很多差别的。

Jakarta Commons Logging

Jakarta Commons Logging,即JCL,是一个抽象层(适配器)日志框架,旨在提供对多个日志框架的统一访问接口。JCL在运行时动态查找和绑定日志实现,这使得其在不同的环境下可以自动选择合适的日志实现。

Apache Commons Logging

即Apache Commons Logging,前身是Jakarta Commons Logging。

Maven依赖如下:

<dependency>
	<groupId>commons-logging</groupId>
	<artifactId>commons-logging</artifactId>
</dependency>

动态查找原理,Log是一个接口声明。LogFactory的内部会去装载具体的日志系统,并获得实现该Log接口的实现类。流程如下:

  • 首先寻找org.apache.commons.logging.LogFactory属性配置
  • 否则,利用JDK1.3开始提供的服务发现机制SPI,会扫描classpath下的META-INF/services/org.apache.commons.logging.LogFactory文件,若找到则装载里面的配置,使用里面的配置
  • 否则,从classpath里寻找commons-logging.properties,找到则根据里面的配置加载
  • 否则,使用默认配置:如果能找到Log4j则使用Log4j实现,如果没有则使用JDK14Logger实现,再没有则使用commons-logging内部提供的SimpleLog实现。

因此,只要引入Log4j并在classpath配置log4j.xml,则commons-logging就会使用Log4j,而Java代码里无需添加任何Log4j代码。

存在的问题:动态绑定机制可能导致一些难以调试的配置问题,如在某些环境下可能绑定到意外的日志实现。

SLF4J

官网,GitHub。

Simple Logging Facade for Java,SLF4J,Java简单日志门面,类似于JCL。为不同的日志框架提供简单的门面或抽象的实现,允许最终用户在部署时能够接入自己想要使用的日志框架。

使用SLF4J时,需要使用某一种日志实现,必须选择正确的SLF4J的JAR包的集合,即各种桥接包,这就是SLF4J的静态绑定(bindings):
在这里插入图片描述
如上图,SLF4J(和其他日志框架)提供的binding如下:

  • logback-classic:因为Logback晚于SLF4J诞生,故一开始SLF4J没有提供Logback的实现类,由Logback提供,实现org.slf4j.spi.SLF4JServiceProvider
  • slf4j-logj12:SLF4J提供,下同。
  • slf4j-jdk14:使用JUL打印
  • slf4j-simple:使用SLF4J自带
  • slf4j-nop:不打印日志
  • slf4j-jcl:?

SLF4J静态绑定原理:SLF4J会在编译时查找org.slf4j.spi.LoggerFactoryBinder(2.0.0版本后,被org.slf4j.spi.SLF4JServiceProvider)的实现类,如slf4j-log4j12的实现类org.slf4j.impl.StaticLoggerBinder,该类里面实现对具体日志方案的绑定接入。任何一种基于SLF4J的实现都要有一个这个类。如果有任意两个实现SLF4J的包同时出现,可能会出现问题。

Bridging,桥接是指将某个特定的日志库的日志请求重定向到SLF4J,使得所有的日志调用最终都通过SLF4J处理。这对于希望将整个应用程序统一到一个日志框架下非常有用。
在这里插入图片描述

SLF4J对比Commons Logging

Commons Logging通过动态查找的机制,在程序运行时自动找出真正使用的日志库。使用ClassLoader寻找和载入底层的日志库,导致像OSGI这样的框架无法正常工作,因为OSGI的不同的插件使用自己的ClassLoader。OSGI的这种机制保证插件互相独立。

SLF4J在编译时静态绑定真正的Log库,可以在OSGI中使用。SLF4J支持参数化的log字符串,避免之前为了减少字符串拼接的性能损耗而不得不写的if(logger.isDebugEnable()),现在你可以直接写:logger.debug(“current user is: {}”, user)。拼装消息被推迟到它能够确定是不是要显示这条消息的时候,但是获取参数的代价并没有幸免。

其他

MDC

Marker

Migrator:为了方便从别的日志框架迁移到SLF4J,提供Migrator工具。具体原理,可参考GitHub项目slf4j-migrator目录。

Log4j

Apache的一个开放源代码项目,通过使用Log4j,可以控制日志信息输送的目的地是控制台、文件、GUI组件,甚至是套接口服务器、NT的事件记录器、Unix Syslog守护进程等;也可以控制每一条日志的输出格式;通过定义每一条日志信息的级别,能够更加细致地控制日志的生成过程。这些可以通过一个配置文件来灵活地进行配置,而不需要修改应用的代码。

Log4j由三个重要的组成构成:

  1. Loggers:日志记录器,控制要输出哪些日志记录语句,对日志信息进行级别限制
  2. Appenders:输出端,指定日志将打印到控制台还是文件中
  3. Layout:日志格式化器,控制日志信息的显示格式

常用的appender:

  • ConsoleAppender:控制台
  • FileAppender:文件
  • DailyRollingFileAppender:每天产生一个日志文件
  • RollingFileAppender:文件大小到达指定尺寸时产生新文件
  • WriterAppender:将日志信息以流格式发送到任意指定的地方

常用的layout:

  • HTMLLayout:以HTML表格形式布局
  • PatternLayout:可以灵活地指定布局模式
  • SimpleLayout:包含日志信息的级别和信息字符串
  • TTCCLayout:包含日志产生的时间、线程、类别等信息

Log4j的早期GAV如下:

<dependency>
	<groupId>log4j</groupId>
	<artifactId>log4j</artifactId>
	<version>1.2.17</version>
</dependency>

这就是Log4j1,被废弃,不建议使用。新的GAV如下:

<dependency>
	<groupId>org.apache.logging.log4j</groupId>
	<artifactId>log4j-core</artifactId>
</dependency>

值得一提的是,log4j-core的第一个正式版为2.0,这就是Log4j2。

spring-boot-starter-log4j的最后一个版本:

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-log4j</artifactId>
	<version>1.3.8.RELEASE</version>
</dependency>

依赖于上面的log4j,此artifact已废弃:
在这里插入图片描述
使用如下GAV:

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>

默认引入:

<dependency>
	<groupId>org.apache.logging.log4j</groupId>
	<artifactId>log4j-slf4j2-impl</artifactId>
	<!-- Spring Boot 3.2.4 版本 -->
	<version>2.21.1</version>
	<!-- scope = compile,下文不再赘述 -->
	<scope>compile</scope>
</dependency>
<dependency>
	<groupId>org.apache.logging.log4j</groupId>
	<artifactId>log4j-core</artifactId>
</dependency>
<dependency>
	<groupId>org.apache.logging.log4j</groupId>
	<artifactId>log4j-jul</artifactId>
</dependency>

Logback

由Log4j创始人设计的又一个开源日记组件,作为Log4j的替代者,性能表现比Log4j优异。

<dependency>
	<groupId>ch.qos.logback</groupId>
	<artifactId>logback-core</artifactId>
</dependency>

对于Spring Boot应用,引入spring-boot-starter-logging依赖即可:

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-logging</artifactId>
</dependency>

默认引入如下依赖:

<dependency>
	<groupId>ch.qos.logback</groupId>
	<artifactId>logback-classic</artifactId>
	<version>1.4.14</version>
</dependency>
<dependency>
	<groupId>org.apache.logging.log4j</groupId>
	<artifactId>log4j-to-slf4j</artifactId>
	<version>2.21.1</version>
</dependency>
<dependency>
	<groupId>org.slf4j</groupId>
	<artifactId>jul-to-slf4j</artifactId>
	<version>2.0.12</version>
</dependency>

Spring Boot将使用Logback作为日志框架,无需新增logback.xml,开箱即用,这也是Spring Boot的方便之处。当然为了方便收集日志和统一维护,一般都会定义logback.xml

性能对比

Logback在设计上优于Log4j,但和下面将出场的Log4j2,孰优孰劣,请参考官网benchmark。

Log4j2

Logback在2017年3月31日发布1.2.3版本后,在很长一段时间内几乎处于停滞状态,这也使得在Maven上看到这个版本的Usages高达1w多。
在这里插入图片描述
4年多后,2021年7月19日终于发布1.2.4版本。

事实上,Logback自身也确实存在一些问题:

  • 配置繁琐
  • 功能简陋
  • 异步性能不高

因此,有不少开发者将目光投向Log4j2。除内部设计的调整外,有以下几点大升级:

  • 更简化的配置
  • 更强大的参数格式化
  • 夸张的异步性能

Log4j2中,分为API(log4j-api)和实现(log4j-core)两个模块,log4j-core包含log4j-api。API和SLF4J类似,属于日志抽象/门面;而实现才是Log4j2的核心:

  • org.apache.logging.log4j » log4j-api
  • org.apache.logging.log4j » log4j-core

从2016年5月25日发布的2.6版本开始,Log4j2默认就以零GC模式运行。即不会由于Log4j2而导致GC。Log4j2中各种Message对象,字符串数组,字节数组等全部复用,不重复创建,大大减少无用对象的创建,从而做到零GC。

Log4j2提供MemoryMappedFileAppender,使用MemoryMappedFile来实现,可以得到极高的I/O性能。

Log4j2支持XML/JSON/YML/Properties四种格式的配置文件,最主流的还是XML。

log4j-api和SLF4J相比,提供更丰富的参数格式化功能。Log4j2除了支持{}形式的参数占位符,还支持String.format形式:

private static final Logger logger1 = LogManager.getLogger(Test.class);
logger1.info("current time {}", new Date());
// getFormatterLogger方法才能使用String.format打印
private static final Logger logger = LogManager.getFormatterLogger(Test.class);
logger.info("current time %s", new Date());

惰性打印:Log4j2的Logger,提供一系列lambda支持,通过这些方法可实现惰性打日志。

与其他日志抽象/门面适配
在这里插入图片描述

Benchmark

参考Log4j2官网。

原理

classpath下新增配置文件如log4j2.xml,配置好Appenders和Loggers。
在这里插入图片描述
一个应用中可能存在多个有效的LoggerContext。每一个LoggerContext都有一个有效的Configuaration,它包含所有的Appenders、context-wide Filters、LoggerConfigs以及对StrSubstitutor的引用。在重新配置期间,两个Configuaration会同时存在;一旦日志器被重新赋予新的Configuaration,旧的Configuaration就会停止工作并丢弃。

LoggerConfig将会在Loggers在logging configuration中被声明时创建。在LoggerConfig拥有一列类的过滤器,这些过滤器将会过来所有的记录日志的事件,只有符合要求的日志才会被传递到Appenders。LoggerConfig需要将事件传递给Appenders,所以它拥有一系列Appenders的引用。

根据Logger请求选择去接受或者拒绝该只是他们的一个能力。Log4j2允许日志打印服务打印到多个目的地上,即Appdender。Appender可以是:Console、Async、File、JDBC、Cassandra、Failover、Flume、JMS、JPA、Http、Kafka、MemoryMappedFile、NoSQL、OutputStream、RandomAccessFile等。

体系

logback-classic依赖于logback-core

commons-logging.commons-logging-api已废弃,使用commons-logging.commons-logging

log4j-over-slf4j

log4j-core依赖于log4j-api

log4j-slf4j2-impl

其他可能在开发中看到的日志框架,如jboss-logging,类似于JCL:

<dependency>
	<groupId>org.jboss.logging</groupId>
	<artifactId>jboss-logging</artifactId>
	<version>3.6.0.Final</version>
</dependency>

TODO。

实战

Log4j

一般都是配合SLF4J使用:

  1. 仅供参考的log4j.properties文件
log4j.rootCategory=INFO,stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS} %5p %X{RequestId} - %m%n
log4j.appender.RollingFile.File=logs/app.log
log4j.appender.RollingFile.layout=org.apache.log4j.PatternLayout
log4j.logger.org.springframework=warn # Spring日志记录到warn级别
  1. Logger调用。在每一个要产生日志的类添加如下代码:
private static final Logger LOGGER = Logger.getLogger(*.class);

Logback

另起一篇,参考Logback实战使用笔记。

Lombok

上面介绍过,在使用log4j时,每个类都需要定义一个Logger,还是挺麻烦的。借助于Lombok的注解@Slf4j,省去冗余定义。

问题

程序包org.slf4j不存在

使用Lombok的@Slf4j注解,报错如上。

排查思路:借助于Maven Helper或mvn dependency:tree命令分析是否添加slf4j-api这个JAR包。如果是多Maven module项目,则需要判断一下Maven dependencyManagement使用是否正确。

ClassNotFoundException: org.apache.logging.log4j.util.Lazy

报错如上。

排查:org.apache.logging.log4j.util.Lazy位于org.apache.logging.log4j:log4j-api这个JAR包里,而log4j-core而默认引入log4j-api。ClassNotFoundException这个异常一般都是类冲突,即多个JAR包引入相同的类。通过Maven Helper分析,发现当前Maven module项目里还引入一个org.apache.logging.log4j:log4j-slf4j2-impl。经过试错,排除掉后面这个依赖,即log4j-slf4j2-impl,可解决问题。

参考

  • 深入理解Slf4j框架绑定原理

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2038664.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Day 22~28 MySQL

MySQL 1、数据库 JavaEE&#xff1a;企业级开发 Web 前端 &#xff08;页面&#xff1a;展示&#xff0c;数据&#xff09; 后台&#xff08;连接点&#xff1a;连接数据库JDBC&#xff0c;连接前端&#xff08;控制&#xff0c;控制视图跳转&#xff0c;给前端传递数据&…

dedecms织梦 验证码不显示问题

dedecms验证码不显示呢?近期小编仔细研究了一下并根据网上的各个版本总结下面几种解决方法&#xff1a; 问题一&#xff1a;首先先确定php配置环境没问题&#xff0c;如果一个服务器有的网站显示验证码有的不显示&#xff0c;可以排除运行环境的问题;出现这种情况有可能是&…

学习日志8.14--ALC(Access Control List)访问控制列表

ACL访问控制列表是一条或者多条流量规则的集合&#xff0c;作用主要用于流量的匹配&#xff0c;还可以匹配路由。通过ACL对流量加以控制&#xff0c;通过配合使用过滤工具&#xff0c;对流量进行拦截。需要注意的是ACL只是一个个匹配工具&#xff0c;负责匹配源IP地址、目的IP地…

nestjs 全栈进阶--typeorm 一对一

1. 介绍 在 TypeORM 中&#xff0c;一对一&#xff08;One-to-One&#xff09;关系是一种数据库关系&#xff0c;其中一个表中的每一行只与另一个表中的一行相关联。比如用户和身份证 2. 准备 我们还是将就上节课的项目&#xff0c;不过我们需要把数据库删除了 右键&#x…

[CSS3]2D与3D变换技术详解

文章目录 2D变换&#xff08;2D Transform&#xff09;3D变换&#xff08;3D Transform&#xff09;结语 CSS3中的2D变换与3D变换是指通过transform属性对HTML元素进行几何操作&#xff0c;使其在二维或三维空间中进行移动、旋转、缩放和倾斜等变换。这些变换为前端开发者提供了…

秒通多语种!2024年超实用的4款翻译在线工具,真心好用

互联网时代让沟通变得没有界限。不论是和邻居闲聊家常&#xff0c;还是与远在海外的朋友畅谈&#xff0c;现在都非常容易。特别是对于正在学习外语的人来说&#xff0c;在线翻译工具就像是超级英雄的披风一样重要。我研究了很多资料&#xff0c;找到了几款性价比非常高的翻译在…

Java虚拟机:类的加载机制

大家好&#xff0c;我是栗筝i&#xff0c;这篇文章是我的 “栗筝i 的 Java 技术栈” 专栏的第 034 篇文章&#xff0c;在 “栗筝i 的 Java 技术栈” 这个专栏中我会持续为大家更新 Java 技术相关全套技术栈内容。专栏的主要目标是已经有一定 Java 开发经验&#xff0c;并希望进…

【BUU】[Dest0g3 520迎新赛]Really Easy SQL

2024/8/14 [Dest0g3 520迎新赛]Really Easy SQL 题目标题说明是SQL注入 题目首页 页面title显示是钓鱼站点。 钓鱼站点主要为将我们的输入信息保存在数据库。后台应该是插入语句。 这里无论输入什么都显示密码错误, 只能尝试盲注&#xff0c;基于时间的盲注, 这里经过测试p…

OPC DAY-上海场提前预告:Softing带您探索“智能工厂中的OPC应用”

&#xff08;图片来源于&#xff1a;OPC基金会官网&#xff09; 时间&#xff1a;2024年9月25日 14:00-14:30 | OPC DAY-上海站 地点&#xff1a;上海国家会展中心-5.1H M5-03会议室 2024年9月24-28日&#xff0c;第二十四届中国国际工业博览会将于国家会展中心&#xff08;上…

Linux 中的同步机制

代码基于&#xff1a;Kernel 6.6 临界资源&#xff1a;指哪些在同一时刻只允许被一个线程访问的软件或硬件资源。这种资源的特点是&#xff0c;如果有线程正在使用&#xff0c;其他进程必须等待直到该线程释放资源。 临界区&#xff1a;指在每个线程中访问临界资源的那段代码。…

vue3结合海康WEB开发包,开发web在线预览视频

我们这里选择V3.3版本 文档地址&#xff1a;https://open.hikvision.com/download/5cda567cf47ae80dd41a54b3?type20&id4c945d18fa5f49638ce517ec32e24e24 解压过后&#xff0c;会有三个文件夹 在docs中&#xff0c;点开Demo使用说明&#xff0c;按照流程先测试下&…

赋能基层,融合创新:EasyCVR视频汇聚平台构建平安城市视频共享系统

一、雪亮工程建设的意义 雪亮工程的核心在于通过高清视频监控、环境监测和智能预警等先进技术手段&#xff0c;构建一个高效、智能、安全、便捷的社会安全防控体系。这一工程的建设不仅代表了现代化科技手段在城市治安管理中的应用&#xff0c;更是提升社会安全保障能力、推动…

树形结构查找(B树、B+树)

平衡树结构的树高为 O(logn) &#xff0c;平衡树结构包括两种平衡二叉树结构&#xff08;分别为 AVL 树和 RBT&#xff09;以及一种树结构&#xff08;B-Tree&#xff0c;又称 B 树&#xff0c;它的度大于 2 &#xff09;。AVL 树和 RBT 适合内部存储的应用&#xff0c;而 B 树…

CompreFace Study

系列文章目录 第一章 CompreFace Installation 第二章 Face verification POC 文章目录 系列文章目录前言一、What is the ComreFace&#xff1f;二、How to install the CompreFace? 1.On Linux for CompreFace 1.2.02.Troubleshooting总结 前言 此文旨在记录学习CompreF…

萤石取流播放失败自助排障及常见错误码解决方案

一、在使用播放地址播放时遇到播放失败的情况&#xff0c;可使用排障工具排查具体原因&#xff0c;以下具体介绍排障工具的使用方法 1、在浏览器里打开排障工具&#xff0c;地址&#xff1a;萤石开放平台-提供持续稳定的以音视频为主的全场景、多功能综合性服务 2、在第一行输入…

安全无忧!Windows7全补丁旗舰版:集成所有补丁!

今日&#xff0c;系统之家小编给大家分享集成所有补丁的Windows7旗舰版系统&#xff0c;集成至2023.12所有官方补丁&#xff0c;修复了系统高危漏洞&#xff0c;让大家时刻都能舒心地展开操作。系统基于微软 Windows 7 2009 SP1 旗舰版进行离线制作&#xff0c;全新升级的优化方…

本地环境VMware使用代理解决 Docker 镜像拉取问题

引言 本文将分享我在 Windows 10 环境下&#xff0c;通过 VMware 运行的 CentOS 7.8 虚拟机中配置 Docker 代理&#xff0c;成功解决了镜像拉取问题的经验。 问题描述 在尝试启动一个依赖 Docker 的 GitHub 项目时&#xff0c;拉取 Docker 镜像的失败。尝试配置了几个国内源…

(附源码)基于springboot的智慧社区管理系统-计算机毕设 06797

基于springboot的智慧社区管理系统 摘 要 SpringBoot智慧社区管理系统是一款基于SpringBoot框架开发的智能化社区管理软件&#xff0c;致力于提升社区管理效率和服务质量。该系统涵盖了社区入住管理、物业费管理、公共设施预约等功能&#xff0c;支持在线报修、信息发布、社区活…

Java语言程序设计——篇十三(2)

&#x1f33f;&#x1f33f;&#x1f33f;跟随博主脚步&#xff0c;从这里开始→博主主页&#x1f33f;&#x1f33f;&#x1f33f; 欢迎大家&#xff1a;这里是我的学习笔记、总结知识的地方&#xff0c;喜欢的话请三连&#xff0c;有问题可以私信&#x1f333;&#x1f333;&…

【运维】报错Resource averaged_perceptron_tagger_eng not found.

文章目录 报错信息解决报错信息 able of handling various complex tasks. Please report the progress of this project to the team members.> ========================<