filter执行先后问题_Filter执行顺序不可控制问题

在SpringBoot项目中,为实现API接口的统一解密和加密,选择了使用Servlet过滤器Filter。遇到问题:LogFilter无法在解密Filter后执行。通过分析发现,Filter的执行顺序取决于在filterChain的Filters列表顺序。解决方案是使用@Order和@Component注解来控制Filter的执行顺序,避免使用@ServletComponentScan或其扫描范围包含需要排序的Filter。
摘要由CSDN通过智能技术生成

正所谓前人栽树,后人乘凉。

感谢Huxpro提供的博客模板

1、问题来源

使用SpringBoot 搭建api项目时,需要对api接口进行统一的解密和加密。

加密解密时机:1、SpringMVC 套餐 @ControllerAdvice 、 HttpInputMessage、RequestBodyAdvice

2、使用HttpMessageConverter

3、Servlet Api 过滤器 Filter

经过测试发现:[email protected],并且对请求Content-Type 进行一些配置,可以实现但是并不友好;

[email protected],Content-Type则在转换器中支持所有类型即可;另外从下面的转换方法的方法签名可以看出,需要返回具体的对象,若controller中入参的对象结构比较复杂,返回这个对象会有一定的成本。本着开发时能交给框架就交给框架的懒人原则 :) protected Object readInternal(Class> clazz, HttpInputMessage inputMessage)

方案3 众所周知是一定可以实现的,并且对请求的后续mvc的处理流程完全透明,是比较理想的方案。

最后选择方案3

好了,已经偏题了

项目中同时也是使用了Filter做请求log,于是出现了LogFilter中log不到请求参数的问题,理想状态是解密的Filter第一个被执行,后续再执行其他的Filter。

2、面向Google编程

google到排序的方法:1、根据filter名自然排序的顺序执行(测试不行)

2、xml配置文件中配置filter的先后顺序(springboot还写xml?)

3、使用FilterRegistrationBean向Spring容器注册bean,同时指定FilterRegistrationBean的order值(亲测可行,但每个filter都需要写一个FilterRegistrationBean,不优雅,嫌弃)

4、使用注解@ServletComponentScan(亲测不行,原因后续会提到)

google没找到满意的解决方法,还是自己看下为什么不能排序吧。

3、解决方法

这里写下处理方法:

添加@Order、@Component即可,其他不需要处理。并且不能使用@ServletComponentScan,或者@ServletComponentScan的扫描范围不能包括想要排序的Filter

4、排序分析

1、filter执行链执行方式

a. 通过断点进去filterChain#doFilter方法

public void doFilter(ServletRequest request, ServletResponse response)

throws IOException, ServletException {

if( Globals.IS_SECURITY_ENABLED ) {

// ...

internalDoFilter(req,res);

// ...

} else {

internalDoFilter(request,response);

}

}

b. 跟踪进入 internalDoFilter 可以看到如下关键代码

private void internalDoFilter(ServletRequest request, ServletResponse response)

throws IOException, ServletException {

// Call the next filter if there is one

if (pos < n) {

// 获取并偏移下标

ApplicationFilterConfig filterConfig = filters[pos++];

try {

Filter filter = filterConfig.getFilter();

// ...

// 执行过滤器逻辑(递归)

filter.doFilter(request, response, this);

}

// ...

// 所有过滤器前置执行结束,执行servlet

servlet.service(request, response);

// 执行servlet执行结束,递归出口

// ...

这里看到filters[pos++],这是Filter责任链模式实现的核心,从filterChain内维护的filter列表依次获取并执行。Servlet的Filter责任链模式是通过filter列表和递归调用实现的。

于是我们得到一个结论:filter的执行顺序取决与filter在filterChain的Filters列表的顺序,继续跟进Filters列表创建

2、Filters列表的创建

找到ApplicationFilterChain#addFilter方法,filters由外部添加,断点继续往找;

找到ApplicationFilterFactory#createFilterChain方法,在这里创建处理链,如下:

public static ApplicationFilterChain createFilterChain(ServletRequest request,

Wrapper wrapper, Servlet servlet) {

// ...

// 创建处理链

filterChain = new ApplicationFilterChain();

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值