[Tutorial] Filter Technology of JavaWeb


1. Basic concepts

In real life, we are involved in the filtration of tea, the filtration of sewage, the filtration of sand...
and in JavaWeb, it also involves filtration. At this time, we need to use Filter, and Filter originally means "filter". , Its role is to filter some content and data;
technical term: it is one of the three major components of JavaWeb, the three major components are: Servlet, Filter, Listener.

2. How to work

Insert picture description here

It can be seen that the filter is equivalent to a filter between the browser and the Web resource. Before accessing the resource, the request is modified, judged, and intercepted through a series of filters, and the response can also be modified, judged, and intercepted. Wait.

3. How to use

Let's look at a login example first. This example has a login page (login.jsp) and a home page (main.jsp). After the login is successful, it is required to jump to main.jsp and display the user name.
Project structure:
Insert picture description here

login.jsp:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>登录页面</title>
</head>
<body>
<form action="login" method="post">
    用户名: <input type="text" name="userName"/><br/>&nbsp;&nbsp;&nbsp;&nbsp;码:<input type="password" name="password"/><br/>
    <input type="submit" value="登录"/>
</form>
</body>
</html>

main.jsp:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>主页面</title>
</head>
<body>
<h1>登录成功,欢迎${sessionScope.userName}使用!</h1>
</body>
</html>

LoginServlet.java

@WebServlet(name = "LoginServlet", urlPatterns = "/login")
public class LoginServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 1.接收前端页面输入的用户名和密码信息并打印
        String userName = request.getParameter("userName");
        System.out.println("接收到的用户名为:" + userName);
        String password = request.getParameter("password");
        System.out.println("接收到的密码为:" + password);
        // 2.使用固定的用户名和密码信息来进行登录的校验
        if ("admin".equals(userName) && "123456".equals(password)) {
            System.out.println("登录成功,欢迎使用!");
            // 存储用户名信息
            request.getSession().setAttribute("userName", userName);
            response.sendRedirect("main.jsp");
        } else {
            System.out.println("用户名或密码错误,请重新输入!");
            request.getRequestDispatcher("login.jsp").forward(request, response);
        }
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request, response);
    }
}

After logging in successfully, it does jump to the homepage, and the effect is as follows:
Insert picture description here

Insert picture description here
But if you copy the path of main.jsp, you can also access it on another page of the browser, but there is no login user name displayed at this time.
Insert picture description here
And what we have to do now is to prevent him from accessing the homepage if he is not logged in. Filter is needed at this time. The implementation is as follows:

  • The custom class implements the Filter interface and overrides the doFilter method
public class LoginFilter implements Filter {
    
    
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    
    

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
    
    
        // 1.实现对用户访问主页面的过滤操作,也就是只有用户登录后才能访问主页面,否则一律拦截
        // 判断session中是否已有用户名信息,若没有则进行拦截,否则放行
        HttpServletRequest httpServletRequest = (HttpServletRequest)servletRequest;
        HttpSession session = httpServletRequest.getSession();
        Object userName = session.getAttribute("userName");
        // 获取Servlet的请求路径
        String servletPath = httpServletRequest.getServletPath();
        // 若没有登录,则回到登录页面
        if (null == userName && !servletPath.contains("login")) {
    
    
            servletRequest.getRequestDispatcher("login.jsp").forward(servletRequest, servletResponse);
        } else {
    
    
            // 若已经登录,则放行
            filterChain.doFilter(servletRequest, servletResponse);
        }
    }

    @Override
    public void destroy() {
    
    

    }
}

  • Configure the filter in the web.xml file
<?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>com.example.demo01.LoginFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>LoginFilter</filter-name>
        <url-pattern>/main.jsp</url-pattern>
    </filter-mapping>
</web-app>

In this way, if you access the homepage directly through the copy path, you will not be able to access it, and will be intercepted, and then jump to the login page to ensure the security of the homepage.
ps: It should be noted that if release is required, the method chain.doFilter(request,response) must be called, which is a fixed statement.

4.Filter interface

(1) javax.servlet.Filter interface, used to describe the filter object. As long as other classes implement the Filter interface, they can implement the filter function.
(2) The Filter interface mainly has 3 methods, which represent the life cycle of the Filter. The three methods are:
Insert picture description here

public class LifeFilter implements Filter {
    
    
    public LifeFilter() {
    
    
        System.out.println("构造方法执行!");
    }

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    
    
        System.out.println("初始化操作正在火热进行中...");
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
    
    
        System.out.println("阻拦一切不合理的访问哦!");
    }

    @Override
    public void destroy() {
    
    
        System.out.println("销毁操作执行完毕了!");
    }
}
<?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>LifeFilter</filter-name>
        <filter-class>com.lagou.demo02.LifeFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>LifeFilter</filter-name>
        <url-pattern>*.html</url-pattern>
    </filter-mapping>
</web-app>

Running effect As
Insert picture description here
Insert picture description here
you can see, the construction method is executed before the init method.
Both the construction method and the init method are called when the server is started or the service is deployed; the
doFilter method is called when the browser requests the path; the
destroy method is called when the service is redeployed or stopped.

5. FilterConfig interface

(1) javax.servlet.FilterConfig interface, used to describe the configuration information of the filter.
(2) The FilterConfig interface mainly has 4 methods. The 4 methods are:
Insert picture description here
(3) Have you noticed that the parameter reference in the init method of Filter is the FilterConfig interface, so the FilterConfig interface can be carried out in the init method The related method call, the example is as follows:
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>LifeFilter</filter-name>
        <filter-class>com.example.demo02.LifeFilter</filter-class>
        <init-param>
            <param-name>userName</param-name>
            <param-value>admin</param-value>
        </init-param>
        <init-param>
            <param-name>password</param-name>
            <param-value>123456</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>LifeFilter</filter-name>
        <url-pattern>*.html</url-pattern>
    </filter-mapping>
</web-app>

LifeFilter.java:

public class LifeFilter implements Filter {
    
    
    public LifeFilter() {
    
    
        System.out.println("构造方法执行!");
    }

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    
    
        System.out.println("初始化操作正在火热进行中...");
        System.out.println("获取到的过滤器名称为:" + filterConfig.getFilterName());
        String userName = filterConfig.getInitParameter("userName");
        System.out.println("获取到指定初始化参数的数值为:" + userName);  // admin
        Enumeration<String> initParameterNames = filterConfig.getInitParameterNames();
        while (initParameterNames.hasMoreElements()) {
    
    
            // userName password
            System.out.println("获取到的初始化参数名为:" + initParameterNames.nextElement());
        }
        ServletContext servletContext = filterConfig.getServletContext();
        System.out.println("获取到的上下文对象是:" + servletContext);
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
    
    
        System.out.println("阻拦一切不合理的访问哦!");
        filterChain.doFilter(servletRequest, servletResponse);
    }

    @Override
    public void destroy() {
    
    
        System.out.println("销毁操作执行完毕了!");
    }
}

operation result
Insert picture description here

6. Use of multiple filters

Insert picture description here
According to the above figure,
when requesting, the order of execution is: filter 1 -> filter 2 -> filter 3;
when returning, the order of execution is: filter 3 -> filter 2 -> filter 1.
Multiple filters can achieve multi-layer filtering. The implementation is to create multiple java classes that inherit the Filter interface and configure them in web.xml.
The order of execution of multiple filters is related to the url mapping configuration, whichever configuration is executed first.
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>BFilter</filter-name>
        <filter-class>com.example.demo02.BFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>BFilter</filter-name>
        <url-pattern>*.avi</url-pattern>
    </filter-mapping>

    <filter>
        <filter-name>AFilter</filter-name>
        <filter-class>com.example.demo02.AFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>AFilter</filter-name>
        <url-pattern>*.avi</url-pattern>
    </filter-mapping>
</web-app>

A filter:

public class AFilter implements Filter {
    
    
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    
    

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
    
    
        System.out.println("这是第一道防线!");
        filterChain.doFilter(servletRequest, servletResponse);
        System.out.println("第一道防线返回!");
    }

    @Override
    public void destroy() {
    
    

    }
}

B filter:

public class BFilter implements Filter {
    
    
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    
    

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
    
    
        System.out.println("这是第二道防线!");
        filterChain.doFilter(servletRequest, servletResponse);
        System.out.println("第二道防线返回!");
    }

    @Override
    public void destroy() {
    
    

    }
}

Operation result: As
Insert picture description here
you can see, since the filter-mapping configuration of filter B is written in the front, filter B is executed first when requesting.

7. Filter advantages

  • Realizing the "pluggability" of the code, that is, adding or reducing a certain functional module, will not affect the normal execution of the program (for example, the login function just now can log in normally without the filter).
  • Multiple modules with the same processing logic can be written in the filter to achieve code reuse (such as authentication for each request).

Guess you like

Origin blog.csdn.net/u012660464/article/details/109457850