过滤器 Filter vs 拦截器 Interceptor

news/2024/10/4 0:04:47 标签: java, 后端, 学习, filter, interceptor, 过滤器, 拦截器

之前已经详细介绍过了过滤器Filter 和 拦截器Interceptor 了,本文将两种拦截请求的技术做一个对比讲解!

回顾:   过滤器Filter详解        拦截器Interceptor详解

一、过滤器 Filter

Filter,中文名过滤器,是 Servlet 规范中定义的一种拦截机制,如同应用的第一道防线——护城河,所有 HTTP 请求都要经过它的洗礼。它独立于 Spring 框架,地位超然,不受框架限制,任何 Web 应用都可以使用它来实现通用的请求处理逻辑。

1.1 Filter 的工作原理

想象一下,Web 应用就像一座城堡,而 Filter 就是城堡外围的护城河,所有进出城堡的请求都必须经过它。

  1. 请求抵达,Filter 拦截: 当浏览器发送请求到服务器时,请求首先会被 Servlet 容器拦截,就像任何访客都必须先经过护城河的检查。

  2. Filter 链,层层把关: 多个 Filter 可以组成一条链,按照预先定义的顺序依次对请求进行处理,就像护城河上设置了多道关卡,每道关卡都有不同的检查项目。

  3. FilterChain:放行或拦截的决定者: FilterChain 对象就像关卡的守卫队长,它负责调用 Filter 链中的下一个 Filter,或者在所有 Filter 执行完毕后将请求放行到目标资源,最终将响应返回给客户端。

  4. Filter 的生命周期:

    • init(FilterConfig): 在 Filter 初始化时调用一次,可以用来读取配置文件、初始化资源等,就像关卡建立时进行的准备工作。

    • doFilter(ServletRequest, ServletResponse, FilterChain): 每次请求都会调用,实现具体的过滤逻辑,就像每次检查访客都要执行的操作。

    • destroy(): 在 Filter 销毁时调用一次,可以用来释放资源,就像关卡拆除时进行的清理工作。

1.2 Spring Boot 中使用 Filter 

Spring Boot 为我们提供 @WebFilter 注解,让我们可以用更简洁、优雅的方式配置 Filter:

1.2.1 创建 Filter

java">@WebFilter(urlPatterns = {"/user/*", "/admin/*"}, filterName = "securityFilter") 
// 使用 @WebFilter 注解声明这是一个 Filter,并指定拦截路径和过滤器名称
public class SecurityFilter implements Filter { 

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        // 初始化资源,例如加载用户权限配置文件
        System.out.println("SecurityFilter 初始化...");
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        // 1. 获取请求信息,例如请求路径、请求参数
        HttpServletRequest httpRequest = (HttpServletRequest) request;
        String requestURI = httpRequest.getRequestURI();

        // 2. 执行业务逻辑,例如校验用户登录状态、权限验证
        System.out.println("SecurityFilter 拦截到请求: " + requestURI);
        if (!isAuthenticated(httpRequest)) { // 模拟用户认证逻辑
            // 未通过验证,跳转到登录页面或者返回错误信息
            HttpServletResponse httpResponse = (HttpServletResponse) response;
            httpResponse.sendRedirect("/login"); // 跳转到登录页面
            return; 
        }

        // 3. 放行请求到下一个 Filter 或目标资源
        chain.doFilter(request, response);

        // 4. 后置处理,例如记录日志
        System.out.println("SecurityFilter 处理请求完成: " + requestURI);
    }

    @Override
    public void destroy() {
        // 释放资源
        System.out.println("SecurityFilter 销毁...");
    }

    // 模拟用户认证逻辑
    private boolean isAuthenticated(HttpServletRequest request) {
        // 这里可以根据实际需求实现,例如检查 Session 中是否存在用户信息
        return true; 
    }
}

1.2.2 配置 Filter

在 Spring Boot 应用启动类上添加 @ServletComponentScan 注解,自动扫描并注册 Filter:

java">@SpringBootApplication
@ServletComponentScan //  启用 Servlet 组件扫描,自动发现并注册 Filter
public class MyApplication {
    public static void main(String[] args) {
        SpringApplication.run(MyApplication.class, args);
    }
}

1.3 Filter 的应用场景
  • 安全防护: 就像城堡的护城河,Filter 是应用的第一道防线,可以用于实现统一的身份认证、权限校验、敏感信息过滤等安全控制。

  • 字符编码: 可以统一设置请求和响应的字符编码,避免中文乱码问题,就像统一了城堡内使用的语言。

  • 日志记录: 可以记录所有请求和响应的信息,方便排查问题、分析用户行为,就像城堡的史官记录着一切来往人员的信息。

  • gzip 压缩: 可以对响应数据进行 gzip 压缩,减少网络传输量,提高响应速度,就像优化了城堡的交通运输系统。

二、拦截器 Interceptor

Interceptor,中文名拦截器,是 Spring MVC 框架提供的一种更精细化的拦截机制,它专注于拦截控制器方法,就像城堡的城门守卫,只对进入城门的人进行检查。

2.1 Interceptor 的工作原理:三次拦截

想象一下,Interceptor 就像城堡的城门守卫,在客人进入房间之前、离开房间之后,以及处理房间事务的过程中,都会提供周到的服务:

  1. preHandle: 第一道关卡

    • 在目标方法执行之前执行,就像城门守卫在客人进入房间之前进行身份验证。

    • 可以修改请求参数、设置响应头信息、甚至终止请求的执行。

    • 返回 true 表示放行,继续执行下一个拦截器或目标方法;返回 false 则表示拦截,请求终止,就像城门守卫拒绝客人进入。

  2. postHandle: 第二道关卡

    • 在目标方法执行之后,视图渲染之前执行,就像城门守卫在客人离开房间,但还没走出城门时进行检查。

    • 可以修改模型数据、添加逻辑视图等,对响应进行二次加工。

    • 此时无法阻止请求的处理流程,因为目标方法已经执行完毕。

  3. afterCompletion: 最后一道关卡

    • 在请求处理完成后执行,包括视图渲染以及异常处理,就像城门守卫在客人离开城门后进行最后的记录工作。

    • 可以进行资源清理、记录日志等操作,无论请求是否成功都会执行。

2.2 Spring Boot 中使用 Interceptor 

2.2.1 创建 Interceptor

java">public class AuthInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 1. 获取请求信息,例如请求路径、请求参数
        String requestURI = request.getRequestURI();

        // 2. 执行业务逻辑,例如权限验证
        System.out.println("AuthInterceptor 拦截到请求: " + requestURI);
        if (!hasPermission(request)) { // 模拟权限验证逻辑
            //  如果验证失败,设置错误信息,并跳转到错误页面
            response.setStatus(HttpServletResponse.SC_FORBIDDEN); 
            request.setAttribute("message", "您没有权限访问该资源!");
            request.getRequestDispatcher("/error").forward(request, response);
            return false;
        }

        // 3. 放行请求
        System.out.println("AuthInterceptor 放行请求: " + requestURI);
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        // 修改模型数据,例如添加用户信息
        if (modelAndView != null) {
            modelAndView.addObject("username", "John Doe");
        }
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        // 记录日志信息
        System.out.println("AuthInterceptor 请求处理完成: " + request.getRequestURI());
        if (ex != null) {
            System.out.println("发生异常: " + ex.getMessage());
        }
    }

    // 模拟权限验证逻辑
    private boolean hasPermission(HttpServletRequest request) {
        // 这里可以根据实际需求实现,例如检查用户角色
        return true;
    }
}

2.2.2 配置 Interceptor

java">@Configuration
public class MyWebMvcConfigurer implements WebMvcConfigurer {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // 添加拦截器,并配置拦截路径
        registry.addInterceptor(new AuthInterceptor())
                .addPathPatterns("/admin/**") // 拦截 /admin/ 下的所有请求
                .excludePathPatterns("/admin/login"); // 排除 /admin/login 请求
    }
}

2.3 Interceptor 的应用场景
  • 权限控制: 就像城堡的城门守卫,Interceptor 可以拦截特定 URL 的请求,验证用户权限,防止未授权访问。

  • 性能监控: 可以记录请求处理时间,分析系统性能瓶颈,就像城堡的计时器,记录每个访客的停留时间。

  • 日志记录: 可以记录用户的关键操作日志,例如登录、退出、修改信息等,就像城堡的记录员,记录着重要事件。

  • 国际化: 可以根据用户浏览器语言设置,选择合适的语言资源文件,就像城堡提供多语言导览服务。

三、Filter  vs  Interceptor

特性FilterInterceptor
规范Servlet 规范,不依赖 Spring 框架Spring MVC 框架的一部分
拦截范围所有 Web 应用,拦截所有请求仅限 Spring MVC 应用,拦截控制器方法
执行顺序Filter 链式调用,按配置顺序执行Interceptor 链式调用,按配置顺序执行
方法丰富度只有一个 doFilter 方法preHandle、postHandle、afterCompletion 三个方法
应用场景偏向底层、通用性需求,例如字符编码、安全过滤、Gzip 压缩偏向业务逻辑,例如权限控制、日志记录、性能监控

选择建议:

  • 优先考虑 Interceptor: 如果你的应用是基于 Spring MVC 构建的,并且需要对控制器方法进行拦截,那么优先选择 Interceptor,它更方便、更灵活。

  • Filter 也不可或缺: 如果你的需求与 Servlet API 相关,例如文件上传下载、字符编码设置等,或者你需要在 Spring MVC 应用之外使用拦截器,那么 Filter 是更好的选择。

  • 强强联手,灵活组合: 在实际项目中,可以根据需要组合使用 Filter 和 Interceptor,例如使用 Filter 进行字符编码设置,使用 Interceptor 进行权限控制,从而构建更完善的请求处理机制。

总结:

Filter 和 Interceptor 都是 Spring Boot 应用中不可或缺的请求拦截利器,它们就像城堡的护城河和城门守卫,在不同阶段、不同层面守护着应用的安全。开发者需要根据具体的应用场景选择合适的拦截器,并充分利用 Spring Boot 提供的便捷 API 和灵活的配置,才能构建出安全、高效、用户体验俱佳的 Web 应用。

以上就是关于过滤器Filter 和 拦截器Interceptor 的对比讲解了,希望对各位看官有所帮助,下期见,谢谢~


http://www.niftyadmin.cn/n/5689152.html

相关文章

2025 SSM与SpringBoot计算机毕业设计选题推荐【2025Java方向】

文末有博主联系方式 在选择计算机毕业设计题目时,选一个合适的方向和技术栈非常重要。对于使用Java方向的SSM(Spring、Spring MVC、MyBatis)和Spring Boot技术的开发项目,这里为大家整理了50个精选的毕业设计题目,供2…

tushare库简介及数据获取方法

文章目录 tushare库简介tushare使用方法接口数据获取实例获取交易日历股票基础信息沪股通和深股通成份股上市公司基础信息获取新股上市列表数据A股日线行情A股周线行情A股月线行情股票每日指标,选股分析 tushare库简介 tushare库是一个用于抓取中国股票的历史和实时…

性能测试笔记1

为什么要进行性能测试?(在真实项目商用时,需要大量的用户进行使用,因此需要模拟大量用户的使用场景 ) 1、业务需求 电商双 11 活动 / 微信春晚抢红包 /12306 春运订票 当前服务器配置是否支持 20000 人同时使用 技术…

【rCore OS 开源操作系统】Rust 练习题题解: Structs

【rCore OS 开源操作系统】Rust 练习题题解: Structs 摘要 rCore OS 开源操作系统训练营学习中的代码练习部分。 在此记录下自己学习过程中的产物,以便于日后更有“收获感”。 后续还会继续完成其他章节的练习题题解。 正文 structs1 题目 // structs1.rs // //…

【STM32开发笔记】移植AI框架TensorFlow到STM32单片机【下篇】

【STM32开发笔记】移植AI框架TensorFlow到STM32单片机【下篇】 一、上篇回顾二、项目准备2.1 准备模板项目2.2 支持计时功能2.3 配置UART4引脚2.4 支持printf重定向到UART42.5 支持printf输出浮点数2.6 支持printf不带\r的换行2.7 支持ccache编译缓存 三、TFLM集成3.1 添加tfli…

Prometheus之Pushgateway使用

Pushgateway属于整个架构图的这一部分 The Pushgateway is an intermediary service which allows you to push metrics from jobs which cannot be scraped. The Prometheus Pushgateway exists to allow ephemeral and batch jobs to expose their metrics to Prometheus. S…

Solidity 存储和内存管理:深入理解与高效优化

在 Solidity 中,存储和内存管理是编写高效智能合约的关键组成部分。合约执行的每一步操作都可能涉及到数据的存储和读取,而这些操作对 gas 的消耗有很大影响。因此,理解 Solidity 的存储模型以及如何优化数据的管理对于合约的安全性、性能和成…

汇编语言知识(王爽第四版)

汇编语言,当然,我们学习是在c语言的基础上,那么,我们就先复习一下c语言的知识 C语言的基础,进制转换必不可少 数组,函数…… 接下来,我们学习了数据结构:顺序表,链表&…