SpringMvc(Interceptor,Filter)

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

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


1. 过滤器 (Filter)

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

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

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

  • 实现步骤

    1. 实现 jakarta.servlet.Filter 接口。

    2. 重写 doFilter 方法。

    3. 在类上标注 @WebFilter(urlPatterns = "/*")

    4. 在启动类上加 @ServletComponentScan

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

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

  • 实现步骤

    1. 编写一个普通的类实现 Filter 接口。

    2. 创建一个配置类(标注 @Configuration)。

    3. 定义一个 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.Filter HandlerInterceptor
拦截范围 几乎所有请求 (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 请求 。就像在大楼的**正门口(过滤器)贴上"欢迎光临"的告示,比等客人进了办公室(拦截器)**才说欢迎要高效且稳妥得多。

相关推荐
while(1){yan}2 天前
拦截器(详解)
数据库·spring boot·spring·java-ee·拦截器
Roye_ack10 天前
【微服务 Day3】SpringCloud实战开发(网关路由 + 网关登录校验 + 自定义过滤器 + 配置共享 + 配置热更新 + 动态路由)
网关·spring cloud·微服务·架构·过滤器·拦截器·配置管理
七夜zippoe15 天前
Spring MVC请求处理流程源码分析与DispatcherServlet核心逻辑
java·spring·mvc·过滤器·拦截器
这是个栗子23 天前
【前端知识点总结】请求/响应拦截器的介绍
前端·拦截器
全靠bug跑1 个月前
Spring Cloud Gateway 实战:统一鉴权与用户信息全链路透传
java·开发语言·gateway·拦截器
哈哈~haha1 个月前
UI5_Walkthrough_Step 23: Filtering 过滤器
过滤器·filtering
西京刀客1 个月前
什么是gRPC Metadata,使用场景是什么 | 拦截器 与 Metadata
grpc·拦截器·metadata
空空kkk1 个月前
SpringMVC——拦截器
java·数据库·spring·拦截器
我叫张小白。2 个月前
Spring Boot拦截器详解:实现统一的JWT认证
java·spring boot·web·jwt·拦截器·interceptor