引き続きSpring Bootに関する投稿です。今回は、Spring Bootでサーブレットフィルタを設定するにはどうするか?、です。
環境
- spring-boot-2.0.4.RELEASE
- spring-boot-starter-web
- Embedded Tomcat 8.5.32
組み込みのTomcatコンテナで動作させる前提です。
フィルタの登録方法
Spring Bootでは、web.xmlのような設定ファイルは不要で、コントローラやフィルタなどのクラスを実装し、アノテーションやBean定義を行なうだけで、容易にSpring Bootに追加したい機能(今回はフィルタ)を認識させることができます。
さて、Spring Bootでフィルタを登録する方法ですが、1〜3で利用頻度もしくは一般的であろう順(著者感覚)に整理してみました。
1. FilterRegistrationBeanのBean定義
Spring Bootでは、Servlet、Filter、Listenerに対し、それぞれServletRegistrationBean
、FilterRegistrationBean
、ServletListenerRegistrationBean
というInitializerクラスが用意されています。
これらのクラス群は、ServletContextInitializer
インタフェースを実装しており、ServletContextの初期化時に呼ばれ、各種コンフィグレーションを行なうようになっています。そして、各種BeanはServletContextInitializerBeans
コンテナ(ここではコレクションのデータコンテナを意味する)に登録されており、TomcatStarter
のonStartup
コールバックでコンフィグレーションが実行されます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
package com.example.demo; import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.boot.web.servlet.ServletContextInitializer; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class MyWebMvcConfig { @Bean public FilterRegistrationBean myWebMvcFilter() { // ServletContextInitializerBeansに格納される FilterRegistrationBean bean = new FilterRegistrationBean(new MyFilter()); // <url-pattern/> bean.addUrlPatterns("/*"); // MyFilterがMyFilter2より先に呼ばれる bean.setOrder(1); return bean; } @Bean public FilterRegistrationBean myWebMvcFilter2() { // ServletContextInitializerBeansに格納される FilterRegistrationBean bean = new FilterRegistrationBean(new MyFilter2()); // <url-pattern/> bean.addUrlPatterns("/*"); // MyFilterがMyFilter2より先に呼ばれる bean.setOrder(2); return bean; } } |
MyFilter、MyFilter2クラスは、通常のフィルタ定義と同様で、javax.servlet.Filter
インターフェースを実装したクラスとして定義します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
package com.example.demo; import java.io.IOException; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; public class MyFilter implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { System.out.println("do something"); chain.doFilter(request, response); } @Override public void destroy() { } } |
参考
- https://docs.spring.io/spring-boot/docs/current/api/org/springframework/boot/web/servlet/FilterRegistrationBean.html
- https://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/htmlsingle/#boot-features-error-handling-mapping-error-pages-without-mvc
2. FilterのBean定義
Servlet3.0で@WebFilter
でフィルタ定義ができるようになりました。通常Spring Bootで組み込みコンテナを使って起動した場合、この@WebFilter
定義は無視されます。しかし、これらのアノテーションを使ったクラス(ライブラリなど)をアプリケーションでもそのまま利用したい場合、@ServletComponentScan
をつけると認識してくれるようです。
@ServletComponentScan
を付与した場合、ServletComponentHandler
を継承している各種HandlerクラスであるWebFilterHandler
、WebListenerHandler
、WebServletHandler
で処理されます。@ServletComponentScan
には、スキャンのベースとなるパッケージを指定します。@ServletComponentScan
の指定がない場合は、アノテーションが指定されたクラスのパッケージからスキャンされます。
1 2 3 4 5 |
@Configuration @ServletComponentScan(basePackages = "com.example") public class MyWebMvcConfig { ... bean definitions etc } |
フィルタクラスに@WebFilter
を指定します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
package com.example.demo; import java.io.IOException; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.annotation.WebFilter; @WebFilter public class MyFilter3 implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { System.out.println("do something"); chain.doFilter(request, response); } @Override public void destroy() { } } |
参考
- https://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/htmlsingle/#boot-features-embedded-container-context-initializer
- https://docs.spring.io/spring-boot/docs/current/api/org/springframework/boot/web/servlet/ServletComponentScan.html
3. ServletContextInitializerのBean定義
フィルタ以外にもServletContextの初期化時に何らかの処理をしたい場合には、独自のServletContextInitializer
を定義することができます。この場合1と同様、ServletContextInitializerBeans
に登録され、コンテナ起動時にスタートアップコールバックが呼ばれます。コールバックの引数で、ServletContextオブジェクトが渡されるので、その中で必要な設定を行なう方法も可能だと思います。
以下は直接Servlet APIを呼んで、InitParameterやFilterを登録する例です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
package com.example.demo; import javax.servlet.Filter; import javax.servlet.FilterRegistration; import javax.servlet.ServletContext; import javax.servlet.ServletException; import org.springframework.boot.web.servlet.ServletContextInitializer; @Order(Integer.MIN_VALUE) public class MyServletContextInitializer implements ServletContextInitializer { @Override public void onStartup(ServletContext servletContext) throws ServletException { // Set init parameter servletContext.setInitParameter("myparam", "myvalue"); // Register my filter Filter filter = servletContext.createFilter(MyFilter4.class); FilterRegistration filterRegistration = servletContext.addFilter("myFilter4", filter); filterRegistration.addMappingForUrlPatterns(null, true, "/*"); } } |
参考
- https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-developing-web-applications.html#boot-features-embedded-container-context-initializer
- https://docs.spring.io/spring-boot/docs/current/api/org/springframework/boot/web/servlet/ServletContextInitializer.html
参考リンク
- https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-developing-web-applications.html#boot-features-error-handling-mapping-error-pages-without-mvc
- https://docs.spring.io/spring-boot/docs/current/api/org/springframework/boot/web/servlet/ServletComponentScan.html
- https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-developing-web-applications.html#boot-features-embedded-container-context-initializer
- https://qiita.com/suke_masa/items/7bdfab8e974931afdac5
- https://qiita.com/NagaokaKenichi/items/630ce51bbe2b15589dd2
- https://qiita.com/kazuki43zoo/items/757b557c05f548c6c5db
コメント