🐲 一文搞懂 【过滤器】 Filter

1、提出问题

2、三要素

①拦截

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

②过滤

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

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

③放行

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

3、HelloWorld

①创建Filter类

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

java 复制代码
/**  
 * 假设请求中携带一个特定的请求参数表示用户已经登录,可以访问私密资源。  
 * 特定请求参数名称: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类

xml 复制代码
<!-- 注册 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()方法 执行一次
java 复制代码
  
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);  
    }  
}
xml 复制代码
<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链执行的顺序

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

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

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

④引申

  • 方法栈:同一个线程内,先调用的方法后结束;后调用的方法先结束

  • 同一个线程内,所有操作本质上都是按顺序执行的。前面操作没有执行完,后面操作就需要等待。

  • 在不同线程(或进程)内,各个操作都不需要等待其它线程中操作的执行。

  • 同步:操作之间需要彼此等待,按顺序依次执行

  • 异步:操作之间不需要彼此等待,同时各自执行

6、登录检查练习

①需求说明

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

②创建Filter类

java 复制代码
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类

xml 复制代码
<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>
相关推荐
北极无雪16 分钟前
Spring源码学习(拓展篇):SpringMVC中的异常处理
java·开发语言·数据库·学习·spring·servlet
VXbishe23 分钟前
(附源码)基于springboot的“我来找房”微信小程序的设计与实现-计算机毕设 23157
java·python·微信小程序·node.js·c#·php·课程设计
YONG823_API1 小时前
电商平台数据批量获取自动抓取的实现方法分享(API)
java·大数据·开发语言·数据库·爬虫·网络爬虫
扬子鳄0081 小时前
java注解的处理器
java
Amagi.1 小时前
Spring中Bean的作用域
java·后端·spring
2402_857589361 小时前
Spring Boot新闻推荐系统设计与实现
java·spring boot·后端
繁依Fanyi1 小时前
旅游心动盲盒:开启个性化旅行新体验
java·服务器·python·算法·eclipse·tomcat·旅游
J老熊1 小时前
Spring Cloud Netflix Eureka 注册中心讲解和案例示范
java·后端·spring·spring cloud·面试·eureka·系统架构
蜜桃小阿雯2 小时前
JAVA开源项目 旅游管理系统 计算机毕业设计
java·开发语言·jvm·spring cloud·开源·intellij-idea·旅游
CoderJia程序员甲2 小时前
重学SpringBoot3-集成Redis(四)之Redisson
java·spring boot·redis·缓存