SpringBoot版本:2.1.1.RELEASE
当我们在进行web开发时,经常会用到各种各样的框架,常见的有spring、mybatis、hibernate等等,每个框架底层都有着自己的日志实现,那么难道我们在进行开发时,还需要在使用不同框架的时候使用其对应的API嘛?这将会大大增加我们的开发成本。还有如果我们在后期对项目进行二次开发时,如果要换日志框架,难道还得需要把原本的日志API全部替换掉吗?
此时我们在想,如果每个日志框架能像我们平时开发时面向接口开发多好,所有的日志框架都统一API,但是实现可以各不相同,这样就能解决上面所说到的问题了。
而这种思想模式,我们可以称之为门面模式。顾名思义,就是我们面向开发者的API是相同的,但是实现层还是由每个框架来决定的。
所以,SpringBoot帮我们已经做好了。它的日志门面选用的就是 SLF4J,而日志实现选用的是Logback。
一、SLF4J 的使用
从 SLF4J官网上,我们可以看到详细示例,例如:
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");
}
}
从上图中,我们可以看到,如果log4j和JUL想使用SLF4J作为日志门面,还需要一层适配层。例如,如果要使用 SLF4J 作为 log4j 的门面,就必须引入 slf4j-api.jar 和 slf-4j-log412.jar 的依赖。其中 slf-4j-log412.jar 就是用来做适配的,我们在调用slf4j API 的时候其实是在调用 slf-4j-log412.jar 中的API,而 slf-4j-log412.jar 中的API执行的又是 log4j中的具体方法。
二、SpringBoot 中日志的使用
A.SpringBoot整合其他框架日志门面
我们知道,SpringBoot日志是使用SLF4J作为日志门面,但是其他框架肯定也有自己的日志门面,例如 Java Commons Logging ,Jboss Logging 等等,那么如果我想整个项目都使用SLF4j作为日志门面怎么办呢?
不用担心,SpringBoot已经帮我们做了一波偷梁换柱的操作。在没看SpringBoot如何实现之前,我们来看下面这张图:
通常,我们依赖的某些组件依赖于SLF4J以外的日志记录API。为了解决这种情况,SLF4J附带了几个桥接模块,这些模块将对log4j,JCL和java.util.logging API的调用重定向,就好像它们是对SLF4J API一样。
所以,我们可以总结一下如何让系统中所有的日志都统一到SLF4J:
- 将系统中其他的日志框架先排除出去
- 用中间包来代替原有的日志框架
- 导入slf4j其它的实现
当我们在构建SpringBoot项目时,引入了一层依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>2.1.1.RELEASE</version>
<scope>compile</scope>
</dependency>
这里面就会有一个日志启动器:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
<version>2.1.1.RELEASE</version>
<scope>compile</scope>
</dependency>
底层依赖关系:
可以看到,springboot底层默认是使用SLF4J+Logback 的方式记录日志,并且把其他的日志框架也替换成了SLF4J。当我们引入其他框架的时候,只需要把这个框架的默认日志依赖移除掉即可,SpringBoot能自动适配所有的日志。
B.SpringBoot 框架中日志的使用
1.默认配置
SpringBoot 默认帮我们配置好了日志
//记录器
Logger logger = LoggerFactory.getLogger(getClass());
@Test
public void contextLoads() {
//日志的级别;
//由低到高 trace<debug<info<warn<error
//可以调整输出的日志级别;日志就只会在这个级别以以后的高级别生效
logger.trace("这是trace日志...");
logger.debug("这是debug日志...");
//SpringBoot默认给我们使用的是info级别的,没有指定级别的就用SpringBoot默认规定的级别;root级别
logger.info("这是info日志...");
logger.warn("这是warn日志...");
logger.error("这是error日志...");
}
我们也可以在配置文件中修改日志的默认配置:
logging:
# 对指定的包调整日志的级别(trace、debug、info、warn、error)
level:
com:
van: warn
# 如果不指定路径,则在当前项目下生成springboot.log文件
# 如果指定路径,则在指定路径下生成springboot.log文件
file: springboot.log
# 在当前磁盘的根路径下创建spring文件夹和里面的log文件夹;使用 spring.log 作为默认文件
path: /spring/log
pattern:
# 在控制台指定格式输出日志
console:
# 在文件中指定格式输出
file:
2.指定配置
在项目类路径下放上每个日志框架的配置文件,SpringBoot就不会使用自己的默认配置了。下面的这个表格就是对应日志框架在SpringBoot中使用自己的配置文件符合规则的命名。
Logging System | Customization |
---|---|
Logback | logback-spring.xml , logback-spring.groovy , logback.xml or logback.groovy |
Log4j2 | log4j2-spring.xml or log4j2.xml |
JDK (Java Util Logging) | logging.properties |
最后附上一个常用的自定义日志配置文件(logback-spring.xml):
<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="false">
<!--定义日志文件的存储地址 勿在 LogBack 的配置中使用相对路径-->
<property name="LOG_HOME" value="/logs/log" />
<!-- 控制台输出 -->
<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>
<!-- 按照每天生成日志文件 -->
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!--日志文件输出的文件名-->
<FileNamePattern>${LOG_HOME}/swh.log.%d{yyyy-MM-dd}.log</FileNamePattern>
<!--日志文件保留天数-->
<MaxHistory>30</MaxHistory>
</rollingPolicy>
<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>
<!--日志文件最大的大小-->
<triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
<MaxFileSize>10MB</MaxFileSize>
</triggeringPolicy>
</appender>
<!--myibatis log configure -->
<logger name="com.apache.ibatis" level="TRACE"/>
<logger name="java.sql.Connection" level="DEBUG"/>
<logger name="java.sql.Statement" level="DEBUG"/>
<logger name="java.sql.PreparedStatement" level="DEBUG"/>
<!-- mybatis打印sql语句 -->
<logger name="com.van.springboot.dao" level="DEBUG"></logger>
<!-- 日志输出级别 -->
<root level="DEBUG">
<appender-ref ref="STDOUT" />
<appender-ref ref="FILE" />
</root>
</configuration>