JavaWeb Speed Filter

Table of contents

1. Quick Start with Filter

        1.Basic introduction: 

        2. Basic principles: 

        3. Getting Started Example: 

        4. Life cycle: 

2. FilterConfig and FilterChain

        1.FilterConfig : 

            1° Basic introduction

            2° Application examples

        2.FilterChain : 

            1° Basic introduction 

            2° Basic principles 

            3° Application examples 

            4° Usage details


1. Quick Start with Filter

        1.Basic introduction: 

        Filter is one of the three major components of JavaWeb (Servlet program, Listener , Filter ). Listener and Filter essentially belong to the Servlet specification, but due to their independent functions, they are separately regarded as the three major components of JavaWeb.
        Filter is an interface and is used frequently. In addition to solving the problems of code redundancy and functional duplication caused by traditional verification methods, Filter can also be applied to log operations, permission checks, transaction management and other scenarios.

        2. Basic principles: 

        (1) When the browser sends an HTTP request to the server, Tomcat will determine whether the current request requires a filter based on the filter configured in the web.xml configuration file and the url-pattern rule of the specified filter . PS: Filtering rules can be manually specified by programmers.

        (2) If it is judged that no filter is needed, access the Web resources (servlet, web static page, etc.) directly.

        (3) If it is judged necessary, Tomcat will verify according to business requirements. If the verification is legal, the access will continue; if the verification is not legal, it will return . PS: The specific returned URL can also be manually specified by the programmer.

        (4) Before Tomcat calls servlet and other Web resources, it will first match the Filter - that is, according to the requested URL (encapsulated by the req object), it will be matched in the container that manages the Filter's URL . If the match is successful, it will be managed. Find the corresponding Filter instance in the Filter container and call its doFilter method; if there is no match, access the web resource directly . (Contact the two Map containers used to manage servlets in the bottom layer of handwritten Tomcat)

        3. Getting Started Example: 

                Define the login.jsp page, which is used for user login operations. The data is submitted to LoginCheckServlet. If the password is equal to 233, it is considered to be an administrator login, and the request is forwarded to the administration.jsp page (user management page). The administration.jsp page is defined under the target package, defines the filter LoginFilter, and the filtering rule is /target/* .

                The login.jsp page code is as follows: 

<%--
    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>

                The page effect is as follows: 

                The LoginCheckServlet class code is as follows: 

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);
    }
}

                The administration.jsp page code is as follows: 

<%--
    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>

                The page effect is as follows: 

                Define a LoginFilter filter to intercept illegal access by users and prevent non-administrators from illegally accessing the user management interface. The LoginFilter class code is as follows: 

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~");
    }
}

                Configure Filter in the web.xml configuration file, the code is as follows: 

<?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>

                Running effect: (GIF below)

        4. Life cycle: 

        (1) When the Web project starts , Tomcat will create the corresponding Filter instance based on the reflection mechanism ( a Filter is only created once ) and save it in the container maintained by Tomcat.

        (2) Tomcat will execute the default parameterless constructor and init method corresponding to the Filter ( the init method will only be called once in an HTTP request ). Filter instances will reside in memory .

        (3) When creating a Filter instance, Tomcat will also create a FilterConfig object and pass it in through the init method. Programmers can obtain the relevant configuration information of the Filter through the FilterConfig object.

        (4) When an HTTP request is sent from the client, Tomcat will determine whether the URL of the HTTP request matches the <url-pattern> of a filter. If it matches, it will call the doFilter method of the corresponding filter. Moreover, Tomcat will create a ServletRequest object, a ServletResponse object, and a FilterChain object at the same time, and pass them in through the doFilter method .

        (5) When the Web project stops , destroy the Filter instance and call the destroy method.


2. FilterConfig and FilterChain

        1.FilterConfig : 

            1° Basic introduction

        FilterConfig is the configuration class of Filter filter. The purpose of the FilterConfig object is to obtain the configuration content of the Filter filter.

            2° Application examples

                Reconfigure a filter in web.xml. The web.xml code is as follows: 

<?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>

               The FilterConfig_Demo class code is as follows: 

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();
    }
}

                Running effect: (GIF below)

        2.FilterChain : 

            1° Basic introduction 

        FilterChain, filter chain. When dealing with some complex services, one filter is not enough. Multiple filters can be designed to complete the filtering tasks together to form a filter chain .

            2° Basic principles 

                As shown below: 

            3° Application examples 

                Define two filters, namely Filter_Demo1 and Filter_Demo2, and configure them in the order of 1--->2 in the web.xml configuration file .
                The web.xml configuration file code is as follows: 

<?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>

                The Filter_Demo1 class code is as follows: 

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");
    }
}

                The Filter_Demo2 class code is as follows:

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");
    }
}

                Running effect: (GIF)

            4° Usage details

        (1) In the same HTTP request, the same thread is responsible for passing multiple Filters and accessing the target resource. ( And multiple Filters use the same request object )

        (2) Only when the URL of the HTTP request matches the url-pattern of the configured filter, the doFilter method of the filter will be executed ; and if multiple Filters are successfully matched in the same HTTP request, they will be executed sequentially. , forming a Filter call chain. ( The execution order of multiple Filters is consistent with the order configured in the web.xml configuration file )

        (3) When the filterChain.doFilter() method is executed, the doFilter method of the next matching filter will be executed. If there are no other matching filters after the current filter, the target resource is executed .

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

Guess you like

Origin blog.csdn.net/TYRA9/article/details/132382280