Filter インターフェイスについて

すべてのフィルタは javax.servlet.Filter インターフェイスを実装します。フィルタ API には、オーバーライドする必要がある 3 つのメソッドがあります。次の表で、これらのメソッドについて説明します。
メソッド
説明
void init(FilterConfig config)
JRun は、init メソッドを一度呼び出してフィルタを初期化します。その後フィルタを呼び出しても、サーバを再起動しないかぎり init メソッドは呼び出されません。この init メソッドは、初期化
パラメータにアクセスする可能性がある FilterConfig オブジェクトを定義します。
void doFilter(
ServletRequest req,
ServletResponse resp,
FilterChain chain
)
ほとんどの作業は doFilter メソッドで実行されます。doFilter では、リクエストおよびレスポンスオブジェクトに作用し、複数のフィルタが呼び出されます。使用するフィルタの数にかかわらず、フィルタはフィルタチェーンの一部です。フィルタチェーンは、次のフィルタに制御を渡したり、ターゲットリソースに制御を渡したりするときにフィルタが使用するオブジェクトです。
doFilter メソッドは、リクエストおよびレスポンスオブジェクトのデータおよびヘッダーを検証して変更できます。
このメソッドは FilterChain オブジェクトを使用してチェーン内の次のフィルタを呼び出します。その後も、リクエストおよびレスポンスのデータおよびヘッダーを再び検証して変更できます。
void destroy()
JRun は、フィルタが不要になったことを示すために、通常はシャットダウン時に destroy メソッドを一度呼び出します。destroy メソッドは通常、FilterConfig オブジェクトを廃棄することによってフィルタが使用するリソースを解放します。

簡単なフィルタサンプル

次のコードは、フィルタがオーバーライドする必要がある 3 つのメソッドを示しています。このサンプルでは、フィルタチェーンを呼び出すだけです。

import javax.servlet.*;
public class SimpleFilter implements Filter {
 public void init(FilterConfig filterConfig) {
  this.filterConfig = filterConfig;
 }
 public void doFilter(ServletRequest request, ServletResponse 
response, FilterChain chain) throws java.io.IOException, 
javax.servlet.ServletException {
  chain.doFilter(request,response);
 }
 public void destroy() {
  this.filterConfig = null;
 }
}

FilterConfig オブジェクトについて

JRun は、FilterConfig オブジェクトを使用してフィルタを初期化します。FilterConfig オブジェクトは、次のメソッドを提供します。これらのメソッドによって、初期化パラメータおよび ServletContext オブジェクトにアクセスできます。

FilterConfig オブジェクトは、フィルタの init メソッド内で定義します。その後、doFilter メソッド内で、init メソッドで指定されている初期化パラメータを使用できます。

private FilterConfig filterConfig = null;
private String version;
public void init(FilterConfig filterConfig) {
 this.filterConfig = filterConfig;
 this.version = filterConfig.getInitParameter("version");
 System.out.println("フィルタが初期化されました:" + 
filterConfig.getFilterName() + "version " + 
filterConfig.getInitParameter("version"));
 }
public void doFilter(ServletRequest request, ServletResponse response, 
FilterChain chain) throws java.io.IOException, 
javax.servlet.ServletException {
 version = getVersion(request);
 chain.doFilter(request,response);
}
public String getVersion(ServletRequest request) {
 return this.version;
}

フィルタの初期化パラメータは、web.xml デプロイメントディスクリプタのフィルタ定義内で定義します。詳細については、 「フィルタの定義」 を参照してください。

あるいは、フィルタの destroy メソッド内で FilterConfig オブジェクトを廃棄します。コードは次のとおりです。

public void destroy() {
 this.filterConfig = null;
}

FilterChain オブジェクトについて

JRun は、FilterChain オブジェクトをフィルタの doFilter メソッドに渡します。各フィルタは、次のフィルタまたはターゲットリソースに制御を渡しますが、下流のフィルタが処理を終了すると、制御は最終的にチェーンに戻ります。スタックをワインドおよびアンワインドする方法としては、チェーン内の複数のフィルタを使用することができます。

各フィルタは、リクエストの処理を終了すると、制御をチェーンに返します。それ以降、処理は次のフィルタ (存在する場合)、前のフィルタ、またはターゲットリソースで実行されます。

フィルタには、制御をいつチェーンに返すかを指定したり、制御を戻すかどうかを指定したりするロジックを含めることができます。最後のフィルタがチェーンを呼び出し、チェーン内にこれ以上フィルタがないと、リクエストはターゲットリソースに渡されます。

フィルタのロジックによって制御がチェーンに戻されないようになっている場合、チェーンは中断され、レスポンスはフィルタチェーンを通り抜けてクライアントに戻されます。チェーン内の下流にある他のフィルタ (存在する場合) は無視されます。

チェーンを中断したフィルタは、他のリソースにリクエストを転送できます。したがって、フィルタによってはリクエストを一度も受け取らない場合があります。フィルタのチェーンは、RequestDispatcher と、forward または include を使用して中断できます。送信されたリクエストは、コンテナマッピングがあってもチェーン内のフィルタに送られることはなく、クライアントに戻されます。

次の図にこの処理を示します。

さらにリクエストは 2 番めのフィルタ、最初のフィルタ、JRun、クライアントの順に戻されます。

FilterChain オブジェクトには次の 1 つのメソッドがあります。

doFilter(ServletRequest request, ServletResponse response)

リクエストとレスポンスをチェーン内の次のフィルタに渡すには、doFilter メソッドを使用します。現在のフィルタがチェーン内の最後のフィルタか、または唯一のフィルタである場合、リクエストおよびレスポンスはターゲットリソースに渡されます。ターゲットリソースが処理を終了すると、リクエストとレスポンスはチェーンのフィルタに戻されます。このフィルタは、リクエストとレスポンスを、チェーン内の前のフィルタ (存在する場合) に渡していきます。レスポンスがチェーン内の最初のフィルタまたは唯一のフィルタに達すると、レスポンスが渡されます。

フィルタはターゲットリソースにアクセスし、レスポンスを返すために、まず、フィルタの doFilter メソッド内でチェーンの doFilter メソッドを呼び出す必要があります。
コードは次のとおりです。

public void doFilter(ServletRequest request, ServletResponse response, 
FilterChain chain) throws java.io.IOException, 
javax.servlet.ServletException {
 chain.doFilter(request,response);

}

汎用フィルタクラスの作成

すべてのフィルタに javax.servlet.Filter インターフェイスが実装されているので、各フィルタ内では、そのインターフェイスのメソッドをオーバーライドする必要があります。ほとんどのフィルタは init および destroy メソッド内でフィルタ固有のアクションを実行することはありません。したがって、これらのメソッドをオーバーライドする汎用クラスを使用すると、不要なコードを記述せずに済みます。

Java のオブジェクト指向性を利用するには、Filter インターフェイスを実装し、すべてのメソッドをオーバーライドする汎用クラスを作成してください。次に、フィルタで、新しく作成した汎用クラスを拡張し、必要なメソッドについてだけカスタマイズロジックを指定します。ほとんどの場合、doFilter メソッドだけをオーバーライドします。

次のコードは、javax.servlet.Filter インターフェイスを実装する GenericFilter クラスを示しています。フィルタはこのクラスを拡張し、必要なメソッドだけをオーバーライドします。

package jrunsamples.filters;
import javax.servlet.*;
public class GenericFilter implements Filter {
 public FilterConfig filterConfig;
 public void doFilter(ServletRequest request,ServletResponse 
response, FilterChain chain) throws java.io.IOException, 
javax.servlet.ServletException {
  chain.doFilter(request, response);
 }
 public void destroy() {
  this.filterConfig = null;
 }
 public void init(FilterConfig filterConfig) {
  this.filterConfig = filterConfig;
 }
}

GenericFilter を次のように拡張することによって、簡単なフィルタサンプルを実装できます ( 「簡単なフィルタサンプル」 を参照)。

package jrunsamples.filters;
import javax.servlet.*;
public class SimpleFilter extends GenericFilter {
 public void doFilter(ServletRequest request, ServletResponse 
response, FilterChain chain) throws java.io.IOException, 
javax.servlet.ServletException {
  // フィルタロジック
  chain.doFilter(request,response);
  // フィルタロジック
 }
}