Spring Bootでフィルタ(Filter)する方法
Spring BootでFilterを実装する方法です。
Spring Boot では web.xml がありません。では、どうやったら Filter を実装できるのか・・・その方法を紹介します。複数 Filter する方法も掲載しておきます。
これから Spring BootでWebアプリを開発しようという方 のお役に立てればうれしいです。
環境
- Spring Boot 1.4.1
- Thymeleaf 3.0.2
- Windows7
- Java8
- Eclipse 4.6 Neon
こちらのページを参考にサンプルアプリを作ってください。既にSpring Bootアプリがある場合は、読み飛ばして結構です。
Spring BootでFilterを実装する
Filter インターフェースの実装クラスを作ってコンテナ登録します。
package springbootapp;
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 org.springframework.stereotype.Component;
@Component
public class LoggingFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("[Spring BootでFilterを実装] : init");
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
System.out.println("[Spring BootでFilterを実装] : doFilter");
chain.doFilter(request, response);
}
@Override
public void destroy() {
System.out.println("[Spring BootでFilterを実装] : destroy");
}
}
構成はこんな感じです。
実行してログをみてみると・・・
2016-11-17 13:03:32.012 INFO 8592 --- [ost-startStop-1] o.s.b.w.servlet.ServletRegistrationBean : Mapping servlet: 'dispatcherServlet' to [/]
2016-11-17 13:03:32.016 INFO 8592 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'characterEncodingFilter' to: [/*]
2016-11-17 13:03:32.017 INFO 8592 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'hiddenHttpMethodFilter' to: [/*]
2016-11-17 13:03:32.017 INFO 8592 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'httpPutFormContentFilter' to: [/*]
2016-11-17 13:03:32.017 INFO 8592 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'requestContextFilter' to: [/*]
2016-11-17 13:03:32.017 INFO 8592 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'loggingFilter' to: [/*]
[Spring BootでFilterを実装] : init
・・・省略・・・
[Spring BootでFilterを実装] : doFilter
おおお、フィルターされましたねー^^
上記のログから、お馴染みの CharacterEncodingFilter が設定しなくても動いているがわかります。これは HttpEncodingAutoConfiguration によって自動登録されるため、デフォルトエンコーディングとして設定されている「UTF-8」を使う場合は設定する必要がありません。簡単だなー^^
Spring BootでFilterを複数実装する
上で作った LoggingFilter を LoggingFilter1 に名前を変え、LoggingFilter2 としてコピーします。実行順わかりやすいように sysout に「その1」とか「その2」とか付けておきます。
@Component アノテーションは削除しておきます。
package springbootapp;
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 LoggingFilter1 implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("[Spring BootでFilterを実装 その1] : init");
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
System.out.println("[Spring BootでFilterを実装 その1] : doFilter");
chain.doFilter(request, response);
}
@Override
public void destroy() {
System.out.println("[Spring BootでFilterを実装 その1] : destroy");
}
}
package springbootapp;
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 LoggingFilter2 implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("[Spring BootでFilterを実装 その2] : init");
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
System.out.println("[Spring BootでFilterを実装 その2] : doFilter");
chain.doFilter(request, response);
}
@Override
public void destroy() {
System.out.println("[Spring BootでFilterを実装 その2] : destroy");
}
}
WebConfig クラスを作って、WebMvcConfigurerAdapter を extened します。メソッドに @Bean アノテーションを書くことによって、複数のフィルタを追加できます。
package springbootapp;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
@Configuration
public class WebConfig extends WebMvcConfigurerAdapter {
@Bean
public FilterRegistrationBean filter1() {
FilterRegistrationBean bean = new FilterRegistrationBean();
bean.setFilter(new LoggingFilter1());
bean.setOrder(2);
return bean;
}
@Bean
public FilterRegistrationBean filter2() {
FilterRegistrationBean bean = new FilterRegistrationBean();
bean.setFilter(new LoggingFilter2());
bean.setOrder(1);
return bean;
}
}
構成はこんな感じです。
実行してログをみてみると・・・
2016-11-17 13:27:03.388 INFO 6716 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'characterEncodingFilter' to: [/*]
2016-11-17 13:27:03.388 INFO 6716 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'hiddenHttpMethodFilter' to: [/*]
2016-11-17 13:27:03.389 INFO 6716 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'httpPutFormContentFilter' to: [/*]
2016-11-17 13:27:03.389 INFO 6716 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'requestContextFilter' to: [/*]
2016-11-17 13:27:03.389 INFO 6716 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'loggingFilter2' to: [/*]
2016-11-17 13:27:03.389 INFO 6716 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'loggingFilter1' to: [/*]
2016-11-17 13:27:03.389 INFO 6716 --- [ost-startStop-1] o.s.b.w.servlet.ServletRegistrationBean : Mapping servlet: 'dispatcherServlet' to [/]
[Spring BootでFilterを実装 その2] : init
[Spring BootでFilterを実装 その1] : init
・・・省略・・・
[Spring BootでFilterを実装 その2] : doFilter
[Spring BootでFilterを実装 その1] : doFilter
おおお、フィルターされましたねー^^
setOrder プロパティでフィルターの登録順を設定できます。多分、メソッドを書いた順番で動くと思うんですけど、明示的にしておけば安心ですので。
まとめ
Spring BootでFilterを実装する方法を紹介しました。
これで web.xml なしでフィルター実装できることがわかりましたね。
Servlet は 3.0 になってからアノテーションを利用することで Servlet の設定が単純になりました。一度はプログラミングの外に設定を追い出したはずなのに、アノテーションを利用することでまたプログラミングの中に記述するスタイルに戻った・・・ということですかね。さて、どっちがメリット高いのか・・。設定は外出ししておいた方がメンテナンス性は向上しそうだけど、生産性はどうなんだって・・・。永遠のテーマなんでしょうかねー^^;
次は開発と本番で設定ファイルを切り替えるあたりを検証しましょうかね。
おつかれさまでした。