Java过滤器链原理解析

在很多Java Web项目中我们会在web.xml中配置一些过滤器来拦截请求,比如下面解决乱码的编码过滤器:

<filter>
	<filter-name>encodingFilter</filter-name>
	<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
	<init-param>
		<param-name>encoding</param-name>
		<param-value>UTF-8</param-value>
	</init-param>
	<init-param>
		<param-name>forceEncoding</param-name>
		<param-value>true</param-value>
	</init-param>
	</filter>
<filter-mapping>
	<filter-name>encodingFilter</filter-name>
	<url-pattern>/*</url-pattern>
</filter-mapping>
但是让我一直困惑的是,这些过滤器是由谁来调用的?又是谁将它们组织起来,并确保他们的执行顺序的?
今天使用Spring cloud用代码的方法配置过滤器的时候(不再是配到web.xml中,Spring clound自带web容器,提供开箱即用的服务,所以以前很多需要配到web容器的配置都交给Spring来管理了,在学习Spring cloud的时候发现这货真的是想统一全世界呀-_-),发现自己定义的一个过滤器死活不执行,就打算将这个问题深挖到底。

过滤器demo如下(为保护公司秘密,重要代码已删除,各位见谅哈):

@WebFilter(filterName="FilterDemo", urlPatterns={"/**"})
@Order(1)	//当有多个filter时,指定filter的顺序
public class SecurityFilter implements Filter{
	private static final Logger LOGGER = LoggerFactory.getLogger( FilterDemo.class );
	
	@Override
	public void destroy() {
		
	}

	@Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
			throws IOException, ServletException {
		//TODO do some filter action;
		chain.doFilter(request, response);
	}

	@Override
	public void init(FilterConfig arg0) throws ServletException {
		// TODO Auto-generated method stub
	}

}
本以为这样写了之后过滤器就能工作了,可是请求进来以后发现过滤器未执行。后来想到Spring的工作都是交给注册到beanFacotry中的一个个bean来完成的,所以可能需要把这个过滤器注册到beanFactory中,就像这样:

@Configuration   //表明这是一个Spring配置文件
@EnableSwagger2  //swagger是一个restful接口的文档在线自动生成+功能测试功能框架
@RefreshScope    //允许当Spring cloud config配置文件改动之后,依赖配置的bean自动更新而不用重启服务
public class GlobalBeanConfig {

    //将filter加入到Spring配置中,否则只把filter类写出来,不加入配置还是无法起作用
    @Bean  //将xml形式的<bean></bean>采用代码来配置
    public Filter filterDemo(){
        return new FilterDemo();
    }

    @Bean(name = "loggerInteceptor")
    public GlobalAspectInteceptor getLoggerInteceptor() {
        return new GlobalAspectInteceptor();
    }

    @Bean
    public ThreadPoolTaskExecutor globalTaskExecutor(
            @Value("${global.thread.pool.corePoolSize}") Integer corePoolSize,
            @Value("${global.thread.pool.maxPoolSize}") Integer maxPoolSize,
            @Value("${global.thread.pool.queueCapacity}") Integer queueCapacity
    ) {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize( corePoolSize );
        executor.setMaxPoolSize( maxPoolSize );
        executor.setQueueCapacity( queueCapacity );
        executor.setWaitForTasksToCompleteOnShutdown(true);
        executor.setThreadGroupName("globalTaskExecutor");
        executor.setRejectedExecutionHandler( new ThreadPoolExecutor.DiscardPolicy() );
        executor.initialize();
        return executor;
    }
}
加了注解之后果然立马见效,看来我的直觉还是挺准的,嘻嘻~_~

好了,既然我们知道怎么用工具了,下面就来拆工具,看看how it works。通过断点调试,发现过滤器中两个关键的类在起作用:ApplicationFilterConfig,ApplicationFilterChain。

这两个类是org.apache.catalina.core包下面的,可以肯定是tomcat容器来管理过滤器链了。

接下来看ApplicationFilterConfig,先上部分源码:

public final class ApplicationFilterConfig implements FilterConfig, Serializable {
    private static final long serialVersionUID = 1L;
    static final StringManager sm = StringManager.getManager("org.apache.catalina.core");
    private static final Log log = LogFactory.getLog(ApplicationFilterConfig.class);
    private static final List<String> emptyString = Collections.emptyList();
    private final transient Context context;
  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值