上一章我们介绍了spring boot的基本配置, 这一章我们就说说spring boot的日志.
spring boot 封装了多种日志输出的库, 下面以最主流的slf4j做例子, 聊聊spring boot的日志配置的方法和技巧.
1.引入POM依赖
由于spring boot 已经将日志模块放置到基础框架里了,所以我们不需要在pom引入日志的模块了。
2.在YML中引入logback配置
首先在resources根目录下新建一个 logback-spring.xml文件, 这个文件就是slf4j的日志配置文件, spring boot 会默认查找resources目录下的logback-spring.xml配置文件,所以我们不需要在spring boot的配置文件中添加slf4j的配置文件路径. 但是如果slf4j的配置文件没有放置到resources目录下的时候,我们只需要在spring boot的配置文件中新增下面配置即可,在YML文件中添加如下代码:
logging:
config: classpath:logback-spring.xml
3.配置基础的logback文件
在上面的logback-spring.xml添加如下代码:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<contextName>模块名称</contextName>
<!-- spring boot 自带的日志配置 只有控制台输出 -->
<include resource="org/springframework/boot/logging/logback/base.xml" />
<!-- 文件输出格式 -->
<property name="PATTERN" value="%-12(%d{yyyy-MM-dd HH:mm:ss.SSS}) [%contextName] %-5level --- [%thread] %c : %msg%n" />
<property name="MODEL_NAME" value="lesson" />
<!-- 文件路径 -->
<property name="DEV_FILE_PATH" value="e:/logs/${MODEL_NAME}/" />
<!-- 每天产生一个文件 -->
<appender name="DEV_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 文件路径 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 文件名称 -->
<fileNamePattern>${DEV_FILE_PATH}/${MODEL_NAME}.%d{yyyy-MM-dd}.log</fileNamePattern>
<!-- 文件最大保存历史数量 -->
<MaxHistory>100</MaxHistory>
</rollingPolicy>
<!-- 展示格式-->
<layout class="ch.qos.logback.classic.PatternLayout">
<pattern>${PATTERN}</pattern>
</layout>
</appender>
<!-- 指定这个目录下的日志输出级别为DEBUG -->
<logger name="org.learning" level="DEBUG" />
<!-- 基础的日志级别 -->
<root level="info">
<appender-ref ref="DEV_FILE" />
</root>
</configuration>
分析一下上面配置的关键点:
<include resource="org/springframework/boot/logging/logback/base.xml" />
上面这段配置是引入了spring boot的基础配置,有了它,我们就不用再定义开发过程中的控制台输入.
<property name="PATTERN" value="%-12(%d{yyyy-MM-dd HH:mm:ss.SSS}) [%contextName] %-5level --- [%thread] %c : %msg%n" />
上面这段配置可以定义各种日志输出的格式的变量
<property name="MODEL_NAME" value="lesson" />
<!-- 文件路径 -->
<property name="DEV_FILE_PATH" value="e:/logs/${MODEL_NAME}/" />
上面这段配置定义日志输出路径的变量
<!-- 每天产生一个文件 -->
<appender name="DEV_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 文件路径 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 文件名称 -->
<fileNamePattern>${DEV_FILE_PATH}/${MODEL_NAME}.%d{yyyy-MM-dd}.log</fileNamePattern>
<!-- 文件最大保存历史数量 -->
<MaxHistory>100</MaxHistory>
</rollingPolicy>
<!-- 展示格式-->
<layout class="ch.qos.logback.classic.PatternLayout">
<pattern>${PATTERN}</pattern>
</layout>
</appender>
最后在这个主appender中引入上面的变量,完成了简单日志配置.
4.用一个demo验证日志配置
我们在DemoController中定义一个Logger,然后尝试输出一个info,看看是否在我们设定的文件目录中产生了对应的日志文件. 代码如下:
@RestController
public class DemoController {
private final Logger log = LoggerFactory.getLogger(this.getClass());
@RequestMapping("/")
String home() {
log.info("Hello World!");
return "Hello World!";
}
@RequestMapping("/hello/{myName}")
String index(@PathVariable String myName) {
log.error("Hello " + myName + "!!!");
return "Hello " + myName + "!!!";
}
}
我们运行demo程序之后,会发现info和error输出到一个文件里了,这样很不直观,而且在做日志收集时也很麻烦.
5.以日志级别来分文件输出日志
针对上面的问题,我们可以在之前的日志配置中做如下修改就可以将 ERROR和其他的区分文件输出了.
首先在上面logback-spring.xml的“DEV_FILE”的appender中增加一个过滤器,将ERROR的日志过滤掉,代码如下:
<!-- 这里配置个过滤器 遇到ERROR就禁止 (第一种过滤方式)-->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<!--过滤 Error-->
<level>ERROR</level>
<!--匹配到就过滤掉-->
<onMatch>DENY</onMatch>
<!--没有匹配到允许-->
<onMismatch>ACCEPT</onMismatch>
</filter>
接着新增一个appender 名字叫DEV_ERROR_FILE,给这个appender换个输出的日志文件,并且新增一个过滤器,只保留ERROR级别日志输出,代码如下:
<!-- 这里配置个过滤器 只允许ERROR的 (第二种过滤方式)-->
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>Error</level>
</filter>
这样我们就完成了按照日志级别分文件输出了, 全部的logback-spring.xml配置如下:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<contextName>模块名称</contextName>
<!-- spring boot 自带的日志配置 只有控制台输出 -->
<include resource="org/springframework/boot/logging/logback/base.xml" />
<!-- 文件输出格式 -->
<property name="PATTERN" value="%-12(%d{yyyy-MM-dd HH:mm:ss.SSS}) [%contextName] %-5level --- [%thread] %c : %msg%n" />
<property name="MODEL_NAME" value="lesson" />
<!-- 文件路径 -->
<property name="DEV_FILE_PATH" value="e:/logs/${MODEL_NAME}/" />
<!-- 每天产生一个文件 -->
<appender name="DEV_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 这里配置个过滤器 遇到ERROR就禁止 (第一种过滤方式)-->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<!--过滤 Error-->
<level>ERROR</level>
<!--匹配到就过滤掉-->
<onMatch>DENY</onMatch>
<!--没有匹配到允许-->
<onMismatch>ACCEPT</onMismatch>
</filter>
<!-- 文件路径 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 文件名称 -->
<fileNamePattern>${DEV_FILE_PATH}/${MODEL_NAME}.%d{yyyy-MM-dd}.log</fileNamePattern>
<!-- 文件最大保存历史数量 -->
<MaxHistory>100</MaxHistory>
</rollingPolicy>
<!-- 展示格式-->
<layout class="ch.qos.logback.classic.PatternLayout">
<pattern>${PATTERN}</pattern>
</layout>
</appender>
<!-- 每天产生一个文件 ERROR的 -->
<appender name="DEV_ERROR_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 这里配置个过滤器 只允许ERROR的 (第二种过滤方式)-->
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>Error</level>
</filter>
<!-- 文件路径 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 文件名称 -->
<fileNamePattern>${PRO_FILE_PATH}/error.${MODEL_NAME}.%d{yyyy-MM-dd}.log</fileNamePattern>
<!-- 文件最大保存历史数量 -->
<MaxHistory>100</MaxHistory>
</rollingPolicy>
<!--展示格式 -->
<layout class="ch.qos.logback.classic.PatternLayout">
<pattern>${PATTERN}</pattern>
</layout>
</appender>
<!-- 指定这个目录下的日志输出级别为DEBUG -->
<logger name="org.learning" level="DEBUG" />
<!-- 基础的日志级别 -->
<root level="info">
<appender-ref ref="DEV_FILE" />
</root>
</configuration>
6.依据环境区分不同的日志配置
在实际项目中, 我们开发,测试的环境,日志输出往往也采用不同的配置, 我们也可以根据spring boot的 profiles 来确定环境并区分不同的配置. 只需要在appender加入到 <springProfile name="dev"> 中即可. name表示环境标识. 完整的配置如下:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<contextName>模块名称</contextName>
<!-- spring boot 自带的日志配置 只有控制台输出 -->
<include resource="org/springframework/boot/logging/logback/base.xml" />
<!-- 文件输出格式 -->
<property name="PATTERN" value="%-12(%d{yyyy-MM-dd HH:mm:ss.SSS}) [%contextName] %-5level --- [%thread] %c : %msg%n" />
<property name="MODEL_NAME" value="lesson" />
<!-- 文件路径 -->
<property name="DEV_FILE_PATH" value="e:/logs/${MODEL_NAME}/" />
<property name="PRO_FILE_PATH" value="e:/pro_logs/${MODEL_NAME}/" />
<!-- 开发环境 -->
<springProfile name="dev">
<!-- 每天产生一个文件 -->
<appender name="DEV_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 文件路径 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 文件名称 -->
<fileNamePattern>${DEV_FILE_PATH}/${MODEL_NAME}.%d{yyyy-MM-dd}.log</fileNamePattern>
<!-- 文件最大保存历史数量 -->
<MaxHistory>100</MaxHistory>
</rollingPolicy>
<!-- 展示格式-->
<layout class="ch.qos.logback.classic.PatternLayout">
<pattern>${PATTERN}</pattern>
</layout>
</appender>
<!-- 指定这个目录下的日志输出级别为DEBUG -->
<logger name="org.learning" level="DEBUG" />
<!-- 基础的日志级别 -->
<root level="info">
<appender-ref ref="DEV_FILE" />
<appender-ref ref="CONSOLE" />
</root>
</springProfile>
<!-- 生产 环境 -->
<springProfile name="pro">
<!-- 每天产生一个文件 INFO的 -->
<appender name="PRO_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 这里配置个过滤器 遇到ERROR就禁止 (第一种过滤方式)-->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<!--过滤 Error-->
<level>ERROR</level>
<!--匹配到就过滤掉-->
<onMatch>DENY</onMatch>
<!--没有匹配到允许-->
<onMismatch>ACCEPT</onMismatch>
</filter>
<!-- 文件路径 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 文件名称 -->
<fileNamePattern>${PRO_FILE_PATH}/${MODEL_NAME}.%d{yyyy-MM-dd}.log</fileNamePattern>
<!-- 文件最大保存历史数量 -->
<MaxHistory>100</MaxHistory>
</rollingPolicy>
<!--展示格式 -->
<layout class="ch.qos.logback.classic.PatternLayout">
<pattern>${PATTERN}</pattern>
</layout>
</appender>
<!-- 每天产生一个文件 ERROR的 -->
<appender name="PRO_ERROR_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 这里配置个过滤器 只允许ERROR的 (第二种过滤方式)-->
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>Error</level>
</filter>
<!-- 文件路径 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 文件名称 -->
<fileNamePattern>${PRO_FILE_PATH}/error.${MODEL_NAME}.%d{yyyy-MM-dd}.log</fileNamePattern>
<!-- 文件最大保存历史数量 -->
<MaxHistory>100</MaxHistory>
</rollingPolicy>
<!--展示格式 -->
<layout class="ch.qos.logback.classic.PatternLayout">
<pattern>${PATTERN}</pattern>
</layout>
</appender>
<root level="info">
<appender-ref ref="PRO_FILE" />
</root>
<root level="error">
<appender-ref ref="PRO_ERROR_FILE" />
</root>
</springProfile>
</configuration>
在上面的例子中,标红的代码分别标识了开发环境和生产环境的不同日志配置. 当我们更改spring boot的 profiles配置时, 日志配置也会跟着改变。
7.用lombok简化日志对象引入代码
在使用slf4j时, 每个需要日志输出的类都需要加入,就像下面这段代码:
private final Logger log = LoggerFactory.getLogger(this.getClass());
这样很繁琐, 我们可以使用lombok来解决这个问题,只需要在代码中的类头上加入@Slf4j注释, 我们就可以使用log了。
(如对lombok不太了解的可以看看我写的lombok介绍和配置 )
代码如下:
@Slf4j
@RestController
public class DemoController {
@RequestMapping("/")
String home() {
log.info("Hello World!");
return "Hello World!";
}
@RequestMapping("/hello/{myName}")
String index(@PathVariable String myName) {
log.error("Hello " + myName + "!!!");
return "Hello " + myName + "!!!";
}
}
8.修改默认的spring boot 启动logo
spring boot的日志总是会带一个Banner,就是下面这个:
首先我们尝试把这个logo去掉。
将原来的
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
替换为:
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication application = new SpringApplication(Application.class);
application.setBannerMode(Banner.Mode.OFF);
application.run(args);
}
}
运行一下,发现logo没有了
我们也可以对这个logo进行自定义,实现我们自己的logo,做法很简单,不用修改Application.java ,只需要在resources目录下新建一个banner.txt文件,在这里输入你想要的内容,那启动项目的时候就会输出了.
好了,关于spring boot 日志设置的内容就讲到这了.
本章结束
下一章将介绍spring boot 的单元测试.