log4j的MDC配合Spring-mvc进行日志追踪

这篇博客介绍了如何利用log4j的MDC(Mapped Diagnostic Context)配合Spring-mvc实现请求日志追踪。首先创建一个日志工具类设置和移除MDC的序列值,然后定义一个拦截器在请求开始时插入序列值,并在结束时移除。在spring-mvc.xml中配置拦截器,并在log4j配置文件中定制日志输出格式以显示序列值。

跳槽后,接到的第一个需求是在项目里给每个请求加一个唯一字符串,能够通过日志追踪到请求的整个流程。一个很简单的需求,上网查找资料考虑半天后,决定用log4j的MDC进行请求追踪。(logback和slf4j也是支持MDC)
因为我们项目是Spring-mvc和mybatis搭建的,页面请求都是直接转发到我们的controller层,所以考虑使用Spring的拦截器(interceptor)。inteceptor拦截所有请求,在preHandle中给请求赋唯一序列值,在afterCompletion中remove MDC的序列值。然后再log4j的配置文件中使用%X{logkey}输出请求的序列值。
另外唯一序列值我们采用的是随机数Math.abs(random.nextLong()),当然也可以采用UUID或者其他的都是OK的。
说了这么多,接下来就直接上代码吧。

第一步:新建一个日志工具类

import org.apache.log4j.MDC;
import java.util.Random;

/**

  • @description 日志工具类
    *@author jerry
    @date 2018-08
    /
    public class LoggerTools {
    /

    *@description 日志序列号
    *@author jerry
    @date 2018-08-03
    /
    public static void logger(){
    Random random=new Random();
    MDC.put(“logkey”,Math.abs(random.nextLong()));
    }
    /
    • @description 删除本次请求的日志序列号
    • @author jerry
    • @date 2018-08
      */
      pub
### 配置 Log4j2 使用 YAML 格式并记录用户名 在 Spring Boot 2.6.6 中,虽然 Log4j2 的默认配置文件格式是 XML,但可以通过引入额外依赖支持 YAML 格式的日志配置。同时,结合 MDC(Mapped Diagnostic Context)机制,可以在日志中动态记录当前用户名信息。 #### 1. 添加依赖支持 YAML 配置 Log4j2 原生不支持 YAML 配置,因此需要引入额外的依赖来解析 YAML 格式的日志配置文件。在 `pom.xml` 中添加以下依赖: ```xml <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> </dependency> <dependency> <groupId>com.fasterxml.jackson.dataformat</groupId> <artifactId>jackson-dataformat-yaml</artifactId> </dependency> ``` 这样可以确保 Spring Boot 能够正确加载 `log4j2-spring.yml` 文件作为日志配置来源 [^4]。 #### 2. 创建 `log4j2-spring.yml` 配置文件 在 `src/main/resources` 目录下创建 `log4j2-spring.yml` 文件,内容如下: ```yaml configuration: status: warn appenders: Console: name: Console target: SYSTEM_OUT PatternLayout: pattern: "%d{yyyy-MM-dd HH:mm:ss} [%t] %-5p %c{36} - %X{username} - %m%n" loggers: root: level: info appender-ref: - ref: Console ``` 上述配置中,`%X{username}` 表示从 MDC 中提取 `username` 字段并写入日志输出中 [^1]。 #### 3. 使用拦截器将用户名写入 MDC 为了在日志中记录用户名,需要在请求处理过程中将用户名写入 MDC。可以通过实现 `HandlerInterceptor` 来完成: ```java import org.slf4j.MDC; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.web.servlet.HandlerInterceptor; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class UserMdcInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) { String username = "anonymous"; if (SecurityContextHolder.getContext().getAuthentication() != null && SecurityContextHolder.getContext().getAuthentication().isAuthenticated()) { username = SecurityContextHolder.getContext().getAuthentication().getName(); } MDC.put("username", username); return true; } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) { MDC.clear(); } } ``` #### 4. 注册拦截器 通过配置类将拦截器注册到 Spring MVC 的请求处理链中: ```java import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @Configuration public class WebConfig implements WebMvcConfigurer { @Autowired private UserMdcInterceptor userMdcInterceptor; @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(userMdcInterceptor); } } ``` #### 5. 验证日志输出 启动应用后,访问任意接口,日志中将包含当前用户的用户名信息,例如: ``` 2023-10-01 12:34:56 [http-nio-8080-exec-1] INFO com.example.controller.HelloController - admin - helloworld, admin ``` 上述输出中,`admin` 即为当前登录用户名称,通过 MDC 注入到日志模板中 [^2]。 ### 注意事项 - 确保在请求结束时调用 `MDC.clear()`,以避免线程复用导致的上下文污染。 - 若未使用 Spring Security,需根据实际认证机制获取用户名。 - YAML 格式配置 Log4j2 需要 Jackson 库支持,否则无法正确加载配置 [^4]。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值