在很多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;