traceId在链路监控中是很重要的组成部分,在实际项目中,traceId处理可以在filter中处理,也可以在interceptor中处理。
本文重点说明下他们的区别是什么?以及spring对fitler的增强。
1、filter与interceptor的执行顺序
2、spring的OncePerRequestFilter
执行顺序
注册了两个fitler和一个interceptor
1 | @Override |
1、Filter:与Spring 无关,基于Servlet, 可以获取request 和 response,但是具体处理方法及相关参数获取不到;
2、Interceptor:与Spring相关,可以获取request 和 response 以及具体处理方法,但是获取不到具体方法参数的值;
3、Aspect: 与Spring相关,不可获取request和response , 可以获取具体方法及具体方法参数的值;
OncePerRequestFilter
Filter base class that aims to guarantee a single execution per request dispatch, on any servlet container. It provides a doFilterInternal method with HttpServletRequest and HttpServletResponse arguments.
As of Servlet 3.0, a filter may be invoked as part of a REQUEST or ASYNC dispatches that occur in separate threads. A filter can be configured in web.xml whether it should be involved in async dispatches. However, in some cases servlet containers assume different default configuration. Therefore sub-classes can override the method shouldNotFilterAsyncDispatch() to declare statically if they should indeed be invoked, once, during both types of dispatches in order to provide thread initialization, logging, security, and so on. This mechanism complements and does not replace the need to configure a filter in web.xml with dispatcher types.
简单的说就是去适配了不同的web容器,以及对异步请求,也只过滤一次的需求。另外打个比方:如:servlet2.3与servlet2.4也有一定差异:
在servlet2.3中,Filter会经过一切请求,包括服务器内部使用的forward转发请求和<%@ include file=”/login.jsp”%>的情况
servlet2.4中的Filter默认情况下只过滤外部提交的请求,forward和include这些内部转发都不会被过滤,
因此此处我有个建议:我们若是在Spring环境下使用Filter的话,个人建议继承OncePerRequestFilter吧,而不是直接实现Filter接口。这是一个比较稳妥的选择