61
55

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Spring Bootでサーブレットフィルターを使う [Spring Boot 1.x, 2.x両対応]

Last updated at Posted at 2018-02-28

環境

  • 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のAuto Configurationクラス内でFilterが取り出され、Embedded Serverに登録されます。

@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が持っている機能です。
引数で受け取ったBeanを、Filterのコンストラクタなどで受け取ればOKです。

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でFilterにBeanをDIしたり、AOPをFilterに適用したりすることはできません。

全Filterの適用順序を一覧で見る

FilterRegistrationBeanからFilter取り出し・Embedded Serverへの登録を行っているのは、ServletContextInitializerBeansというクラスです。このクラスのDEBUGログ(注: Spring Boot 2.1以降はTRACEログ)を出力すればOKです。
orderの値の昇順にFilterが実行されます。

application.properties
# 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定義してもOKなのですが、url-patternや実行順序を指定できません。@Beanメソッドに@Orderアノテーションを指定しても無視されるようです(@Orderの値に関わらず、ログに出力されるorderの値が2147483647になります)。

    @Bean
    @Order(Integer.MIN_VALUE) // この値は無視されるっぽい(仕様かどうかは不明)
    public HogeFilter hogeFilter() {
        return new HogeFilter();
    }

ということで、FilterRegistrationBeanを使いましょう。

参考資料

Spring Boot Reference
https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#boot-features-embedded-container-servlets-filters-listeners-beans
Javadoc
https://docs.spring.io/spring-boot/docs/current/api/org/springframework/boot/web/servlet/FilterRegistrationBean.html

61
55
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
61
55

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?