likes
comments
collection
share

🐲 一文搞懂 【过滤器】 Filter

作者站长头像
站长
· 阅读数 32

1、提出问题

🐲 一文搞懂  【过滤器】 Filter

2、三要素

①拦截

作为过滤器这样的组件,首先需要能够把请求拦截住,然后才能做后续的相关操作。

②过滤

通常是基于业务功能的需要,在拦截到请求之后编写特定的代码,对请求进行相关的处理或检查。

最典型的就是登录检查:检查当前请求是否已经登录。

③放行

如果当前请求满足过滤条件,那么就应该放行:让请求继续去找它原本要访问的资源。

3、HelloWorld

①创建Filter类

要求实现接口:jakarta.servlet.Filter。更简洁的做法是继承jakarta.servlet.http.HttpFilter类。

/**  
 * 假设请求中携带一个特定的请求参数表示用户已经登录,可以访问私密资源。  
 * 特定请求参数名称:message,特定的值:monster  
 */public class Filter01HelloWorld extends HttpFilter {  
  
    @Override  
    public void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException {  
  
        // 1、获取请求参数  
        String message = request.getParameter("message");  
  
        // 2、检查请求参数是否满足预设的要求  
        if ("monster".equals(message)) {  
            // 3、满足条件的请求放行  
            chain.doFilter(request, response);  
        } else {  
            // 4、不满足预设条件就把请求转发到拒绝页面  
            request.getRequestDispatcher("/WEB-INF/pages/forbidden.html").forward(request, response);  
        }  
  
    }  
}

②注册Filter类

<!-- 注册 Filter --><filter>  
    <!-- Filter 友好名称 -->  
    <filter-name>Filter01HelloWorld</filter-name>  
  
    <!-- Filter 全类名 -->  
    <filter-class>com.filter.filter.Filter01HelloWorld</filter-class>  
</filter>  
<filter-mapping>  
    <!-- 引用 Filter 友好名称 -->  
    <filter-name>Filter01HelloWorld</filter-name>  
  
    <!-- 当前 Filter 要拦截的请求的 URL 地址的匹配模式 -->  
    <url-pattern>/private/*</url-pattern>  
</filter-mapping>

4、Filter生命周期

Servlet生命周期Filter生命周期
创建对象第一次接收到请求创建对象通过反射调用无参构造器执行一次Web应用启动时创建对象通过反射调用无参构造器执行一次
初始化创建对象之后立即执行init()方法执行一次创建对象之后立即执行init()方法执行一次
干活每一次接收到请求,处理请求service()方法可能多次每一次接收到请求,过滤请求doFilter()方法
销毁Web应用卸载时执行destroy()方法执行一次Web应用卸载时执行destroy()方法执行一次
  
import jakarta.servlet.FilterChain;  
import jakarta.servlet.ServletException;  
import jakarta.servlet.http.HttpFilter;  
import jakarta.servlet.http.HttpServletRequest;  
import jakarta.servlet.http.HttpServletResponse;  
  
import java.io.IOException;  
  
public class Filter02LifeCycle extends HttpFilter {  
  
    // 生命周期相关:无参构造器  
    public Filter02LifeCycle() {  
        System.out.println("Filter02LifeCycle 执行了无参构造器!创建了对象!");  
    }  
  
    // 生命周期相关:初始化操作  
    @Override  
    public void init() throws ServletException {  
        System.out.println("Filter02LifeCycle 执行了init()方法,初始化完成!");  
    }  
  
    // 生命周期相关:清理或销毁操作  
    @Override  
    public void destroy() {  
        System.out.println("Filter02LifeCycle 执行了destroy()方法!");  
    }  
  
    // 生命周期相关:过滤请求操作  
    @Override  
    protected void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {  
        System.out.println("Filter02LifeCycle 执行了doFilter()方法!");  
        chain.doFilter(request, response);  
    }  
}
<filter>  
    <filter-name>Filter02LifeCycle</filter-name>  
    <filter-class>com.filter.filter.Filter02LifeCycle</filter-class>  
</filter>  
<filter-mapping>  
    <filter-name>Filter02LifeCycle</filter-name>  
    <!-- 拦截当前 Web 应用下的所有资源 -->  
    <url-pattern>/*</url-pattern>  
</filter-mapping>

5、Filter链

①Filter链的形成

当多个Filter拦截同一个资源,那么访问这个资源的请求就需要逐个经过各个Filter。

🐲 一文搞懂  【过滤器】 Filter

②Filter链的执行

  • 每个Filter都放行,请求才能到达原本要访问的目标资源
  • 有任何一个Filter没有放行,那么后面的Filter和目标资源就都不会被执行
  • Filter如果没有放行,那么需要给出响应。例如:转发、重定向等方式。
  • Filter如果没有放行,也没有给出响应,那么浏览器窗口就是一片空白。

③Filter链执行的顺序

参考web.xml中filter-mapping的顺序:

  • filter-mapping靠前的:Filter执行时在外层(先执行:先开始,后结束)
  • filter-mapping靠后的:Filter执行时在内层(后执行:后开始,先结束)

本质上来说,同一个Filter链中的各个方法都是在同一个线程里依次调用的方法:

④引申

  • 方法栈:同一个线程内,先调用的方法后结束;后调用的方法先结束
  • 同一个线程内,所有操作本质上都是按顺序执行的。前面操作没有执行完,后面操作就需要等待。
  • 在不同线程(或进程)内,各个操作都不需要等待其它线程中操作的执行。
  • 同步:操作之间需要彼此等待,按顺序依次执行
  • 异步:操作之间不需要彼此等待,同时各自执行

6、登录检查练习

①需求说明

凡是对Soldier增删改查操作,都需要登录才能访问

②创建Filter类

import com.demo.entity.User;  
import jakarta.servlet.FilterChain;  
import jakarta.servlet.ServletException;  
import jakarta.servlet.http.HttpFilter;  
import jakarta.servlet.http.HttpServletRequest;  
import jakarta.servlet.http.HttpServletResponse;  
import jakarta.servlet.http.HttpSession;  
  
import java.io.IOException;  
  
public class LoginFilter extends HttpFilter {  
  
    @Override  
    protected void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {  
        HttpSession session = request.getSession();  
        User loginUser = (User) session.getAttribute("loginUser");  
        if (loginUser == null) {  
            request.setAttribute("message", "请登录后再操作!");  
            request.getRequestDispatcher("/UserServlet/toLoginPage").forward(request, response);  
        } else {  
            chain.doFilter(request, response);  
        }  
    }  
}

③注册Filter类

<filter>  
    <filter-name>loginFilter</filter-name>  
    <filter-class>com.demo.filter.LoginFilter</filter-class>  
</filter>  
<filter-mapping>  
    <filter-name>loginFilter</filter-name>  
    <url-pattern>/SoldierServlet/*</url-pattern>  
</filter-mapping>
转载自:https://juejin.cn/post/7339042939603419188
评论
请登录