JavaWeb速度フィルター

目次

1. フィルターを使用したクイックスタート

        1.基本的な紹介: 

        2. 基本原則: 

        3. 開始の例: 

        4. ライフサイクル: 

2. FilterConfig と FilterChain

        1.フィルター構成: 

            1° 基本的な紹介

            2° 応用例

        2.フィルターチェーン: 

            1° 基本的な紹介 

            2° 基本原則 

            3° 応用例 

            4° 使用方法の詳細


1. フィルターを使用したクイックスタート

        1.基本的な紹介: 

        Filter は、JavaWeb の 3 つの主要コンポーネント (サーブレット プログラム、 リスナー フィルター ) の 1 つです。リスナーとフィルターは本質的にはサーブレット仕様に属しますが、機能が独立しているため、JavaWeb の 3 つの主要コンポーネントとして個別に見なされます。
        Filter はインターフェースであり、頻繁に使用されます。従来の検証方法によって引き起こされるコードの冗長性や機能の重複の問題を解決するだけでなく、フィルターはログ操作、権限チェック、トランザクション管理などのシナリオにも適用できます。

        2. 基本原則: 

        (1)ブラウザが HTTP リクエストをサーバーに送信すると、 Tomcat は、web.xml 設定ファイルで設定されたフィルタと、指定されたフィルタの URL パターン ルールに基づいて、現在のリクエストにフィルタが必要かどうかを判断しますPS: フィルタリング ルールはプログラマが手動で指定できます。

        (2)フィルタが必要ないと判断した場合は、Web リソース(サーブレット、Web 静的ページなど)に直接アクセスします。

        (3) Tomcatは必要と判断した場合、ビジネス要件に応じて検証を行い、正当な検証であればアクセスを続行し、正当な検証でなければ を返しますPS: 返される特定の URL は、プログラマが手動で指定することもできます。

        (4) Tomcat がサーブレットやその他の Web リソースを呼び出す前に、最初にフィルターと一致します。つまり、要求された URL (req オブジェクトによってカプセル化されている) に従って、フィルターの URL を管理するコンテナー内で一致します。一致が成功すると、管理されます。Filter コンテナ内で対応する Filter インスタンスを見つけて、その doFilter メソッドを呼び出します。一致するものがない場合は、Web リソースに直接アクセスします(手書きの Tomcat の最下層でサーブレットを管理するために使用される 2 つの Map コンテナーに連絡します)

        3. 開始の例: 

                ユーザーのログイン操作に使用されるlogin.jspページを定義します。データはLoginCheckServletに送信されます。パスワードが233に等しい場合、管理者ログインとみなされ、リクエストはadministration.jspページに転送されます。 (ユーザー管理ページ)。Administration.jsp ページはターゲット パッケージの下で定義され、フィルタ LoginFilter を定義し、フィルタリング ルールは /target/* です

                login.jsp ページのコードは次のとおりです。 

<%--
    User : Cyan_RA9
    Version : 21.0
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>login</title>
    <style>
        table, td {
            border: cornflowerblue 2px solid;
            background-color: lightcyan;
            border-collapse: collapse;
            padding: 5px;
        }
    </style>
</head>
<body>
<form action="<%= request.getContextPath() %>/loginCheckServlet" method="post">
    <table>
        <tr>
            <th colspan="2">Manage the login</th>
        </tr>
        <tr>
            <td>Username : </td>
            <td><input type="text" name="username"/></td>
        </tr>
        <tr>
            <td>Password : </td>
            <td><input type="password" name="password"/></td>
        </tr>
        <tr>
            <td><input type="submit" value="submit"/></td>
            <td><input type="reset" value="reset"/></td>
        </tr>
    </table>
</form>
</body>
</html>

                ページ効果は次のとおりです。 

                LoginCheckServlet クラスのコードは次のとおりです。 

package filter;

import jakarta.servlet.RequestDispatcher;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

import java.io.IOException;

/**
 * @author : Cyan_RA9
 * @version : 21.0
 */
@WebServlet(urlPatterns = {"/loginCheckServlet"})
public class LoginCheckServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String username = req.getParameter("username");
        String password = req.getParameter("password");
        RequestDispatcher requestDispatcher = null;

        if ("233".equals(password)) {
            //若验证合法,向session中放入用户名
            req.getSession().setAttribute("username", username);

            requestDispatcher = req.getRequestDispatcher("/target/administration.jsp");
            requestDispatcher.forward(req, resp);
        } else {
            requestDispatcher = req.getRequestDispatcher("/login.jsp");
            requestDispatcher.forward(req, resp);
        }
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doPost(req, resp);
    }
}

                Administration.jsp ページのコードは次のとおりです。 

<%--
    User : Cyan_RA9
    Version : 21.0
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>target</title>
    <%--<base href="<%= request.getContextPath() %>/img/"/>--%>
    <style>
        table, td {
            border: 2px lightpink solid;
            background-color: lightcyan;
            border-collapse: collapse;
            padding: 10px;
            margin-left: auto;
            margin-right: auto;
        }
    </style>
</head>
<body>
<table width="500px">
    <tr>
        <th>ID</th>
        <th>Username</th>
        <th>Function</th>
    </tr>
    <tr>
        <td>100011</td>
        <td>Cyan</td>
        <td><a href="none">删除用户</a></td>
    </tr>
    <tr>
        <td>100023</td>
        <td>Rain</td>
        <td><a href="none">删除用户</a></td>
    </tr>
    <tr>
        <td>100033</td>
        <td>Ice</td>
        <td><a href="none">删除用户</a></td>
    </tr>
    <tr>
        <td>100041</td>
        <td>Five</td>
        <td><a href="none">删除用户</a></td>
    </tr>
    <tr>
        <td>100099</td>
        <td>Irving</td>
        <td><a href="none">删除用户</a></td>
    </tr>
</table>
</body>
</html>

                ページ効果は次のとおりです。 

                LoginFilter フィルターを定義して、ユーザーによる不正なアクセスを遮断し、管理者以外のユーザー管理インターフェイスへの不正なアクセスを防ぎます。LoginFilter クラスのコードは次のとおりです。 

package filter;

import jakarta.servlet.*;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpSession;

import java.io.IOException;

public class LoginFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("LoginFilter is initialized~");
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("LoginFilter's doFilter method is invoked~");
        /**
         * (1) 每次调用该Filter对象时,都会动态绑定调用doFilter方法;
         * (2) 若doFilter方法中没有调用继续请求的方法,那么对请求的资源的访问就会卡在这里。
         * (3) Tomcat在调用Filter之前,就已经创建好了req和resp对象,并且req中已经封装好了
         *      HTTP请求的相关信息。因此,可以通过req对象来获取到这些信息,例如URL,session,
         *      等等,从而实现日志操作,权限检查,事务管理等业务需求。
         * (4) 可以通过filterChain对象的doFilter方法将servletRequest对象和
         *       servletResponse对象传递下去。
         * (5) 特别注意:请求转发不经过过滤器!(在服务器端)
         */

        //动态---动态绑定的使用
        HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
        HttpSession session = httpServletRequest.getSession();

        //session中的属性可能之后会用到(eg : log),因此可以单独做接收。
        String username = (String) session.getAttribute("username");
        if (username != null) {
            filterChain.doFilter(servletRequest, servletResponse);
        } else {
            RequestDispatcher requestDispatcher = servletRequest.getRequestDispatcher("/login.jsp");
            requestDispatcher.forward(servletRequest, servletResponse);
        }
        /**
         * 关于filterChain.doFilter方法 :
         * (1) 该方法执行,会继续访问URL的目标资源;
         * (2) 创建好的servletRequest对象和servletResponse对象会传递给目标资源(servlet/jsp,etc)
         * (3) 因此,目标资源中获得的这两个对象是相同的对象 (同一次HTTP请求中)
         */
    }

    @Override
    public void destroy() {
        System.out.println("LoginFilter is destroyed~");
    }
}

                web.xml 構成ファイルでフィルターを構成します。コードは次のとおりです。 

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">

    <filter>
        <filter-name>LoginFilter</filter-name>
        <filter-class>filter.LoginFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>LoginFilter</filter-name>
        <url-pattern>/target/*</url-pattern>
    </filter-mapping>
    <!--
        此处的<url-pattern>即指过滤规则,当请求的URL满足该条件时,
        都需要走该过滤器。这时Tomcat会调用该Filter的doFilter()方法。
        (回顾URL四种匹配模式)
    -->
</web-app>

                ランニング効果:(下のGIF)

        4. ライフサイクル: 

        (1) Web プロジェクトが開始されると、Tomcat はリフレクション メカニズムに基づいて対応する Filter インスタンスを作成し ( Filter は 1 回だけ作成されます)、Tomcat が管理するコンテナに保存します。

        (2) Tomcat は、デフォルトのパラメーターなしのコンストラクターとフィルターに対応する init メソッドを実行します ( init メソッドは HTTP リクエストで 1 回だけ呼び出されます)。フィルター インスタンスはメモリ内に常駐します

        (3) Filter インスタンスを作成するとき、Tomcat は FilterConfig オブジェクトも作成し、それを init メソッドを通じて渡します。プログラマは、FilterConfig オブジェクトを通じてフィルタの関連構成情報を取得できます。

        (4)クライアントから HTTP リクエストが送信されると、Tomcat は HTTP リクエストの URL がフィルタの <url-pattern> と一致するかどうかを判定し、一致する場合は対応するフィルタの doFilter メソッドを呼び出します。さらに、 Tomcat は ServletRequest オブジェクト、ServletResponse オブジェクト、および FilterChain オブジェクトを同時に作成し、それらを doFilter メソッドを通じて渡します

        (5) Web プロジェクトが停止したら、Filter インスタンスを破棄し、destroy メソッドを呼び出します。


2. FilterConfig と FilterChain

        1.フィルター構成: 

            1° 基本的な紹介

        FilterConfig はFilter フィルターの構成クラスです。FilterConfigオブジェクトの目的は、 Filter フィルターの構成コンテンツを取得することです。

            2° 応用例

                web.xml でフィルターを再構成します。web.xml コードは次のとおりです。 

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">

    <filter>
        <filter-name>LoginFilter</filter-name>
        <filter-class>filter.LoginFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>LoginFilter</filter-name>
        <url-pattern>/target/*</url-pattern>
    </filter-mapping>

    <filter>
        <filter-name>FilterConfig_Demo</filter-name>
        <filter-class>filter.FilterConfig_Demo</filter-class>
        <init-param>
            <param-name>color</param-name>
            <param-value>cyan</param-value>
        </init-param>
        <init-param>
            <param-name>sport</param-name>
            <param-value>basketball</param-value>
        </init-param>
        <init-param>
            <param-name>fruit</param-name>
            <param-value>grape</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>FilterConfig_Demo</filter-name>
        <url-pattern>/filterConfig_Demo</url-pattern>
    </filter-mapping>
</web-app>

               FilterConfig_Demo クラスのコードは次のとおりです。 

package filter;

import jakarta.servlet.*;

import java.io.IOException;
import java.util.Enumeration;

public class FilterConfig_Demo implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        //获取当前过滤器的名称
        String filterName = filterConfig.getFilterName();
        System.out.println("filterName = " + filterName);

        //获取当前过滤器中配置的参数(根据name获取指定参数)
        String color = filterConfig.getInitParameter("color");
        String fruit = filterConfig.getInitParameter("fruit");
        String sport = filterConfig.getInitParameter("sport");
        System.out.println("color = " + color);
        System.out.println("fruit = " + fruit);
        System.out.println("sport = " + sport);

        //获取当前过滤器中配置的全部参数
        Enumeration<String> initParameterNames = filterConfig.getInitParameterNames();
        while (initParameterNames.hasMoreElements()) {
            System.out.println("parameter's name = " + initParameterNames.nextElement());
        }
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        RequestDispatcher requestDispatcher = servletRequest.getRequestDispatcher("/Listener_Filter/login.jsp");
        requestDispatcher.forward(servletRequest, servletResponse);
    }

    @Override
    public void destroy() {
        Filter.super.destroy();
    }
}

                ランニング効果:(下のGIF)

        2.フィルターチェーン: 

            1° 基本的な紹介 

        FilterChain、フィルターチェーン。一部の複雑なサービスを処理する場合、1 つのフィルタでは不十分であり、複数のフィルタを設計してフィルタリング タスクをまとめて完了し、フィルタ チェーンを形成できます

            2° 基本原則 

                以下に示すように: 

            3° 応用例 

                Filter_Demo1 と Filter_Demo2 という 2 つのフィルターを定義し、web.xml 構成ファイルで 1--->2 の順序で構成します
                web.xml 構成ファイルのコードは次のとおりです。 

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">

    <filter>
        <filter-name>Filter_Demo1</filter-name>
        <filter-class>filter.Filter_Demo1</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>Filter_Demo1</filter-name>
        <url-pattern>/img/*</url-pattern>
    </filter-mapping>

    <filter>
        <filter-name>Filter_Demo2</filter-name>
        <filter-class>filter.Filter_Demo2</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>Filter_Demo2</filter-name>
        <url-pattern>/img/cornflower.jpg</url-pattern>
    </filter-mapping>
</web-app>

                Filter_Demo1 クラスのコードは次のとおりです。 

package filter;

import jakarta.servlet.*;

import java.io.IOException;

public class Filter_Demo1 implements Filter {
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("Filter_Demo1 ———— doFilter's fore code");

        filterChain.doFilter(servletRequest, servletResponse);

        System.out.println("Filter_Demo1 ———— doFilter's end code");
    }
}

                Filter_Demo2 クラスのコードは次のとおりです。

package filter;

import jakarta.servlet.*;

import java.io.IOException;

public class Filter_Demo2 implements Filter {
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("Filter_Demo2 ———— doFilter's fore code");

        filterChain.doFilter(servletRequest, servletResponse);

        System.out.println("Filter_Demo2 ———— doFilter's end code");
    }
}

                ランニングエフェクト:(GIF)

            4° 使用方法の詳細

        (1) 同じ HTTP リクエスト内で、同じスレッドが複数のフィルターを渡してターゲット リソースにアクセスする役割を果たします。(複数のフィルターが同じリクエスト オブジェクトを使用します)

        (2) HTTP リクエストの URL が設定されたフィルターの URL パターンと一致する場合にのみ、フィルターの doFilter メソッドが実行され、同じ HTTP リクエスト内で複数のフィルターが正常に一致した場合は、それらのフィルターが順番に実行されます。 、フィルター呼び出しチェーンを形成します。(複数のフィルターの実行順序は、web.xml 構成ファイルで構成された順序と一致します)

        (3) filterChain.doFilter()メソッドが実行されると、次に一致するフィルタのdoFilterメソッドが実行されます。現在のフィルターの後に他に一致するフィルターがない場合、ターゲット リソースが実行されます

        System.out.println("END------------------------------------------ -------------------------------------------------- ------------------------------------");

おすすめ

転載: blog.csdn.net/TYRA9/article/details/132382280