Slf4J 不是底层日志框架,只是门面框架(抽象),需要配合jul、log4j、logback、log4j2等底层框架(真正干活的)使用。
补充:更老的门面框架还有jcl, 所以会看到有程序应用 jcl + log4j 这种搭配。Slf4J 后采用 Slf4J + log4j,但一些 jcl + log4j 项目也想用Slf4J 时,可以通过引入 jcl-over-slf4j log桥接工具的依赖,将原本输出到jcl的日志输出重定向到 SLF4J。
如果只用了slf4j,而没有使用任何底层框架,就会出现以下错误:
SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder". SLF4J: Defaulting to no-operation (NOP) logger implementation SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
log4j log4j 1.2.17
log4j.rootLogger=info, stdout log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - %m%n log4j.appender.logfile=org.apache.log4j.FileAppender log4j.appender.logfile.File=target/spring.log log4j.appender.logfile.layout=org.apache.log4j.PatternLayout log4j.appender.logfile.layout.ConversionPattern=%d %p [%c] - %m%n
import org.apache.log4j.Logger; //更多请阅读:https://www.yiibai.com/log4j/log4j_sample_program.html public class log4jExample{ static Logger log = Logger.getLogger(log4jExample.class.getName()); public static void main(String[] args) { if (log.isDebugEnabled()) { log.debug("### Hello this is an debug message"); } log.info("### Hello this is an info message"); // 不支持占位符 } }输出
2022-07-27 21:10:03,358 INFO [org.example.log4jExample] - ### Hello this is an info message
Logback 旨在作为流行的 log4j 项目的继承者,在 log4j 1.x 停止的地方接手。
Logback 的架构非常通用,可以在不同的情况下应用。 目前,logback 分为三个模块,logback-core、logback-classic 和 logback-access。
logback-core 模块为其他两个模块奠定了基础。
logback-classic 模块可以同化为 log4j 1.x 的显着改进版本。 此外,logback-classic 原生实现了 SLF4J API。
logback-access 模块与 Tomcat 和 Jetty 等 Servlet 容器集成,以提供 HTTP 访问日志功能。 请注意,您可以轻松地在 logback-core 之上构建自己的模块。
依赖
ch.qos.logback logback-classic 1.2.3
默认配置
Logback 默认配置的步骤 参考:https://www.cnblogs.com/warking/p/5710303.html
logback.xml
%-4relative [%thread] %-5level %logger{35} - %msg %n
代码
import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class LogbackExample { static Logger log = LoggerFactory.getLogger(LogbackExample.class); public static void main(String[] args) { if (log.isDebugEnabled()) { log.debug("### Hello this is an debug message"); } log.info("### Hello this is an info message"); // 不支持占位符 } }
输出
129 [main] INFO org.example.LogbackExample - ### Hello this is an info message
如果需要将日志按规则生成到文件,也可以在logback.xml中配置;logback.xml中各标签的含义,查阅上文。
如图可以配置将日志信息同时实时输出到终端和离线输出到日志文件。
@Slf4j 注解
能够少写两行代码,不用每次都在类的最前边写上:
private static final Logger logger = LoggerFactory.getLogger(this.XXX.class);
需要 lombok依赖。如果是基于SpringBoot,因为默认加入了Slf4j-api和logback的依赖,所以只需要添加lombok的依赖即可。
org.projectlombok lombok 1.16.10
import lombok.extern.slf4j.Slf4j; @Slf4j public class SLF4JExample { public static void main(String[] args) { if (log.isDebugEnabled()) { log.debug("### Hello this is an debug message"); } log.info("### Hello this is an info message"); // log 由lombok提供,如报错是idea的问题 } }
org.slf4j slf4j-log4j12 1.7.28
只需要依赖 slf4j-log4j12,它自身依赖log4j 和 slf4j-api 两个包。
配置
由于底层框架仍然使用的是log4j,仍然需要 配置文件: log4j.properties
log4j.rootLogger=info, stdout log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - %m%n log4j.appender.logfile=org.apache.log4j.FileAppender log4j.appender.logfile.File=target/spring.log log4j.appender.logfile.layout=org.apache.log4j.PatternLayout log4j.appender.logfile.layout.ConversionPattern=%d %p [%c] - %m%n
代码
import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class LogSlf4jExample { static Logger log = LoggerFactory.getLogger(LogSlf4jExample.class); public static void main(String[] args) { if (log.isDebugEnabled()) { log.debug("### Hello this is an debug message"); } log.info("### Hello this is an info message"); // 不支持占位符 } }
在代码层面已经实现和使用logback时一样了,都是从 org.slf4j.LoggerFactory 这个包下 getLogger来获取 Logger 对象。
当然也可以使用 @Slf4j 注解的方法。代码是一样的,无法看出底层框架是log4j还是logback。