- Home ›
- サーブレット/JSP入門 ›
- フィルタ
Filterインターフェース
ではフィルタとして呼び出されるサーブレットの作成方法について見ていきます。フィルタを作成するにはFilterインターフェースを実装したクラスを作成します。
フィルタインターフェースを実装するには次の3つのメソッドを実装する必要があります。
init public void init(FilterConfig filterConfig) throws ServletException
Called by the web container to indicate to a filter that it is being placed into service. The servlet container calls the init method exactly once after instantiating the filter. The init method must complete successfully before the filter is asked to do any filtering work. The web container cannot place the filter into service if the init method either 1.Throws a ServletException 2.Does not return within a time period defined by the web container Throws: ServletException
"init"メソッドはフィルタの初期化処理に使います。
destroy public void destroy()
Called by the web container to indicate to a filter that it is being taken out of service. This method is only called once all threads within the filter's doFilter method have exited or after a timeout period has passed. After the web container calls this method, it will not call the doFilter method again on this instance of the filter. This method gives the filter an opportunity to clean up any resources that are being held (for example, memory, file handles, threads) and make sure that any persistent state is synchronized with the filter's current state in memory.
"destroy"メソッドはフィルタが破棄される時に呼び出されます。
doFilter public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws java.io.IOException, ServletException
The doFilter method of the Filter is called by the container each time a request/response pair is passed through the chain due to a client request for a resource at the end of the chain. The FilterChain passed in to this method allows the Filter to pass on the request and response to the next entity in the chain. Throws: java.io.IOException ServletException
"doFilter"メソッドはFilterインターフェースを実装したフィルタクラスがフィルタとして呼び出された時に実行されるメソッドです。通常のサーブレットのdoGetメソッドやdoPostメソッドに相当します。
よってフィルタとして使うサーブレットは次のような構成になります。
import java.io.*; import javax.servlet.*; import javax.servlet.Filter; import javax.servlet.FilterChain; public class FilterTest implements Filter{ public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain){ try{ /* フィルタで行う処理 */ }catch (ServletException se){ }catch (IOException e){ } } public void init(FilterConfig filterConfig){ } public void destroy(){ } }
"doFilte"メソッド内で、フィルタとして行いたい処理を記述します。
FilterChainインターフェース
先ほどのような構成だと、フィルタが呼び出された後で本来実行されるべきサーブレットに処理を戻していません。1つのフィルタは複数のサーブレットの前処理として共通して利用される場合があり、フィルタがどのサーブレットを実行する途中で呼び出されたのかを知る必要があります。その流れを管理しているのが"doFilter"メソッドの3番目の引数であるFilterChainインターフェースの値です。
FilterChainインターフェースは、どのサーブレットを呼び出そうとした時にこのフィルタが呼ばれ、このフィルタの次に呼び出すべきサーブレットは何かということを管理しています。フィルタの次に別のフィルタがさらに呼び出される場合もありますし、本来の目的のサーブレットが呼び出される場合もありますが、フィルタではあまり意識することなく、FilterChainインターフェースで定義されている"doFilter"メソッドを呼び出すだけで次のサーブレットへ処理を移してくれます。
doFilter public void doFilter(ServletRequest request, ServletResponse response) throws java.io.IOException, ServletException
Causes the next filter in the chain to be invoked, or if the calling filter is the last filter in the chain, causes the resource at the end of the chain to be invoked. Parameters: request - the request to pass along the chain. response - the response to pass along the chain. Throws: java.io.IOException ServletException
※FilterインターフェースとFilterChainインターフェースで同じ名前で定義されている"doFilter"メソッドをそれぞれ使うので注意して下さい。
よってフィルタでは、フィルタ内の処理が終わった段階で"doFilter"メソッドを呼び出すことでフィルタとしての処理を終了します。
import java.io.*;
import javax.servlet.*;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
public class FilterTest implements Filter{
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain){
try{
/* フィルタで行う処理 */
chain.doFilter(request, response);
}catch (ServletException se){
}catch (IOException e){
}
}
public void init(FilterConfig filterConfig) throws ServletException{
}
public void destroy(){
}
}
FilterChainインターフェースの"doFilter"メソッドを呼び出さずに、他のサーブレットへフォワードやリダイレクトしてフィルタの流れを切る事も可能です。例えばフィルタで認証のチェックを行い認証が行われていなければログインを行うサーブレットへリダイレクトするといった処理です。
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain){ try{ if (認証が行われている) then{ chain.doFilter(request, response); }else{ ((HttpServletResponse)response).sendRedirect("/Login"); } }catch (ServletException se){ }catch (IOException e){ } } }
サンプルプログラム
では簡単なサンプルプログラムでフィルタを試してみましょう。
今回作成するWebアプリケーションのパスは「filter」とし、Webアプリケーションの置き場所は「d:\servlet-sample\filter\」としました。コンテキストファイルは下記のようになります。
<Context path="/filter" docBase="d:/servlet-sample/filter"/>
web.xmlファイルは下記のようにしました。
<?xml version="1.0" encoding="ISO-8859-1"?> <web-app xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd" version="2.4"> <filter> <filter-name>filtertest</filter-name> <filter-class>FilterTest</filter-class> </filter> <filter-mapping> <filter-name>filtertest</filter-name> <url-pattern>/helloworld</url-pattern> </filter-mapping> <servlet> <servlet-name>helloworld</servlet-name> <servlet-class>HelloWorld</servlet-class> </servlet> <servlet-mapping> <servlet-name>helloworld</servlet-name> <url-pattern>/helloworld</url-pattern> </servlet-mapping> </web-app>
プログラムは下記の通りです。
import java.io.*; import javax.servlet.*; import javax.servlet.http.*; public class HelloWorld extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException{ response.setContentType("text/html; charset=Shift_JIS"); PrintWriter out = response.getWriter(); System.out.println("HelloWorld"); out.println("<html>"); out.println("<head>"); out.println("<title>フィルタテスト</title>"); out.println("</head>"); out.println("<body>"); out.println("<p>Hello World!</p>"); out.println("</body>"); out.println("</html>"); } }
import java.io.*; import javax.servlet.*; import javax.servlet.Filter; import javax.servlet.FilterChain; public class FilterTest implements Filter{ public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain){ try{ System.out.println("フィルタ実行"); chain.doFilter(request, response); }catch (ServletException se){ }catch (IOException e){ } } public void init(FilterConfig filterConfig) throws ServletException{ } public void destroy(){ } }
上記をコンパイル後に「d:\servlet-sample\filter\WEB-INF\classes\」ディレクトリにクラスファイルを移動した後で、ブラウザで「http://localhost:8080/filter/helloworld」へアクセスしてみます。
まず呼び出したサーブレットは普通に実行されています。次にフィルタとして設定したサーブレットが実行されているか確認します。
Tomcatのstdoutログを確認すると、フィルターで記述した標準出力への出力が実行されていることが確認できました。HelloWorldクラスを呼び出すと、HelloWorldクラスが呼び出される前にFilterTestクラスが呼び出されていることになります。
( Written by Tatsuo Ikura )
著者 / TATSUO IKURA
これから IT 関連の知識を学ばれる方を対象に、色々な言語でのプログラミング方法や関連する技術、開発環境構築などに関する解説サイトを運営しています。