English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Servlet フィルタの書き方

Servletフィルタは、リクエストや応答に含まれる情報を変換したり使用するために、動的にリクエストや応答をインターセプトできます。

1つまたは複数のServletフィルタをServletまたはServletグループにアタッチできます。Servletフィルタは、JavaServer Pages (JSP) ファイルやHTMLページにもアタッチできます。Servletを呼び出す前に、すべてのアタッチされたServletフィルタを呼び出します。

Servlet フィルタは、Servlet プログラミングに使用できるJavaクラスで、以下の目的を実現できます:

  • クライアントのリクエストがバックエンドリソースにアクセスする前に、これらのリクエストをインターセプトします。

  • サーバーの応答がクライアントに送信される前に、これらの応答を処理します。

規範に提案されている様々な種類のフィルタ:

  • 認証フィルタ(Authentication Filters)。

  • データ圧縮フィルタ(Data compression Filters)。

  • 暗号化フィルタ(Encryption Filters)。

  • リソースアクセスイベントをトリガーするフィルタ。

  • 画像変換フィルタ(Image Conversion Filters)。

  • ログ記録および監査フィルタ(Logging and Auditing Filters)。

  • MIME-TYPE メディアタイプチェーンフィルタ(MIME-TYPE Chain Filters)。

  • トークナイズフィルタ(Tokenizing Filters)。

  • XSL/T フィルタ(XSL/T Filters),XML内容を変換します。

フィルタはWebデプロイメントディスクリプタ(web.xml)内のXMLタグで宣言され、その後、アプリケーションのデプロイメントディスクリプタ内のServlet名またはURLパターンにマッピングされます。

WebコンテナがWebアプリケーションを起動した際、デプロイメントディスクリプタ内で宣言されている各フィルタに対して、サンプルオブジェクトを作成します。

Filterの実行順序はweb.xml設定ファイル内の配置順序と一致しており、一般的にはすべてのServletの前にFilterを設定します。

Servlet フィルタメソッド

フィルタはjavax.servlet.Filterインターフェースを実装したJavaクラスです。javax.servlet.Filterインターフェースは3つのメソッドを定義しています:

番号メソッド & 説明
1public void doFilter(ServletRequest, ServletResponse, FilterChain)
このメソッドは実際のフィルタリング操作を完了します。クライアントのリクエストメソッドがフィルタの設定に一致するURLとマッチする場合、ServletコンテナはまずフィルタのdoFilterメソッドを呼び出します。FilterChainは後続のフィルタにアクセスします。
2public void init(FilterConfig filterConfig)
ウェブアプリケーションが起動した際、ウェブサーバーはFilterのサンプルオブジェクトを作成し、そのinitメソッドを呼び出してweb.xmlの設定を読み取り、オブジェクトの初期化機能を完了し、その後のユーザー請求に対するインターセプトの準備を整えます(filterオブジェクトは一度だけ作成され、initメソッドも一度だけ実行されます)。開発者はinitメソッドの引数を通じて、現在のfilter設定情報を表すFilterConfigオブジェクトを取得できます。
3public void destroy()
Servlet コンテナがフィルタサンプルを破棄する前に、このメソッドを呼び出し、その中で Servlet フィルタが占めるリソースを解放します。

FilterConfig は

Filter の init メソッドでは FilterConfig オブジェクトが提供されます。

web.xml ファイルの設定は以下のようになります:

<filter>
    <filter-name>LogFilter</filter-name>
    <filter-class>com.w3codebox.test.LogFilter</filter-class>
    <init-param>
        <param-name>Site</param-name>
        <param-value>基本チュートリアルウェブ</param-value>
    </init-param>
</filter>

init メソッドで FilterConfig オブジェクトを使用してパラメータを取得します:

public void  init(FilterConfig config) throws ServletException {
    // 初期化パラメータを取得
    String site = config.getInitParameter("Site"); 
    // 初期化パラメータを出力
    System.out.println("サイト名: " + site); 
}

Servlet フィルタの例

以下は、サイト名とURLを出力する Servlet フィルタの例です。このサンプルを使用して、Servlet フィルタの基本的な理解を深めることができます。複雑なフィルタアプリケーションを書く際に、同じ概念を使用できます:

package com.w3codebox.test;
//导入必需的 java ライブラリ
import javax.servlet.*;
import java.util.*;
//Filter クラスを実装
public class LogFilter implements Filter  {
    public void  init(FilterConfig config) throws ServletException {
        // 初期化パラメータを取得
        String site = config.getInitParameter("Site"); 
        // 初期化パラメータを出力
        System.out.println("サイト名: " + site); 
    }
    public void  doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws java.io.IOException, ServletException {
        // サイト名を出力
        System.out.println("サイトURL:http://ja.oldtoolbag.com");
        // リクエストをフィルタリングチェーンに戻します
        chain.doFilter(request,response);
    }
    public void destroy( ){
        /* Filter サンプルが Web コンテナからサービスから削除される前に呼び出されます */
    }
}

前文に記載された DisplayHeader.java を例として使用しています:

//导入必需的 java ライブラリ
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Enumeration;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet("/DisplayHeader)
//HttpServlet クラスを拡張
public class DisplayHeader extends HttpServlet
    // GET メソッドリクエストを処理するメソッド
    public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
    {
        // 設定する応答内容タイプ
        response.setContentType("text/html;charset=UTF-8");
        PrintWriter out = response.getWriter();
        String title = "HTTP Header リクエストサンプル - 基础教程网サンプル";
        String docType =
            "<!DOCTYPE html> \n";
            out.println(docType +
            "<html>\n" +
            "<head><meta charset=\"utf-8\"><title>" + title + "</title></head>\n"+
            "<body bgcolor=\"#f0f0f0\">\n" +
            "<h1 align=\"center\">" + title + "</h1>\n" +
            "<table width=\"100%\" border=\"1\" align=\"center\">\n" +
            "<tr bgcolor=\"#949494\">\n" +
            "<th>Header 名前</th><th>Header 値</th>\n"+
            "</tr>\n");
        Enumeration headerNames = request.getHeaderNames();
        while(headerNames.hasMoreElements()) {
            String paramName = (String)headerNames.nextElement();
            out.print("<tr><td>" + paramName + "</td>\n");
            String paramValue = request.getHeader(paramName);
            out.println("<td> " + paramValue + "</td></tr>\n");
        }
        out.println("</table>\n</body></html>");
    }
    // POSTメソッドリクエストを処理するメソッド
    public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }
}

Web.xmlのServletフィルタマッピング(Servlet Filter Mapping)

フィルタを定義し、URLやServletにマッピングします。これはServletを定義し、URLパターンにマッピングする方法と大抵同じです。デプロイメント記述ファイル web.xml 中でfilterタグの以下のエントリを作成します:

<?xml version="1.0" encoding="UTF-8"?>  
<web-app>  
<filter>
  <filter-name>LogFilter</filter-name>
  <filter-class>com.w3codebox.test.LogFilter</filter-class>
  <init-param>
    <param-name>Site</param-name>
    <param-value>基本チュートリアルウェブ</param-value>
  </init-param>
</filter>
<filter-mapping>
  <filter-name>LogFilter</filter-name>
  <url-pattern>/*</url-pattern>
</filter-mapping>
<servlet>  
  <!-- クラス名 -->  
  <servlet-name>DisplayHeader</servlet-name>  
  <!-- のパッケージ -->  
  <servlet-class>com.w3codebox.test.DisplayHeader</servlet-class>  
</servlet>  
<servlet-mapping>  
  <servlet-name>DisplayHeader</servlet-name>  
  <!-- 訪問したURL -->  
  <url-pattern>/TomcatTest/DisplayHeader</url-pattern>  
</servlet-mapping>  
</web-app>

上記のフィルタはすべてのServletに適用されます。なぜなら、私たちは設定で指定しているからです。 /* 特定のServletにのみフィルタを適用したい場合は、特定のServletパスを指定できます。

通常の方法でどのServletを呼び出すか試してみてください。Webサーバーで生成されるログが見られます。Logを使用することもできます。4Jレコーダーを使って上記のログを別のファイルに記録します。

次にこのサンプルのURLにアクセスします http://localhost:8080/TomcatTest/DisplayHeader, 然后在控制台看下输出内容,如下所示:

使用多个过滤器

Web 应用程序可以根据特定的目的定义若干个不同的过滤器。假设您定义了两个过滤器 AuthenFilterLogFilter。您需要创建一个如下所述的不同的映射,其余的处理与上述所讲解的大致相同:

<filter>
   <filter-name>LogFilter</filter-name>
   <filter-class>com.w3codebox.test.LogFilter</filter-class>
   <init-param>
      <param-name>test-param</param-name>
      <param-value>Initialization Paramter</param-value>
   </init-param>
</filter>
<filter>
   <filter-name>AuthenFilter</filter-name>
   <filter-class>com.w3codebox.test.AuthenFilter</filter-class>
   <init-param>
      <param-name>test-param</param-name>
      <param-value>Initialization Paramter</param-value>
   </init-param>
</filter>
<filter-mapping>
   <filter-name>LogFilter</filter-name>
   <url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
   <filter-name>AuthenFilter</filter-name>
   <url-pattern>/*</url-pattern>
</filter-mapping>

过滤器的应用顺序

web.xml 中的 filter-mapping 元素的顺序决定了 Web 容器应用过滤器到 Servlet 的顺序。若要反转过滤器的顺序,您只需要在 web.xml 文件中反转 filter-mapping 元素即可。

例如,上面的示例将先应用 LogFilter,然后再应用 AuthenFilter,但是下面的示例将颠倒这个顺序:

<filter-mapping>
   <filter-name>AuthenFilter</filter-name>
   <url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
   <filter-name>LogFilter</filter-name>
   <url-pattern>/*</url-pattern>
</filter-mapping>

web.xml配置各节点说明

  • <filter>指定一个过滤器。

    • <filter-name>用于为过滤器指定一个名字,该元素的内容不能为空。

    • <filter-class>元素用于指定过滤器的完整的限定类名。

    • <init-param>元素用于为过滤器指定初始化参数,它的子元素<param-name>指定参数的名字,<param-value>指定参数的值。

    • 在过滤器中,可以使用FilterConfig接口对象来访问初始化参数。

  • <filter-mapping>元素用于设置一个 Filter 所负责拦截的资源。一个Filter拦截的资源可通过两种方式来指定:Servlet 名称和资源访问的请求路径

    • <filter-name>子元素用于设置filter的注册名称。该值必须是在<filter>元素中声明过的过滤器的名字

    • <url-pattern>は、フィルタがインターセプトするリクエストパス(フィルタに関連するURLスタイル)を設定します。

  • <servlet-name>は、フィルタがインターセプトする Servlet の名前を指定します。

  • <dispatcher>は、フィルタがインターセプトするリソースが Servlet コンテナで呼び出される方法を指定します。REQUEST、INCLUDE、FORWARD、ERRORのいずれか一つです。デフォルトはREQUESTです。ユーザーは、Filterがリソースの複数の呼び出し方法をインターセプトするように、複数の<dispatcher>子要素を設定できます。

  • <dispatcher>子要素が設定できる値とその意味

    • REQUEST:ユーザーが直接ページにアクセスした場合、Webコンテナがフィルタを呼び出します。ターゲットリソースがRequestDispatcherのinclude()またはforward()メソッドでアクセスされた場合、そのフィルタは呼び出されません。

    • INCLUDE:ターゲットリソースがRequestDispatcherのinclude()メソッドでアクセスされた場合、そのフィルタが呼び出されます。それ以外の場合、フィルタは呼び出されません。

    • FORWARD:ターゲットリソースがRequestDispatcherのforward()メソッドでアクセスされた場合、そのフィルタが呼び出されます。それ以外の場合、フィルタは呼び出されません。

    • ERROR:ターゲットリソースが宣言的な例外処理メカニズムで呼び出された場合、そのフィルタが呼び出されます。それ以外の場合、フィルタは呼び出されません。