1. 为什么使用Logger打印日志?
- 在真实的开发中,绝不会使用
System.out
去打印信息的 - 因为一个服务出现问题时,我们希望知道服务出问题的时间、它是在执行哪个类的代码出问题了等信息
- 如果开发者不手动传入上述信息,则
System.out
打印出来的内容是不会包含上述信息的,这对我们分析、排查问题来说,是十分不友好的 - 专为日志打印而生的Logger,天生或者通过一些全局配置,就能自动打印上述必要信息,无需开发者手动传入
- 下面的代码,分别使用logger和
System.out
去打印信息:import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class LoggerTest { private static final Logger logger = LoggerFactory.getLogger(LoggerTest.class); public static void main(String[] args) { logger.error("ERROR level message"); System.out.println("System.out message"); } }
- 可以发现,logger打印的内容十分丰富,有利于分析、排查问题;而
System.out
打印的信息,则十分简陋
- 因此,真实的开发中,都会选择使用某种Logger进行日志打印
2. slf4j + logback-classic实现日志打印
2.1 引入依赖
-
引入如下依赖,其中,SLF4J(
Simple logging Facade for Java
)不是一个真正的日志实现,而是一个抽象层 (abstraction layer
)<!-- SLF4J(Simple logging Facade for Java)不是一个真正的日志实现,而是一个抽象层( abstraction layer)--> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>1.7.30</version> </dependency> <!-- 引入具体的日志实现,logback --> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> <version>1.2.3</version> </dependency> <!-- 必须添加,后续会说明原因 --> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-core</artifactId> <version>1.2.3</version> </dependency>
-
重新运行上面的示例代码,发现能成功打印日志信息
-
使用的logback的默认格式,打印的日志没有年月日,对于长期运行的服务来说,没有年月日那是十分不方便的
-
Don’t worry,日志格式是可以配置的。例如:你想不打印线程名,或者不想打印DEBUG级别的日志信息
2.2 如何设置日志格式
-
在
resoures
目录下,创建logback.xml
,输入以下内容,则可以打印带年月日的完整时间<?xml version="1.0" encoding="UTF-8"?> <configuration debug="false"> <!--控制台日志, 控制台输出 --> <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"> <!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度,%msg:日志消息,%n是换行符--> <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern> </encoder> </appender> <!-- 日志输出级别 --> <root level="DEBUG"> <appender-ref ref="STDOUT" /> </root> </configuration>
-
关于日志级别:
ERROR
<WARN
<INFO
<DEBUG
,若设置日志级别为INFO,则不会打印DEBUG级别的日志;其他情况,以此类推- 一般情况下,日志级别与打印日志的方法是对应的,例如,
error()
则打印ERROR级别的日志,info()
则打印INFO级别的日志
-
例如,将
logback.xml
的日志级别改为INFO,执行如下代码:public class LoggerTest { private static final Logger logger = LoggerFactory.getLogger(LoggerTest.class); public static void main(String[] args) { logger.error("ERROR level message"); logger.warn("WARN level message"); logger.info("INFO level message"); logger.debug("DEBUG level message"); } }
-
执行结果中,DEBUG级别的日志没有打印出来
-
其他的一些配置,可以参考博客:一文读懂Logback的配置
3. Caused by: java.lang.ClassNotFoundException: ch.qos.logback.core.joran.spi.JoranException
-
非maven项目,下载上述两个依赖的jar包,并将其放入
lib
目录 -
程序运行报错:
Failed to instantiate SLF4J LoggerFactory Reported exception: java.lang.NoClassDefFoundError: ch/qos/logback/core/joran/spi/JoranException at org.slf4j.LoggerFactory.bind(LoggerFactory.java:150) at org.slf4j.LoggerFactory.performInitialization(LoggerFactory.java:124) at org.slf4j.LoggerFactory.getILoggerFactory(LoggerFactory.java:417) at org.slf4j.LoggerFactory.getLogger(LoggerFactory.java:362) at org.slf4j.LoggerFactory.getLogger(LoggerFactory.java:388) at com.vivo.lucy.LockTest.<clinit>(LockTest.java:11) at com.vivo.lucy.Main.main(Main.java:7) Caused by: java.lang.ClassNotFoundException: ch.qos.logback.core.joran.spi.JoranException
-
上网百度以后,发现还需要添加
logback-core
对应的jar到lib
目录 -
其对应的maven依赖如下,可以到mvnrepository下载对应的jar
<dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-core</artifactId> <version>1.2.3</version> </dependency>
-
原因: 使用maven项目时,
logback-classic
依赖logback-core
,会自动引入该jar包。如果非maven项目,则需要手动引入才行