使用 Spring Boot 中的 Servlet 过滤器 [适用于 Spring Boot 1.x 和 2.x]
环境
-
- Spring Boot 1.5.10
-
- Embedded Tomcat 8.5.27
- JDK 8
2018-03-09备注
升级至Spring Boot 2.0.0.RELEASE后,仍然表现出相同的行为。2018-12-20备注
添加了Spring Boot 2.1的说明。
基本的Filter的注册方式
在Spring Boot中使用提供的FilterRegistrationBean类。
当定义FilterRegistrationBean作为一个Bean时,Spring Boot的自动配置类将检索并注册Filter到嵌入式服务器中。
@Configuration
public class SomeConfig {
@Bean
public FilterRegistrationBean hogeFilter() {
// FilterをnewしてFilterRegistrationBeanのコンストラクタに渡す
FilterRegistrationBean bean = new FilterRegistrationBean(new HogeFilter());
// Filterのurl-patternを指定(可変長引数なので複数指定可能)
bean.addUrlPatterns("/*");
// Filterの実行順序。整数値の昇順に実行される
bean.setOrder(Integer.MIN_VALUE);
return bean;
}
@Bean
public FilterRegistrationBean fugaFilter() {
FilterRegistrationBean bean = new FilterRegistrationBean(new FugaFilter());
bean.addUrlPatterns("/*");
// HogeFilterの後に実行される
bean.setOrder(Integer.MIN_VALUE + 1);
return bean;
}
// 何個でもFilterを定義可能
}
在Filter中使用其他的Bean
@Bean方法可以使用参数接收其他的Bean。这是Spring原本就具备的功能。
只要在Filter的构造函数等地方接收参数传入的Bean就可以了。
public class HogeFilter extends OncePerRequestFilter { // もちろん「implements Filter」でもOK
private final FugaBean fugaBean; // フィールドを作成
public HogeFilter(FugaBean fugaBean) { // コンストラクタでBeanを受け取る
this.fugaBean = fugaBean;
}
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException {
// 前処理をここに書く
chain.doFilter(request, response);
// 後処理をここに書く
}
}
@Configuration
public class HogeConfig {
@Bean
public FilterRegistrationBean hogeFilter(FugaBean fugaBean) {
// FilterのコンストラクタにBeanを渡す
FilterRegistrationBean bean = new FilterRegistrationBean(new HogeFilter(fugaBean));
// ...
return bean;
}
}
FugaBean需要在其他地方(如其他Config类或组件扫描中)进行Bean定义。
请注意,Filter本身不是一个Bean。也就是说,无法通过@Autowired将Bean注入到Filter中,也无法将AOP应用于Filter。
可在一覽表中查看所有Filter適用的順序。
将Filter从FilterRegistrationBean中提取出来并注册到Embedded Server中的是ServletContextInitializerBeans类。只要输出该类的DEBUG日志(注意:Spring Boot 2.1及更高版本要输出TRACE日志)就可以了。Filter将按照order值的升序进行执行。
# Boot 2.1以降は、debugではなくtraceにする
logging.level.org.springframework.boot.web.servlet.ServletContextInitializerBeans=debug
...
2018-02-28 11:58:37.611 DEBUG 4323 --- [ost-startStop-1] o.s.b.w.s.ServletContextInitializerBeans : Added existing Filter initializer bean 'loggingFilter1'; order=-2147483648, resource=com.example.Application
2018-02-28 11:58:37.611 DEBUG 4323 --- [ost-startStop-1] o.s.b.w.s.ServletContextInitializerBeans : Added existing Filter initializer bean 'loggingFilter2'; order=-2147483647, resource=com.example.Application
2018-02-28 11:58:37.612 DEBUG 4323 --- [ost-startStop-1] o.s.b.w.s.ServletContextInitializerBeans : Added existing Filter initializer bean 'loggingFilter3'; order=-2147483646, resource=com.example.Application
2018-02-28 11:58:37.612 DEBUG 4323 --- [ost-startStop-1] o.s.b.w.s.ServletContextInitializerBeans : Added existing Servlet initializer bean 'dispatcherServletRegistration'; order=2147483647, resource=class path resource [org/springframework/boot/autoconfigure/web/DispatcherServletAutoConfiguration$DispatcherServletRegistrationConfiguration.class]
2018-02-28 11:58:37.638 DEBUG 4323 --- [ost-startStop-1] o.s.b.w.s.ServletContextInitializerBeans : Created Filter initializer for bean 'characterEncodingFilter'; order=-2147483648, resource=class path resource [org/springframework/boot/autoconfigure/web/HttpEncodingAutoConfiguration.class]
2018-02-28 11:58:37.638 DEBUG 4323 --- [ost-startStop-1] o.s.b.w.s.ServletContextInitializerBeans : Created Filter initializer for bean 'hiddenHttpMethodFilter'; order=-10000, resource=class path resource [org/springframework/boot/autoconfigure/web/WebMvcAutoConfiguration.class]
2018-02-28 11:58:37.638 DEBUG 4323 --- [ost-startStop-1] o.s.b.w.s.ServletContextInitializerBeans : Created Filter initializer for bean 'httpPutFormContentFilter'; order=-9900, resource=class path resource [org/springframework/boot/autoconfigure/web/WebMvcAutoConfiguration.class]
2018-02-28 11:58:37.638 DEBUG 4323 --- [ost-startStop-1] o.s.b.w.s.ServletContextInitializerBeans : Created Filter initializer for bean 'requestContextFilter'; order=-105, resource=class path resource [org/springframework/boot/autoconfigure/web/WebMvcAutoConfiguration$WebMvcAutoConfigurationAdapter.class]
...
将Filter本身定义为Bean会怎样?
虽然将Filter本身定义为Bean也是可以的,但无法指定url-pattern或执行顺序。即使在@Bean方法中指定了@Order注解,也会被忽略(不论@Order的值为何,在日志中输出的order值都将变为2147483647)。
@Bean
@Order(Integer.MIN_VALUE) // この値は無視されるっぽい(仕様かどうかは不明)
public HogeFilter hogeFilter() {
return new HogeFilter();
}
那么,让我们使用FilterRegistrationBean。
请参考以下资料。
Spring Boot参考文档
https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#boot-features-embedded-container-servlets-filters-listeners-beans
Java文档
https://docs.spring.io/spring-boot/docs/current/api/org/springframework/boot/web/servlet/FilterRegistrationBean.html