基于spring boot 和MDC实现 同一笔记录的日志跟踪实现--1.filter
同一个项目中,一般包含controller/servlet、service、dao等。1笔记录的日志贯穿于controller、service、dao中,在并发情况下,那如何找出该笔日志?
可通过以下三种方式实现:
1、filter:依赖servlet容器
2、Interceptor:依赖spring
3、AOP:spring boot中,不能拦截servlet(我试过的,但可能也行)
以下时filter的实现。
首先,包结构:
代码实现:
logback.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="false">
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%X{requestId}] %p | %logger{20}.%M:%L - %m%n</pattern>
</encoder>
</appender>
<!-- TRACE < DEBUG < INFO < WARN < ERROR -->
<root level="INFO">
<appender-ref ref="console"/>
</root>
</configuration>
MdcLogEnhancerFilter
package com.ebc.slf4j.mdc.filter; import java.io.IOException; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import org.slf4j.MDC; import org.springframework.stereotype.Component; import cn.hutool.core.lang.Console; import cn.hutool.core.util.IdUtil; @Component public class MdcLogEnhancerFilter implements Filter { @Override public void destroy() { } @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { MDC.put("requestId", IdUtil.objectId()); filterChain.doFilter(servletRequest, servletResponse); MDC.remove("requestId");//否则内存溢出 //Console.log("======{}",MDC.get("requestId"));//输出null } }
Application
package com.ebc.slf4j.mdc; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.web.servlet.ServletComponentScan; @SpringBootApplication @ServletComponentScan(basePackages="com.ebc.slf4j.mdc.servlet") public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } }
下边是业务类
M2Servlet
package com.ebc.slf4j.mdc.servlet; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import lombok.extern.slf4j.Slf4j; import org.springframework.web.context.WebApplicationContext; import org.springframework.web.context.support.WebApplicationContextUtils; import com.ebc.slf4j.mdc.service.WelcomeService; @WebServlet("/M2Servlet") @Slf4j public class M2Servlet extends HttpServlet { private static final long serialVersionUID = 1L; protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { log.info("进入了servlet"); WebApplicationContext wac = WebApplicationContextUtils.getRequiredWebApplicationContext(getServletContext()); WelcomeService welcomeService = (WelcomeService) wac.getBean("welcomeService"); String reStr = welcomeService.exec("遥远2"); log.info("service返回:{}",reStr); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doGet(request, response); } }
WelcomeService
package com.ebc.slf4j.mdc.service; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; @Service @Slf4j public class WelcomeService { public String exec(String name) { log.info("service接收到:{}",name); return "hello "+name; } }
执行:http://localhost:8080/M2Servlet
结果:
2019-01-22 11:22:03.900 [5c468c5bcbb014209e2ea828] INFO | c.e.s.m.s.M2Servlet.doGet:20 - 进入了servlet 2019-01-22 11:22:03.900 [5c468c5bcbb014209e2ea828] INFO | c.e.s.m.s.WelcomeService.exec:11 - service接收到:遥远2 2019-01-22 11:22:03.900 [5c468c5bcbb014209e2ea828] INFO | c.e.s.m.s.M2Servlet.doGet:24 - service返回:hello 遥远2