traceId在filter还是interceptor中处理

traceId在链路监控中是很重要的组成部分,在实际项目中,traceId处理可以在filter中处理,也可以在interceptor中处理。

本文重点说明下他们的区别是什么?以及spring对fitler的增强。

1、filter与interceptor的执行顺序

2、spring的OncePerRequestFilter

执行顺序

注册了两个fitler和一个interceptor

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
@Override
public void addInterceptors(InterceptorRegistry registry) {

registry.addInterceptor(new SelfInterceptor());
}

@Bean
public FilterRegistrationBean registerSecondFilter() {
FilterRegistrationBean<SecondFilter> registration = new FilterRegistrationBean<>();
registration.setFilter(new SecondFilter());
registration.addUrlPatterns("/*");
registration.setName("SecondFilter");
registration.setOrder(Ordered.HIGHEST_PRECEDENCE + 1);
return registration;
}

@Bean
public FilterRegistrationBean registerTraceIdFilter() {
FilterRegistrationBean<TraceIdFilter> registration = new FilterRegistrationBean<>();
registration.setFilter(new TraceIdFilter());
registration.addUrlPatterns("/*");
registration.setName("traceIdFilter");
registration.setOrder(Ordered.HIGHEST_PRECEDENCE);
return registration;
}

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接口。这是一个比较稳妥的选择

Ways to add Servlet Filters in Spring Boot

公众号:码农戏码
欢迎关注微信公众号『码农戏码』