背景
要实现一个拦截器,确保每次请求线程的所有日志的日志戳唯一。
解决方法?
1.进控制器方法的时候,删除日志戳
2.第一次打印日志的时候,设置日志戳
3.从第二次打印日志开始,用第一次的日志戳
4.控制器方法结束的时候,删除日志戳
基于拦截器实现,关于删除日志戳和设置日志戳,这个需要自定义日志类,拦截器只是调用自定义日志类的方法去删除日志戳和设置日志戳。本文只讲拦截器,忽略自定义日志类。
拦截器介绍
和servlet的filter过滤器作用一样,只不过到了spring里名字就叫拦截器interceptor,但是作用一样,而且生命周期也一样,就是进入方法之前、进入方法之后,做一些统一操作。
实现
实现类
package com.xxx.payment.intercepter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import xxx.log.logback.layout.converter.LogPreFixConverter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
/**
* 日志戳拦截器,作用是确保每次请求的线程的日志戳唯一
*
* @author gzh
* @createTime 2021/2/2 9:37 AM
*/
public class LogPreInterceptor implements HandlerInterceptor {
public static final Logger log = LoggerFactory.getLogger(LogPreInterceptor.class);
/**
* 进入控制器的方法之后,立即删除日志戳。然后第一次打印日志的时候,会设置随机日志戳。从第二次打印日志开始,用第一次设置的日志戳。
*
* @param request
* @param response
* @param handler
* @return
* @throws Exception
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
LogPreFixConverter.resetLogPreFix();
return true;
}
/**
* 控制器的方法结束之后,删除日志戳(postHandle()方法是Controller方法正常返回后才执行)
*
* @param request
* @param response
* @param handler
* @param modelAndView
* @throws Exception
*/
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
// LogPreFixConverter.resetLogPreFix();
}
/**
* 控制器的方法结束之后,删除日志戳(无论Controller方法是否抛异常都会执行afterCompletion方法)
*
* @param request
* @param response
* @param handler
* @param ex
* @throws Exception
*/
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response,
Object handler, Exception ex) throws Exception {
LogPreFixConverter.resetLogPreFix();
}
}
配置
<!-- 日志戳拦截器-->
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**/*.do"/>
<bean class="com.xxx.payment.intercepter.LogPreInterceptor"></bean>
</mvc:interceptor>
</mvc:interceptors>
过滤请求路径说明
1.匹配任意目录路径
/**
2.匹配指定后缀路径
/**/*.do
参考
AntPathMatcher
This is a path pattern that used in Apache ant, spring team implement it and use it throughout the framework.
The mapping matches URLs using the following rules:
? matches one character //?,匹配任意单个字符
* matches zero or more characters //*,匹配0或多个字符
** matches zero or more 'directories' in a path //**,匹配0多多个目录
Some examples:
com/t?st.jsp - matches com/test.jsp but also com/tast.jsp or com/txst.jsp
com/*.jsp - matches all .jsp files in the com directory
com/**/test.jsp - matches all test.jsp files underneath the com path
org/springframework/**/*.jsp - matches all .jsp files underneath the org/springframework path
org/**/servlet/bla.jsp - matches org/springframework/servlet/bla.jsp but also org/springframework/testing/servlet/bla.jsp and org/servlet/bla.jsp
opensourceforgeeks.blogspot.com/2016/01/dif…
方法调用栈
preHandle:32, LogPreInterceptor (com.xxx.payment.intercepter) //自定义拦截器
applyPreHandle:133, HandlerExecutionChain (org.springframework.web.servlet)
doDispatch:962, DispatcherServlet (org.springframework.web.servlet) //spring mvc请求转发类
doService:901, DispatcherServlet (org.springframework.web.servlet)
processRequest:970, FrameworkServlet (org.springframework.web.servlet)
doGet:861, FrameworkServlet (org.springframework.web.servlet)
service:621, HttpServlet (javax.servlet.http)
service:846, FrameworkServlet (org.springframework.web.servlet)
service:728, HttpServlet (javax.servlet.http)
internalDoFilter:303, ApplicationFilterChain (org.apache.catalina.core)
doFilter:208, ApplicationFilterChain (org.apache.catalina.core)
doFilter:52, WsFilter (org.apache.tomcat.websocket.server)
internalDoFilter:241, ApplicationFilterChain (org.apache.catalina.core)
doFilter:208, ApplicationFilterChain (org.apache.catalina.core)
handle:438, CatFilter$Context (com.dianping.cat.servlet)
handle:235, CatFilter$CatHandler$3 (com.dianping.cat.servlet)
handle:436, CatFilter$Context (com.dianping.cat.servlet)
handle:328, CatFilter$CatHandler$4 (com.dianping.cat.servlet)
handle:436, CatFilter$Context (com.dianping.cat.servlet)
handle:218, CatFilter$CatHandler$2 (com.dianping.cat.servlet)
handle:436, CatFilter$Context (com.dianping.cat.servlet)
handle:127, CatFilter$CatHandler$1 (com.dianping.cat.servlet)
handle:436, CatFilter$Context (com.dianping.cat.servlet)
doFilter:65, CatFilter (com.dianping.cat.servlet)
internalDoFilter:241, ApplicationFilterChain (org.apache.catalina.core)
doFilter:208, ApplicationFilterChain (org.apache.catalina.core)
doFilter:31, EncodingFilter (hikefa.core.web.filter)
internalDoFilter:241, ApplicationFilterChain (org.apache.catalina.core)
doFilter:208, ApplicationFilterChain (org.apache.catalina.core)
invoke:219, StandardWrapperValve (org.apache.catalina.core)
invoke:110, StandardContextValve (org.apache.catalina.core)
invoke:444, AuthenticatorBase (org.apache.catalina.authenticator)
invoke:169, StandardHostValve (org.apache.catalina.core)
invoke:104, ErrorReportValve (org.apache.catalina.valves)
invoke:1025, AccessLogValve (org.apache.catalina.valves)
invoke:116, StandardEngineValve (org.apache.catalina.core)
service:445, CoyoteAdapter (org.apache.catalina.connector)
process:1137, AbstractHttp11Processor (org.apache.coyote.http11)
process:637, AbstractProtocol$AbstractConnectionHandler (org.apache.coyote)
run:319, JIoEndpoint$SocketProcessor (org.apache.tomcat.util.net)
runWorker:1149, ThreadPoolExecutor (java.util.concurrent)
run:624, ThreadPoolExecutor$Worker (java.util.concurrent)
run:61, TaskThread$WrappingRunnable (org.apache.tomcat.util.threads)
run:748, Thread (java.lang)