SpringMvc(Interceptor,Filter)实现方案

 更新时间:2026年01月12日 10:16:03   作者:清风徐来QCQ  
在JavaWeb开发中,过滤器和拦截器都是用于实现AOP的工具,但它们在框架层级和执行时机上有所不同,过滤器属于Servlet规范,位于所有Servlet之前,可以对所有请求进行预处理,本文给大家介绍SpringMvc(Interceptor,Filter)实现方案,感兴趣的朋友一起看看吧

在 Java Web 开发中,过滤器 (Filter)拦截器 (Interceptor) 都是常用的 AOP(面向切面编程)实现方式,但它们所属的框架层级和执行时机有很大不同。

我们可以把它们想象成进入大楼的保安(过滤器)和进入办公室前的秘书(拦截器)

1. 过滤器 (Filter)

过滤器属于 Servlet 规范,它位于所有 Servlet 之前。它可以对几乎所有的请求(HTML、图片、JS、路径等)进行预处理。

实现方案一:通过@WebFilter注解(Servlet 原生)

这是最简单、最直接的方式,不需要额外的配置类。

  • 实现步骤
    • 实现 jakarta.servlet.Filter 接口。
    • 重写 doFilter 方法。
    • 在类上标注 @WebFilter(urlPatterns = "/*")
    • 在启动类上加 @ServletComponentScan

实现方案二:通过FilterRegistrationBean(Spring Boot统一管理生命周期 推荐)

如果你需要更精细地控制过滤器的执行顺序(Order),或者你的过滤器是第三方库提供的,这种方案最合适。

  • 实现步骤
    • 编写一个普通的类实现 Filter 接口。
    • 创建一个配置类(标注 @Configuration)。
    • 定义一个 Bean 返回 FilterRegistrationBean 实例。
@Bean
public FilterRegistrationBean<MyFilter> registrationBean() {
    FilterRegistrationBean<MyFilter> bean = new FilterRegistrationBean<>();
    bean.setFilter(new MyFilter()); // 设置过滤器
    bean.addUrlPatterns("/api/*");  // 设置拦截路径
    bean.setOrder(1);               // 设置优先级,数字越小越靠前
    return bean;
}

2. 拦截器 (Interceptor)

拦截器属于 Spring MVC 框架。它只能拦截发送到 Controller 的请求。因为它在 Spring 容器中,所以它可以直接使用 Spring 注入的对象(比如 Service)。

需要继承/实现的类

  • 实现接口org.springframework.web.servlet.HandlerInterceptor
  • 主要方法
    • preHandle:在 Controller 执行前调用(常用作权限校验)。
    • postHandle:Controller 执行后,视图渲染前调用。
    • afterCompletion:整个请求结束(视图渲染后)调用,常用于清理资源。

注册拦截器

实现拦截器后,必须将其注册到 Spring MVC 的配置中:

  • 继承 WebMvcConfigurer 接口。
  • 重写 addInterceptors 方法。

3. 核心区别对比表

特性过滤器 (Filter)拦截器 (Interceptor)
所属框架Servlet 容器 (如 Tomcat)Spring MVC 框架
实现接口jakarta.servlet.FilterHandlerInterceptor
拦截范围几乎所有请求 (URL 匹配即可)仅针对 Controller 的请求
注入能力较难直接注入 Spring Bean完美支持注入 Bean
执行时机在 Servlet 之前执行在 Servlet 之后,Controller 之前执行
主要用途编码设置、敏感词过滤、全局压缩权限检查、日志记录、参数预处理

简单总结:

  • 过滤器:适合做底层的、通用的操作(如:字符编码、请求跨域、全局加密)。
  • 拦截器:适合做业务相关的操作(如:检查是否登录、接口权限控制、记录操作日志)。

为什么跨域请求要通过过滤器实现?

其实跨域(CORS)既可以通过**过滤器(Filter)实现,也可以通过拦截器(Interceptor)**或者 Spring 提供的 @CrossOrigin 注解实现。

但在实际生产中,绝大多数架构师会首选过滤器。这主要源于跨域请求的一个特殊机制:预检请求(Preflight Request)

1. 预检请求(OPTIONS)的拦路虎

当浏览器发现你在发起一个“复杂请求”(比如带了自定义 Header 或 Content-Type 为 application/json)时,它会先自动发送一个 OPTIONS 方法的探测请求。

  • 过滤器的优势:由于过滤器在 Servlet 容器的最外层,它能在请求到达 Spring MVC 的 DispatcherServlet 之前,就识别出这是一个 OPTIONS 请求,并直接返回允许跨域的响应头(200 OK)。
  • 拦截器的劣势:拦截器工作在 Spring MVC 内部。如果你的 OPTIONS 请求因为某些安全配置或权限校验没能通过 DispatcherServlet 的映射,拦截器可能根本不会执行。这会导致预检请求失败,浏览器直接拦截掉后续的正式请求。

2. 为什么选择过滤器的三大理由

① 执行时机最早(最核心原因)

跨域配置本质上是给 HTTP 响应头加上 Access-Control-Allow-Origin 等字段。

  • 过滤器在整个过滤链的最前端。如果请求跨域失败,直接在过滤器层级就“挡回去”或“处理掉”了,不会浪费后续的业务逻辑资源(如数据库连接、权限检查)。

② 解决权限框架(Security/Shiro)的冲突

如果你的项目中使用了 Spring Security,它本身就是通过一系列过滤器实现的。

  • 如果你把跨域放在拦截器里,由于拦截器的执行晚于 Spring Security 的过滤器,Spring Security 会在拦截器生效前发现请求没带 Token 或不符合安全规则,直接返回 403。
  • 此时浏览器因为没收到跨域响应头,会报一个“CORS error”,而隐藏了真正的“403 Forbidden”错误,导致前端无法准确定位问题。

③ 覆盖范围广

过滤器是针对 URL 模式拦截的。如果你的项目里既有 Spring MVC 的 Controller,又有一些原生的 Servlet,或者静态资源,过滤器可以一把抓,统一处理所有资源的跨域问题。

3. 实现代码对比

过滤器方案(推荐)

这种方式利用 Spring 提供的 CorsFilter,通常配合 FilterRegistrationBean 使用,优先级设为最高。

@Bean
public FilterRegistrationBean<CorsFilter> corsFilter() {
    UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
    CorsConfiguration config = new CorsConfiguration();
    config.setAllowCredentials(true);
    config.addAllowedOriginPattern("*"); // 允许所有来源
    config.addAllowedHeader("*");        // 允许所有Header
    config.addAllowedMethod("*");        // 允许所有方法
    source.registerCorsConfiguration("/**", config);
    FilterRegistrationBean<CorsFilter> bean = new FilterRegistrationBean<>(new CorsFilter(source));
    bean.setOrder(Ordered.HIGHEST_PRECEDENCE); // 确保在最前端执行
    return bean;
}

总结

跨域选择过滤器,是因为它能在业务逻辑和安全框架之前处理 OPTIONS 请求。就像在大楼的**正门口(过滤器)贴上“欢迎光临”的告示,比等客人进了办公室(拦截器)**才说欢迎要高效且稳妥得多。

到此这篇关于SpringMvc(Interceptor,Filter)实现方案的文章就介绍到这了,更多相关SpringMvc Interceptor,Filter内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 详解SpringBoot+Dubbo集成ELK实战

    详解SpringBoot+Dubbo集成ELK实战

    这篇文章主要介绍了详解SpringBoot+Dubbo集成ELK实战,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-10-10
  • Java中Array、List、Map相互转换的方法详解

    Java中Array、List、Map相互转换的方法详解

    这篇文章主要介绍了Java中Array、List、Map相互转换的方法详解,在实际项目开发中或者一些算法面试题目中经常需要用到Java中这三种类型的相互转换,比如对于一个整型数组中寻找一个整数与所给的一个整数值相同,需要的朋友可以参考下
    2023-08-08
  • Java编程线程同步工具Exchanger的使用实例解析

    Java编程线程同步工具Exchanger的使用实例解析

    这篇文章主要介绍了Java编程线程同步工具Exchanger的使用实例解析,分享了相关代码示例,小编觉得还是挺不错的,具有一定借鉴价值,需要的朋友可以参考下
    2018-02-02
  • Java线程活锁的实现与死锁等的区别

    Java线程活锁的实现与死锁等的区别

    活锁是一种递归情况,其中两个或更多线程将继续重复特定的代码逻辑,本文主要介绍了Java线程活锁的实现与死锁等的区别,具有一定的参考价值,感兴趣的可以了解一下
    2024-04-04
  • 使用Java对PDF添加水印的操作代码

    使用Java对PDF添加水印的操作代码

    在当今数字化办公环境中,PDF 文档作为信息交流和存储的重要载体,其安全性和版权保护变得尤为关键,企业常常需要对内部敏感文档或对外发布的资料添加水印,以防止未经授权的使用,本文将为您揭示这一问题的解决方案,深入探讨如何使用Java对PDF添加水印,需要的朋友可以参考下
    2025-10-10
  • Java详细讲解IO流的Writer与Reader操作

    Java详细讲解IO流的Writer与Reader操作

    Writer与Reader类不能直接调用,需要使用多带的方法调用它们的子类,在他们的前边加上一个File即可如(FileWriter或FileReader)的多态方法进行其调用,并且他们也是抽象类调用需要连接接口Exception,它们的优点在于可以直接写入或读出内容,不需要使用byte转八进制
    2022-05-05
  • spring中的注解事务演示和添加步骤详情

    spring中的注解事务演示和添加步骤详情

    这篇文章主要介绍了spring中的注解事务演示和添加步骤详情,文章围绕主题展开详细的内容介绍,具有一定的参考价值,需要的朋友可以参考一下
    2022-07-07
  • Java数据结构之有向图的拓扑排序详解

    Java数据结构之有向图的拓扑排序详解

    这篇文章主要为大家详细介绍了Java数据结构中有向图的拓扑排序,文中的示例代码讲解详细,具有一定的借鉴价值,感兴趣的小伙伴可以了解一下
    2022-11-11
  • Java与Oracle实现事务(JDBC事务)实例详解

    Java与Oracle实现事务(JDBC事务)实例详解

    这篇文章主要介绍了Java与Oracle实现事务(JDBC事务)实例详解的相关资料,需要的朋友可以参考下
    2017-05-05
  • SpringBoot+redis配置及测试的方法

    SpringBoot+redis配置及测试的方法

    这篇文章主要介绍了SpringBoot+redis配置及测试的方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-04-04

最新评论