java日志框架介绍
参考地址:https://blog.csdn.net/xhf852963/article/details/141226327
java主流日志框架
-
日志实现(具体干活的):JUL(java util logging)、logback、log4j、log4j2
-
日志门面(指定规则的):JCL(Jakarta Commons Logging)、slf4j( Simple Logging Facade for Java)
JUL日志框架
Java util Logging是java原生的日志框架,使用时不需要另外引用第三方类库,使用方便,学习简单,能在小型应用中灵活使用。
在JUL中有以下组件:
Loggers:被称为记录器,应用程序通过获取Logger对象,调用其API来来发布日志信息。Logger 通常时应用程序访问日志系统的入口程序。
- Handler :负责将日志记录发送到适当的目的地,如控制台、文件或者网络目的地。下面是一些常见的 Handler 类型:
- ConsoleHandler - 将日志记录输出到标准错误流(通常是控制台)。
- FileHandler - 将日志记录输出到文件中。可以通过配置指定文件名模式,允许创建滚动文件。
- SocketHandler - 将日志记录发送到套接字服务器。
- StreamHandler - 将日志记录输出到任意的输出流。
- MemoryHandler - 将日志记录存储在内存缓冲区中,当满足某些条件时,将缓冲区中的日志记录推送到目标 Handler。
Formatters:Formatter 接口用于定义日志记录的格式。通过自定义 Formatter,可以控制日志输出的具体样式,比如日期格式、消息前缀等。也有一些内置的 Formatter 类。
Level:每条日志消息都有一个关联的日志级别。该级别粗略指导了日志消息的重要性和紧迫,可以将Level和Loggers,Handler 做关联以便于我们过滤消息。
Filters:过滤器,根据需要定制哪些信息会被记录,哪些信息会被放过。
代码示例
package org.example.logTest; import java.io.IOException; import java.util.logging.*; public class JUITest1 { public static void main(String[] args) { // 获取日志记录器对象 Logger logger = Logger.getLogger("org.example.logTest.JUITest1"); // 日志输出 logger.info("日志输出测试:1111111111"); // 使用通用方法进行日志输出 logger.log(Level.INFO,"message info !"); // 通过占位符方式代替字符串拼接输入日志 String name = "yoyo"; int age = 20; logger.log(Level.INFO,"name:{0},age:{1}",new Object[]{name,age}); try { // 1.创建 FileHandler 实例,指定日志文件的位置和是否追加日志 FileHandler fileHandler = new FileHandler("app.log", true); // 2.设置日志格式化器 fileHandler.setFormatter(new SimpleFormatter()); // 3.创建 ConsoleHandler 实例 ConsoleHandler consoleHandler = new ConsoleHandler(); // 添加 Handler 到 Logger logger.addHandler(fileHandler); logger.addHandler(consoleHandler); // 4.设置 Logger 的日志级别 logger.setLevel(java.util.logging.Level.ALL); // 记录一条日志消息 logger.info("This is an info message."); } catch (IOException e) { throw new RuntimeException(e); } } }
运行结果

JUL日志级别
在 JUL 中定义了 7 种日志的级别,分别为:SEVERE(最高值)> WARNING > INFO (默认级别) > CONFIG > FINE > FINER > FINEST(最低值),如下代码:
package org.example.logTest; import java.util.logging.Level; import java.util.logging.Logger; public class JULTest2 { public static void main(String[] args) { // 1.创建日志记录器对象 Logger logger = Logger.getLogger("org.example.logTest"); //2.日志输出的第二种方式,指定日志的输出级别 logger.log(Level.SEVERE,"SEVERE msg"); logger.log(Level.WARNING,"WARNING msg"); logger.log(Level.INFO,"INFO msg"); logger.log(Level.CONFIG,"CONFIG msg"); logger.log(Level.FINE,"FINE msg"); logger.log(Level.FINER,"FINER msg"); logger.log(Level.FINEST,"FINEST msg"); } }
运行结果:

可以看到由于默认级别是 INFO,它只会打印比 INFO 级别高的日志。
我们看看Level这个枚举类的源代码:
public class Level implements java.io.Serializable { private static final String defaultBundle = "sun.util.logging.resources.logging"; private final String name; private final int value; private final String resourceBundleName; private transient String localizedLevelName; private transient Locale cachedLocale; public static final Level OFF = new Level("OFF",Integer.MAX_VALUE, defaultBundle); public static final Level SEVERE = new Level("SEVERE",1000, defaultBundle); public static final Level WARNING = new Level("WARNING", 900, defaultBundle); public static final Level INFO = new Level("INFO", 800, defaultBundle); public static final Level CONFIG = new Level("CONFIG", 700, defaultBundle); public static final Level FINE = new Level("FINE", 500, defaultBundle); public static final Level FINER = new Level("FINER", 400, defaultBundle); public static final Level FINEST = new Level("FINEST", 300, defaultBundle); public static final Level ALL = new Level("ALL", Integer.MIN_VALUE, defaultBundle); protected Level(String name, int value) { this(name, value, null); } protected Level(String name, int value, String resourceBundleName) { this(name, value, resourceBundleName, true); } private Level(String name, int value, String resourceBundleName, boolean visible) { if (name == null) { throw new NullPointerException(); } this.name = name; this.value = value; this.resourceBundleName = resourceBundleName; this.localizedLevelName = resourceBundleName == null ? name : null; this.cachedLocale = null; if (visible) { KnownLevel.add(this); } }
......
自定义日志级别
还有两个特殊的级别,ALL 和 OFF,他们都属于自定义的级别,其中 OFF 可用来关闭日志记录,ALL 可用来启用所有的日志消息,如下代码:
package org.example.logTest; import java.util.logging.ConsoleHandler; import java.util.logging.Level; import java.util.logging.Logger; import java.util.logging.SimpleFormatter; public class JULTest3 { public static void main(String[] args) { // 1.创建日志记录器对象 Logger logger = Logger.getLogger("org.example.logTest"); // 2.关闭系统默认的级别 logger.setUseParentHandlers(false); // 3.重新配置日志具体级别 logger.setLevel(Level.ALL); // 4.创建 ConsoleHandler 控制台输出 ConsoleHandler consoleHandler = new ConsoleHandler(); // 5.创建简单格式转换对象 SimpleFormatter simpleFormatter = new SimpleFormatter(); // 6.将 Handler 和 Formatter 进行关联: logger ——关联—— Handler ——关联—— Formatter consoleHandler.setFormatter(simpleFormatter); logger.addHandler(consoleHandler); // 7.设consoleHandler 控制台输出的级别~ consoleHandler.setLevel(Level.ALL); logger.log(Level.SEVERE,"SEVERE msg"); logger.log(Level.WARNING,"WARNING msg"); logger.log(Level.INFO,"INFO msg"); logger.log(Level.CONFIG,"CONFIG msg"); logger.log(Level.FINE,"FINE msg"); logger.log(Level.FINER,"FINER msg"); logger.log(Level.FINEST,"FINEST msg"); } }
运行结果:

Logger对象父子关系
JUL 中 Logger 之间存在父子关系,这种父子关系通过树状结构存储,JUL 在初始化时会创建一个顶层 RootLogger 作为所有 Logger 父 Logger,存储上作为树状结构的根节点。并父子关系通过路径来关联。
package org.example.logTest; import java.util.logging.ConsoleHandler; import java.util.logging.Level; import java.util.logging.Logger; import java.util.logging.SimpleFormatter; public class JULTest4 { public static void main(String[] args) { // 父子关系通过命名规范包结构来的 Logger logger1 = Logger.getLogger("org.example.logTest"); Logger logger2 = Logger.getLogger("org.example"); // logger1的父元素对象是logger2 System.out.println(logger1.getParent() == logger2); // 所有日志记录器的顶级父元素为:LogManager$RootLogger System.out.println(logger2.getParent()); // 创建控制台输出控制器 ConsoleHandler consoleHandler = new ConsoleHandler(); // 创建简单个格式转换对象 SimpleFormatter simpleFormatter = new SimpleFormatter(); logger2.addHandler(consoleHandler); consoleHandler.setFormatter(simpleFormatter); // 关闭系统默认的级别 logger2.setUseParentHandlers(false); // 设置日志级别 logger2.setLevel(Level.INFO); logger2.log(Level.INFO,"level info 1"); logger2.log(Level.FINE,"level fine 1"); // 子日志记录器默认继承父记录器日志级别 logger1.log(Level.INFO,"level info 2"); logger1.log(Level.FINE,"level fine 2"); } }
运行结果:

JUL日志配置文件
JUL日志配置文件默认位置:$JAVAHOME\jre\lib\logging.properties,如图:

指定配置文件的位置,首先在 resources 下创建一个 logging.properties 文件
handlers= java.util.logging.ConsoleHandler
.level= ALL
java.util.logging.FileHandler.pattern = %h/java%u.log
java.util.logging.FileHandler.limit = 50000
java.util.logging.FileHandler.count = 1
java.util.logging.FileHandler.formatter = java.util.logging.XMLFormatter
java.util.logging.ConsoleHandler.level = FINE
java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter
com.xyz.foo.level = SEVERE
在代码里面读取配置文件
package org.example.logTest; import java.io.IOException; import java.io.InputStream; import java.util.logging.LogManager; import java.util.logging.Logger; public class JULTest5 { public static void main(String[] args) throws IOException { // 通过类加载器读取自定义配置文件(通过类路径读取资源文件) InputStream in = JULTest5.class.getClassLoader().getResourceAsStream("logging.properties"); // 获取日志管理器对象 LogManager logManager = LogManager.getLogManager(); // 通过日志管理器加载配置文件 logManager.readConfiguration(in); Logger logger = Logger.getLogger("package org.example.logTest"); logger.severe("severe"); logger.warning("warning"); logger.info("info"); logger.config("config"); logger.fine("fine"); logger.finer("finer"); logger.finest("finest"); } }
运行结果

日志原理解析
JUL流程示意图:

1、初始化 LogManager,LogManager 加载 logging.properties 配置,并添加 Logger 到LogManager。
2、从单例 LogManager 获取 Logger
3、设置级别 Level,并指定日志记录 LogRecord
4、Filter 提供了日志级别之外更细粒度的控制
5、Handler 是用来处理日志输出位置
6、Formatter 是用来格式化 LogRecord 的。
Log4j
Log4j 是 Apache 下的一款开源的日志框架,通过在项目中使用 Log4J,我们可以控制日志信息输出到控制台、文件、甚至是数据库中。我们可以控制每一条日志的输出格式,通过定义日志的输出级别,可以更灵活的控制日志的输出过程。方便项目的调试。
Log4j官方文档:https://logging.apache.org/log4j/1.x/
https://logging.apache.org/
Log4j入门
添加maven依赖
<dependencies>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
</dependencies>
java代码demo
package org.example.logtest; import org.apache.log4j.BasicConfigurator; import org.apache.log4j.Logger; public class Logtest1 { public static void main(String[] args) { // 1、由于没有配置文件,所以需要初始化系统配置信息 BasicConfigurator.configure(); // 2、创建日志记录器对象 Logger logger = Logger.getLogger(Logtest1.class); // 3、日志记录输出的第一种方式 logger.info("hello log4j"); // 4、日志记录输出的第二种方式 logger.fatal("fatal"); // 严重错误,一般会造成系统崩溃和终止运行 logger.error("error"); // 错误信息,但不会影响系统运行 logger.warn("warn"); // 警告信息,可能会发生问题 logger.info("info"); // 程序运行信息,数据库的连接、网络、IO操作等 logger.debug("debug"); // 调试信息,一般在开发阶段使用,记录程序的变量、参数等 logger.trace("trace"); // 追踪信息,记录程序的所有流程信息 } }
输出结果如下所示,没有输出 trace 日志信息是因为 log4j 默认的日志输出级别是 debug

日志的级别从高到低分别为:fatal > error > warn > info > debug > trace ,在实际开发中一般只使用 error、warn、info 和 debug 就可以了。
Log4j组件
Log4J 主要由 Loggers (日志记录器)、Appenders(输出端)和 Layout(日志格式化器)组成。其中 Loggers 控制日志的输出级别与日志是否输出;Appenders 指定日志的输出方式(输出到控制台、文件等);Layout 控制日志信息的输出格式。
Loggers
日志记录器,负责收集处理日志记录,实例的命名就是类 “XX” 的 full quailied name(类的全限定名),Logger 的名字大小写敏感,其命名有继承机制:例如:name 为 org.apache.commons 的 logger 会继承 name 为 org.apache 的 logger。
Log4J 中有一个特殊的 logger 叫做 “root”,他是所有 logger 的根,也就意味着其他所有的 logger 都会直接或者间接地继承自 root。root logger 可以用 Logger.getRootLogger() 方法获取。
Appenders
Appender 用来指定日志输出到哪个地方,可以同时指定日志的输出目的地。Log4j 常用的输出目的地有以下几种:
ConsoleAppender 将日志输出到控制台
FileAppender 将日志输出到文件中
DailyRollingFileAppender 将日志输出到一个日志文件,并且每天输出到一个新的文件
RollingFileAppender 将日志信息输出到一个日志文件,并且指定文件的尺寸,当文件大小达到指定尺寸时,会自动把文件改名,同时产生一个新的文件
JDBCAppender 把日志信息保存到数据库中
Layout
布局器 Layouts 用于控制日志输出内容的格式,让我们可以使用各种需要的格式输出日志。 Log4j 常用的 Layouts 有以下几种:
HTMLLayout 格式化日志输出为HTML表格形式
SimpleLayout 简单的日志输出格式化,打印的日志格式为(info - message)
PatternLayout 最强大的格式化期,可以根据自定义格式输出日志,如果没有指定转换格式,就是用默认的转换格式
使用配置文件
在 resources 目录下添加 log4j.properties 的配置文件,并配置相关的配置信息,如下所示:
# 指定 RootLogger 顶级父元素默认配置信息
# 指定日志级别为 info,使用的 appdener 为 console
log4j.rootLogger = info,console
# 指定控制台日志输出的 appender 对象
log4j.appender.console = org.apache.log4j.ConsoleAppender
# 指定消息格式 layout
log4j.appender.console.layout = org.apache.log4j.SimpleLayout
测试代码如下:
package org.example.logtest; import org.apache.log4j.Logger; public class Logtest2 { public static void main(String[] args) { Logger logger = Logger.getLogger(Logtest2.class); // 2、日志记录输出的第一种方式 logger.info("hello log4j"); // 3、日志记录输出的第二种方式 logger.fatal("fatal"); // 严重错误,一般会造成系统崩溃和终止运行 logger.error("error"); // 错误信息,但不会影响系统运行 logger.warn("warn"); // 警告信息,可能会发生问题 logger.info("info"); // 程序运行信息,数据库的连接、网络、IO操作等 logger.debug("debug"); // 调试信息,一般在开发阶段使用,记录程序的变量、参数等 logger.trace("trace"); // 追踪信息,记录程序的所有流程信息 } }

输出到文件
配置文件如下
# 指定 RootLogger 顶级父元素默认配置信息 # 指定日志级别为 info,使用的 appdener 为 console log4j.rootLogger = info,console,file # 指定控制台日志输出的 appender 对象 log4j.appender.console = org.apache.log4j.ConsoleAppender # 指定消息格式 layout log4j.appender.console.layout = org.apache.log4j.SimpleLayout # 日志输出的 appender 对象 log4j.appender.file = org.apache.log4j.FileAppender # 指定消息格式 layout log4j.appender.file.layout = org.apache.log4j.PatternLayout # 指定消息格式的内容 log4j.appender.file.layout.conversionPattern = [%p]%r %l %d{yyyy-MM-dd HH:mm:ss.SSS} %m%n # 指定日志文件保存路径 log4j.appender.file.file = log4j.log # 指定日志文件的字符集 log4j.appender.file.encoding = UTF-8
再次运行以上代码,则日志文件输出到了项目根目录

日志门面
在项目的初期时,我们可能只是使用 JUL 进行日志的单一输出,JUL 可以满足项目的需求。但是随着功能的增加,单一的日志文件会越来越臃肿,所以我们需要按照一定的规则进行滚动拆分,比如说按照时间以天为单位进行管理,但是 JUL 并不支持。
此时我们就需要在项目中引入 log4j,但是项目之前的日志代码都是基于 JUL 来实现的,一旦换了日志框架,那么之前的代码就需要修改,工作量是非常大的。所以此时 apache 组织就站出来了,将这两个日志框架进行了统一的管理和维护,提供了一个日志门面 JCL ,并提供了一套全新的 api,以面向接口的方式来操作具体的实现。即日志框架变了,代码也不需要发生修改。这个就是日志门面技术。
日志门面的实现
常见的日志门面有 JCL 和 slf4j。JCL 仅支持 JUL 和 log4j 框架,目前已经被淘汰。slf4j 是目前市场上比较主流的日志门面,它支持现在所有的日志实现框架。
常见的日志实现有 JUL、log4j、logback、log4j2 等。
日志门面和日志实现关系
最早的时候,用户要想进行日志记录是直接操作日志实现类的。这种方式意味着,如果后期日志实现发生了变化,代码也需要发生变化。
但是现在有了日志门面之后,用户只需要操作统一的 api 就可以了,由这套接口的底层再去操作具体的日志实现进行日志的记录,这样就可以实现用户和日志实现的解耦的思想,方便进行统一的管理和维护。后期如果想替换日志实现,只需要替换相应的 jar 包即可。

日志框架历史顺序
log4j -->JUL-->JCL--> logback --> slf4j --> log4j2
- jdk 最早期的时候是没有提供日志记录功能的,而是通过 System.out 的方式进行输出,此时 apache 的一个哥们就设计出了一个框架 log4j,设计出来之后很受欢迎。所以 jdk 在 1.4 版本时也设计出了一个日志框架 JUL。
- 所以当时市场就比较混乱,有的公司使用 log4j,有的公司使用 JUL,为了解决这个问题,apache 公司就推出了 JCL 来统一管理 log4j 和 JUL。
- 过了一段时间之后 log4j 的创始人和 apache 闹了一些矛盾就出去单飞了,然后单飞的这个哥们就基于 log4j 设计出了一个全新的日志框架 logback,功能和性能比 log4j 更强大,但是用的人不多,因为 JCL 不支持 logback。
- 基于这种情况,这个哥们又设计出了一个日志门面 slf4j,这个日志门面支持所有的日志实现框架,而且操作起来非常简单。等到 slf4j 出现之后,JCL 就完犊子了。
- apache 公司就着急了,市场上没有人用了,所以他们就蛰伏了两年,根据 logback 开放的源代码,设计出了全新的日志框架 log4j2,它从功能上而言几乎和 logback 一致,但是性能上比 logback 提升了很多。需要注意的是 log4j2 既是日志门面技术也是日志实现框架
使用日志门面的原因
- 面向接口开发,不再依赖具体的实现类。减少代码的耦合
- 项目通过导入不同的日志实现类,可以灵活的切换日志框架
- 统一 API,方便开发者学习和使用
- 统一配置便于项目日志的管理
JCL日志门面
JCL官方文档:https://commons.apache.org/proper/commons-logging/dependency-info.html
JCL 全称为 Jakarta Commons Logging,是 Apache 提供的一个通用日志 API。
它是为 "所有的 Java 日志实现" 提供一个统一的接口,它自身也提供一个日志的实现,但是功能非常常弱(SimpleLog)。所以一般不会单独使用它。他允许开发人员使用不同的具体日志实现工具:Log4j、Jdk 自带的日志(JUL)。
JCL 有两个基本的抽象类:基本记录器 Log 和负责创建 Log 实例的 LogFactory。架构图如下:

首先创建一个 maven 工程,添加如下的 maven 依赖:
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.2</version>
</dependency>
测试代码如下:
package org.example.logTest; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; public class LogTest1 { public static void main(String[] args) { // 创建日志对象 Log log = LogFactory.getLog(LogTest1.class); // 日志记录输出 log.fatal("fatal"); log.error("error"); log.warn("warn"); log.info("info"); log.debug("debug"); System.out.println("Hello world!"); } }
输出结果如下,可以看到 JCL 默认调用的就是 JUL 里面的 api 来打印日志的。

接下来我们添加 log4j 的 maven 依赖,并将 log4j.properties 配置文件复制到 resources 目录下,再次执行上面的代码,可以看到,这次调用就是 log4j 的底层 api 了。

JCL原理
JCL 底层实际上是通过 LogFactory 动态加载 Log 实现类来完成日志功能的,可以加载下面的四种实现类。

JCL 这种日志门面支持的日志实现数组有下面的四个,首先判断是否存在 log4j ,如果存在则调用它的 api,不存在则调用 jdk 自带的 logger。
slf4j
官方文档:https://www.slf4j.org/manual.html
简单日志门面(Simple Logging Facade For Java)SLF4J 主要是为了给 Java 日志访问提供一套标准、规范的 API 框架,其主要意义在于提供接口,具体的实现可以交由其他日志框架,例如 log4j 和 logback 等。当然 slf4j 自己也提供了功能较为简单的实现,但是一般很少用到。对于一般的 Java 项目而言,日志框架会选择 slf4j 作为门面,配上具体的实现框架(log4j、logback等),中间使用桥接器完成桥接。
SLF4J 是目前市面上最流行的日志门面。现在的项目中,基本上都是使用 SLF4J 作为我们的日志系统。SLF4J 日志门面主要提供两大功能:日志框架的绑定和日志框架的桥接。
快速入门
首先创建一个 maven 工程,并添加下面的依赖:
<dependencies>
<!--slf4j core 使用slf4j必須添加-->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>2.0.17</version>
</dependency>
<!--slf4j 自带的简单日志实现 -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>2.0.17</version>
</dependency>
</dependencies>
测试代码
package org.example.logTest; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class Logtest1 { // 声明日志对象 private final static Logger LOGGER = LoggerFactory.getLogger(Logtest1.class); public static void main(String[] args) { //打印日志信息 LOGGER.error("error"); LOGGER.warn("warn"); LOGGER.info("info"); // 默认输出级别为 info LOGGER.debug("debug"); LOGGER.trace("trace"); // 使用占位符输出日志信息 String name = "jack"; Integer age = 18; LOGGER.info("用户:{},{}", name, age); // 将系统异常信息写入日志 try { int i = 1 / 0; } catch (Exception e) { // e.printStackTrace(); LOGGER.info("出现异常:", e); } } }
运行结果

绑定日志的实现

在这个图片的上方绿颜色的部分表示的是我们项目的应用,如果我们的项目想要进行日志记录的话,首先需要关联 SLF4J,它就是面向的接口,统一所有日志的 api,就是 maven 依赖里面的 slf4j-api ,它的下方需要提供具体的实现,在这里一共有三种情况。
第一种情况是如果项目中只引入了 slf4j-api 日志门面,并没有导入具体的日志实现,那么日志的这个功能就是关闭的,此时不会进行任何的日志输出。上图中左侧的第一个。
第二种情况是蓝颜色部分,它里面有三种日志实现,一个是 logback,一个是 slf4j 内置的 simple 简单框架,还有一个是 nop,这三个框架的设计是要比 slf4j 要晚的,所以它们默认就遵从 slf4j 的开发规范了,即我们只需要导入它们的实现即可。上图中左侧的第二、五和六个。
第三种情况是灰颜色部分,即中间那两个,一个是 log4j,一个是 JUL,它们两个设计的比较早,默认是并没有遵循 slf4j 的规范的,它们是无法进行直接绑定的,中间需要添加一个适配层 Adaptation 来适配我们具体的实现,就会简介的遵循我们的 slf4j 的 api 规范。
绑定logback
logback文档地址:https://logback.qos.ch/documentation.html
添加maven依赖
<dependencies>
<!--slf4j core 使用slf4j必須添加-->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.27</version>
</dependency>
<!-- logback 日志实现-->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
</dependencies>
执行上面同样的代码,如图:

绑定 slf4j-nop
slf4j-nop 是一个日志的开关,当我们导入这个实现之后,就表示 slf4j 就不会使用任何的日志实现框架,这个功能就关闭了,如下 maven 依赖:
<dependencies>
<!--slf4j core 使用slf4j必須添加-->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.27</version>
</dependency>
<!-- nop 日志的开关-->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-nop</artifactId>
<version>1.6.6</version>
</dependency>
</dependencies>
运行上面的代码,可以看到无任何日志输出

绑定log4j
如果想要绑定 log4j,需要需要绑定一个 slf4j-log412 适配器,如下 maven 依赖:
<dependencies>
<!--slf4j core 使用slf4j必須添加-->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.27</version>
</dependency>
<!-- 绑定 log4j 日志实现,需要导入适配器-->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.25</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
</dependencies>
还需要把以前案例中使用的 log4j.properties 文件粘贴到 resources 目录下,然后执行测试代码,如下所示:


浙公网安备 33010602011771号