☕
[Servlet]「ServletContextListenerインターフェース」(リスナー)の実装〜フィルターの呼び出し順序指定クラス〜
◆はじめに
ServletContextListenerインターフェース(以下:リスナー)を実装することで、
複数のFilterに対して指定した順序で呼び出すことが可能です。
その方法について、お伝えいたします。
◆リスナーについて
Filterクラスを実装した際に、
複数のFilterを呼び出す際に、呼び出す順序を指定したい場合があるとします。
その場合、以下の2つの方法があります(他にもあるかもしれませんが)
①ServletContextListenerインターフェース(通称リスナー)による方法
②@WebFilterアノテーションで呼び出し、web.xmlに呼び出す順序を記述する方法
今回は、②の方法で実装する場合について、
事前に準備してあるプロジェクトをベースにご紹介します。
次のトピックをご覧ください。
◆前提/環境など
本記事は、以下の記事の「InputFunction」プロジェクトをベースに作成しています。
Echo機能のServletの処理時間を計測するFilterを実装しています。
以下の記事の内容を踏まえた前提で、記事は書いていますのでご了承ください。
ただ、もし既にServletとFileterを実装しているプロジェクトがあるならば、
基本的には、そのプロジェクトにListerのクラスを実装するだけで、可能だと思います。
呼び出すフィルターの名前だけ変更のみで、あとは手順のコードのコピペで大丈夫です。
※本記事では、 eclipseは以下のバージョンでの画像を使用しています。
日本語化はしていません。
他のversionでの動作は確認しておりません。
◆手順
「InputFunction」プロジェクトからの
変更箇所と追加箇所をメインに記載しています。
また、「InputFunction」プロジェクトの「TimeFilter.java」に記述していた
@WebFilterアノテーションは使用する必要はないため、
予め、コメントアウトしておきましょう。
TimeFilter.java
~~~省略~~~
//@WebFilter("/echo")
public class TimeFilter implements Filter{
~~~省略~~~
①FilterRegisterクラスの用意
・mainフォルダに「listener」のパッケージを作成
・「listener」のパッケージ内に、「FilterRegister.java」を作成
②リスナーのソースコード
・以下のコードを、「FilterRegister.java」に記述
FilterRegister.java
package listener;
import java.util.EnumSet;
import javax.servlet.DispatcherType;
import javax.servlet.Filter;
import javax.servlet.FilterRegistration;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
import filter.TimeFilter;
@WebListener
public class FilterRegister implements ServletContextListener{
@Override
public void contextInitialized(ServletContextEvent servletContextEvent) {
System.out.println("START FilterRegister#contextInitialized()");
ServletContext context = servletContextEvent.getServletContext();
//呼び出すFilterの登録
addFilter(context , "TimeFilter" , TimeFilter.class, "/echo" );
//複数Filterを順序を指定して呼び出す際は、呼び出す順番で以下にaddFilter()を追記
//addFilter(context , "フィルターのクラス名" , フィルターのクラス名.class, "URL" );
System.out.println("END FilterRegister#contextInitialized()");
}
private void addFilter(ServletContext context, String filterName , Class<? extends Filter> filterClass , String... urlPatterns) {
context.addFilter(filterName, filterClass);
FilterRegistration filterRegistration = context.getFilterRegistration(filterName);
EnumSet<DispatcherType> dispatcherTypes = EnumSet.of(DispatcherType.REQUEST , DispatcherType.FORWARD );
filterRegistration.addMappingForUrlPatterns (dispatcherTypes , false , urlPatterns);
}
@Override
public void contextDestroyed(ServletContextEvent servletContextEvent) {
}
}
そして、複数Filterを順序を指定して呼び出す際には、
以下の箇所に、呼び出したい順番で、
addFilter()を使用して追記してください。
~~~省略〜〜〜
addFilter(context , "TimeFilter" , TimeFilter.class, "/echo" );
//複数Filterを順序を指定して呼び出す際は、呼び出す順番で以下にaddFilter()を追記
//addFilter(context , "フィルターのクラス名" , フィルターのクラス名.class, "URL" );
~~~省略〜〜〜
「InputFunction」プロジェクトでは、以上でソースを貼った以外の
ファイルのコードや追加しているライブラリーに関しては、特に変更はありません。
そちらのソースに関しては、以下の記事をご参照ください。
③動作チェック
・Tomcatなどアプリケーションサーバーを起動
・実装後に以下のURLにアクセス
以下の画面が表示されるので、
・テキストボックス文字列を入力
・送信ボタンを押す
Echo機能の仕様は以下です。
・文字列を入力し、送信ボタンを押す。
・Echo機能を提供するServletが呼び出される。
・送信した文字列が、再度、画面に表示される。
因みに、Validation機能の使用は以下です。
・送信された文字列が空欄の場合は、
「この項目は必須入力です。」と文字列が表示される。
そして、正常にTimeFilerが動作していれば、
Eclipseのコンソールに、
計測されたServletの処理時間が表示されているはずです。
以上です。
◆おまけ(②@WebFilterアノテーションでweb.xmlで記述する方法)
「◆はじめに」でご紹介した、
②@WebFilterアノテーションで呼び出し、web.xmlに呼び出す順序を記述する方法
の場合のコードも載せておきます。
web.xml
<web-app>
~~~省略〜〜〜
<!--最初に呼び出すフィルター -->
<filter>
<filter-name>TimeFilter</filter-name>
<filter-class>filter.TimeFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>TimeFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!--以下、同様の書き方で、呼び出す順番にフィルターを記載 -->
~~~省略〜〜〜
</web-app>
◆さいごに
以上です。いかがだったでしょうか。
リスナーの実装はできたでしょうか。
今回のポイントです。
①FilterRegisterクラスを作成する
②addFilter()を使用して、呼び出す順序でフィルターを記載
③フィルターのクラスに @WebFilterアノテーションは不要
コードに関しての詳しい説明に関しては、
あまり書いていません。少し、コード内にコメントはつけてます。
あとは、他の参考に載せている書籍やサイトなど調べてみてください。
最後まで、ご覧いただきありがとうございました。
◆参考
本記事は、以下の書籍を大いに参考にしています。
より詳しく知りたい方は、どうぞ。
Discussion