[Tutorial] Tecnología de filtro de JavaWeb


1. Conceptos básicos

En la vida real, estamos involucrados en la filtración de té, la filtración de aguas residuales, la filtración de arena ...
y en JavaWeb, también involucra filtración. En este momento, necesitamos usar Filtro, y Filtro significa originalmente "filtro "., Su función es filtrar algunos contenidos y datos;
término técnico: es uno de los tres componentes principales de JavaWeb, los tres componentes principales son: Servlet, Filter, Listener.

2. Cómo trabajar

Inserte la descripción de la imagen aquí

Se puede ver que el filtro es equivalente a un filtro entre el navegador y el recurso Web. Antes de acceder al recurso, la solicitud se modifica, juzga e intercepta a través de una serie de filtros, y la respuesta también se puede modificar, juzgar, e interceptado Espera.

3. Cómo usar

Primero veamos un ejemplo de inicio de sesión. Este ejemplo tiene una página de inicio de sesión (login.jsp) y una página de inicio (main.jsp). Después de un inicio de sesión exitoso, es necesario saltar a main.jsp y mostrar el nombre de usuario.
Estructura del proyecto:
Inserte la descripción de la imagen aquí

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

Después de iniciar sesión correctamente, salta a la página de inicio y el efecto es el siguiente:
Inserte la descripción de la imagen aquí

Inserte la descripción de la imagen aquí
Pero si copia la ruta de main.jsp, también puede acceder a ella en otra página del navegador, pero no se muestra ningún nombre de usuario de inicio de sesión en este momento.
Inserte la descripción de la imagen aquí
Y lo que tenemos que hacer ahora es evitar que acceda a la página de inicio si no está conectado. Se necesita filtro en este momento. La implementación es la siguiente:

  • La clase personalizada implementa la interfaz Filter y anula el método doFilter
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 el filtro en el archivo 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>com.example.demo01.LoginFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>LoginFilter</filter-name>
        <url-pattern>/main.jsp</url-pattern>
    </filter-mapping>
</web-app>

De esta manera, si accede a la página de inicio directamente a través de la ruta de copia, no podrá acceder a ella y será interceptado, y luego saltará a la página de inicio de sesión para garantizar la seguridad de la página de inicio.
ps: Debe tenerse en cuenta que si se requiere la liberación, se debe llamar al método chain.doFilter (solicitud, respuesta), que es una declaración fija.

Interfaz 4.Filter

(1) interfaz javax.servlet.Filter, utilizada para describir el objeto de filtro. Siempre que otras clases implementen la interfaz de filtro, pueden implementar la función de filtro.
(2) La interfaz del filtro tiene principalmente 3 métodos, que representan el ciclo de vida del filtro. Los tres métodos son:
Inserte la descripción de la imagen aquí

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>

Efecto de ejecución Como
Inserte la descripción de la imagen aquí
Inserte la descripción de la imagen aquí
puede ver, el método de construcción se ejecuta antes que el método init.
Tanto el método de construcción como el método init se llaman cuando se inicia el servidor o se implementa el servicio; el
método doFilter se llama cuando el navegador solicita la ruta; el
método de destrucción se llama cuando el servicio se vuelve a implementar o se detiene.

5. Interfaz FilterConfig

(1) interfaz javax.servlet.FilterConfig, utilizada para describir la información de configuración del filtro.
(2) La interfaz FilterConfig tiene principalmente 4 métodos. Los 4 métodos son:
Inserte la descripción de la imagen aquí
(3) ¿Ha notado que la referencia de parámetro en el método init de Filter es la interfaz FilterConfig, por lo que la interfaz FilterConfig se puede llevar a cabo en el método init? llamada al método relacionado, el ejemplo es el siguiente:
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("销毁操作执行完毕了!");
    }
}

resultado de la operación
Inserte la descripción de la imagen aquí

6. Uso de múltiples filtros

Inserte la descripción de la imagen aquí
Según la figura anterior,
al solicitar, el orden de ejecución es: filtro 1 -> filtro 2 -> filtro 3;
al regresar, el orden de ejecución es: filtro 3 -> filtro 2 -> filtro 1.
Múltiples filtros pueden lograr un filtrado multicapa. La implementación consiste en crear múltiples clases java que hereden la interfaz Filter y configurarlas en web.xml.
El orden de ejecución de varios filtros está relacionado con la configuración de mapeo de URL, cualquiera que sea la configuración que se ejecute primero.
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>

Un filtro:

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() {
    
    

    }
}

Filtro B:

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() {
    
    

    }
}

Resultado de la operación: como
Inserte la descripción de la imagen aquí
puede ver, dado que la configuración de mapeo de filtros del filtro B está escrita en el frente, el filtro B se ejecuta primero cuando se solicita.

7. Ventajas del filtro

  • Darse cuenta de la "capacidad de conexión" del código, es decir, agregar o reducir un cierto módulo funcional, no afectará la ejecución normal del programa (por ejemplo, la función de inicio de sesión ahora puede iniciar sesión normalmente sin el filtro).
  • Se pueden escribir varios módulos con la misma lógica de procesamiento en el filtro para lograr la reutilización del código (como la autenticación para cada solicitud).

Supongo que te gusta

Origin blog.csdn.net/u012660464/article/details/109457850
Recomendado
Clasificación