SpringMVC:配置 Log

继续后端服务系列:

SpringMVC 配置 slf4j + log4j2。

log4j2参考了logback的一些优秀的设计,并且修复了一些问题,因此带来了一些重大的提升,主要有:

  1. 异常处理:在logback中,Appender中的异常不会被应用感知到,但是在log4j2中,提供了一些异常处理机制。
  2. 性能提升:log4j2相较于log4j 1和logback都具有很明显的性能提升。
  3. 自动重载配置:参考了logback的设计,提供自动刷新参数配置,可以动态的修改日志的级别而不需要重启应用。
  4. 无垃圾机制,log4j2在大部分情况下,都可以使用其设计的一套无垃圾机制,避免频繁的日志收集导致的jvm gc。

maven 依赖

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
<!-- start log -->
<!-- slf4j核心包-->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.30</version>
</dependency>

<!--slf4j对应log4j2的中间件,即桥接 -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
<version>2.13.1</version>
</dependency>

<!-- log4j2 -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.13.1</version>
</dependency>

<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-web</artifactId>
<version>2.13.1</version>
<scope>runtime</scope>
</dependency>

<!--log4j2 异步依赖-->
<dependency>
<groupId>com.lmax</groupId>
<artifactId>disruptor</artifactId>
<version>3.3.6</version>
</dependency>
<!-- end log -->

log4j2.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
<?xml version="1.0" encoding="UTF-8"?>
<configuration status="INFO" monitorInterval="30">

<properties>
<!-- 配置日志文件输出目录 -->
<Property name="log_dir">/tmp/logs/app</Property>
</properties>

<Appenders>
<Console name="CONSOLE" target="SYSTEM_OUT" follow="true">
<PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss:SSS}|%-5level|%thread|%c-%L| - %msg%n"/>
</Console>

<RollingFile name="ROLLING_FILE" fileName="${log_dir}/catalina.out"
filePattern="${log_dir}/catalina.%d{yyyy-MM-dd}.log.gz"
immediateFlush="false">
<Filters>
<ThresholdFilter level="INFO" onMatch="ACCEPT"/>
</Filters>
<PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss:SSS}|%-5level|%thread|%X{invokeNo}|%c-%L| - %msg%n"/>

<Policies>
<TimeBasedTriggeringPolicy modulate="true" interval="1"/>
</Policies>

</RollingFile>
</Appenders>
<Loggers>
<logger name="org.springframework" level="INFO"></logger>
<logger name="org.mybatis" level="INFO"></logger>
<AsyncRoot level="DEBUG" includeLocation="true">
<AppenderRef ref="CONSOLE"/>
<AppenderRef ref="ROLLING_FILE"/>
</AsyncRoot>
</Loggers>
</configuration>

web.xml 设置

增加

1
2
3
4
5
<context-param>
<param-name>log4jConfiguration</param-name>
<!-- 默认文件名log4j2.xml -->
<param-value>classpath:log4j2.xml</param-value>
</context-param>

Java 代码打日志

1
2
3
4
5
6
7
8
9
10
11
12
13
package com.tracenote.api.controller;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Controller;

@Slf4j
@Controller
public class HelloWorld {
@RequestMapping("/hello")
public String hello(){
log.info("~~~~~~~~~ hi ~~~~~~~~~");
return "helloworld";
}
}

这里使用了 lombok 注解 @Slf4j 来简化日志代码。

运行结果:

1
2
3
4
zhang$ tail -f catalina.out 
2020-11-16 09:12:26:889|INFO |qtp2083562754-31||com.tracenote.api.controller.HelloWorld-20| - ~~~~~~~~~ hi ~~~~~~~~~
2020-11-16 09:12:33:692|INFO |qtp2083562754-30||com.tracenote.api.controller.HelloWorld-20| - ~~~~~~~~~ hi ~~~~~~~~~
2020-11-16 09:12:37:012|INFO |qtp2083562754-30||com.tracenote.api.controller.HelloWorld-20| - ~~~~~~~~~ hi ~~~~~~~~~