为什么要用日志
记录关键信息,输出到文件中,方便排查问题,统计分析
日志框架介绍
日志 抽象层 | 特点 |
---|---|
JCL(Jakarta Commons Logging) | Spring选择JCL作为默认输出,特点:2014年已停止维护 |
SLF4J | Spring Boot 默认选择了 SLF4J |
jboss-logging | 特所场景使用 |
日志-实现层 | 特点 |
---|---|
jul(java.util.log) | java自带的日志实现层框架,功能简单 |
log4j | 性能低 |
logback | 是由log4j的作者设计完成的;log4j升级版 |
log4j2 | 新的日志框架 |
Spring框架选择了JCL作为默认日志输出,
而 Spring Boot 默认选择了 SLF4J 结合 LogBack
SLF4J的使用
开发时我们使用的时抽象层接口,而不是直接使用实现层
http://www.slf4j.org/manual.html
slf4j-api-1.7.28.jar
slf4j-simple-1.7.28.jar
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class HelloWorld {
public static void main(String[] args) {
Logger logger = LoggerFactory.getLogger(HelloWorld.class);
logger.info("Hello World");
}
}
为什么需要有Adaptation layer
应为当log4j,jul出现的时候,不知道会出现SLF4J这样的框架;
需要有Adaptation layer,去实现SLF4J接口,然后去调用log4j。
统一日志框架的使用
为什么要统一日志框架呢
A项目(slf4J + logback): Spring(commons logging)、Hibernate(jboss-logging)、
mybatis…
项目中依赖了不同的第三方jar,而他们选择的日志框架可能不尽相同;显然不利于我们使用
统一日志框架使用步骤归纳
- 排除系统中的其他日志框架
- 使用中间包替换要替换的日志框架
- 导入我们选择的SLF4J实现
SpringBoot的日志关系
1. 排除系统中的其他日志框架
我们知道spring-boot-starter-parent 对jar版本进行统一管理,我们看看它怎么管理日志的
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.0</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
spring-boot-starter-parent 依赖 spring-boot-dependencies
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.4.0</version>
</parent>
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-console</artifactId>
<version>${activemq.version}</version>
<exclusions>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>${httpclient.version}</version>
<exclusions>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
我们看到它排除了JCL
spring-boot-starter 依赖了 spring-boot-starter-logging;像spring-boot-starter-web,spring-boot-starter-test都依赖的spring-boot-starter
我们来看看spring-boot-starter-logging
<dependencies>
<!--引入了log4j,logback,log4j-over-slf4j,jul-to-slf4j 等到-->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-to-slf4j</artifactId>
<version>2.13.3</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jul-to-slf4j</artifactId>
<version>1.7.30</version>
<scope>compile</scope>
</dependency>
</dependencies>
log4j-to-slf4j (在 log4j 日志框架作者开发此框架的时候还没有想到使用日志抽象层进行开
发,因此出现了 log4j 向 slf4j 转换的工具),jul-to-slf4j ( Java 自带的日志框架转换为 slf4j).
也实现了第二部和第三步
由此可见SpringBoot底层使用SLF4J+LogBack记录日志,如果我们自行引入其他日志框架,需要排除其日志框架
Spring Boot 的日志使用
日志级别和格式
SpringBoot 默认日志级别为 INFO
默认的日志格式
%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n
# %d{yyyy-MM-dd HH:mm:ss.SSS} 时间
# %thread 线程名称 # %-5level 日志级别从左显示5个字符宽度
# %logger{50} 类名 # %msg%n 日志信息加换行
至于为什么 Spring Boot 的默认日志输出格式是这样?
我们可以在SpringBoot的源码中找到答案
自定义日志输出
# 日志配置
# 指定具体包的日志级别
logging.level.com.lagou=debug
# 控制台和日志文件输出格式
logging.pattern.console=%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n
logging.pattern.file=%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n
# 日志输出路径,默认文件
spring.log logging.file.path=spring.log
#logging.file.name=log.log
logging.file | logging.path | 例子 | 描述 |
---|---|---|---|
(没有) | (没有) | 仅控制台记录 | |
具体文件 | (没有) | my.log | 写入指定的日志文件,名称可以是精准位置或相对于当前目录 |
(没有) | 具体目录 | /var/log | 写入 spring.log 指定的目录,名称可 |
以是精确位置或相对于当前目录。
替换日志框架
如何将LogBack 改成Log4j2呢
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<artifactId>spring-boot-starter-logging</artifactId>
<groupId>org.springframework.boot</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>