java springboot中的拦截器和过滤器的作用、区别和联系

一、作用

1. 过滤器 (Filter)
  • 归属:过滤器是 Java Servlet 规范 规定的标准,属于 Web 服务器层面的技术。任何 Java Web 工程(包括 Spring Boot)都可以使用它。
  • 作用:过滤器用于在请求进入 Web 应用程序(Servlet)之前响应离开应用程序之后执行预处理和后处理。它的核心作用是对 HTTP 请求和响应进行过滤
  • 典型应用场景
    • 解决全局的跨域问题(CORS)
    • 字符编码设置(CharacterEncodingFilter
    • 敏感词过滤、非法请求拦截
    • 通用的日志记录、性能监控(记录请求耗时)
    • 权限校验(简单逻辑,不依赖于 Spring 容器)
2. 拦截器 (Interceptor)
  • 归属:拦截器是 Spring MVC 框架 自身的组件,它深度集成于 Spring 上下文(ApplicationContext)。
  • 作用:拦截器用于在请求进入 Spring MVC 的控制器 (Controller) 之前控制器方法执行之后 以及视图渲染完毕之后 这三个关键点进行拦截处理。它的核心作用是对控制器级别的请求进行更精细化的处理。
  • 典型应用场景
    • 登录状态校验和权限验证(最常用)
    • 日志记录(记录 Controller 方法的入参、出参等)
    • 通用数据的预处理(如从 cookie/token 中解析用户信息并放入模型)
    • 方法执行时间的计算

二、执行顺序与位置(核心区别)

这是理解两者区别最直观的方式。一个 HTTP 请求的处理流程如下:

HTTP Request -> Tomcat -> Filter -> DispatcherServlet -> Interceptor -> Controller -> Interceptor -> Filter -> HTTP Response

  1. 请求到达:HTTP 请求首先被 Tomcat 等 Servlet 容器接收。
  2. 过滤器 (Filter):请求会依次经过配置的过滤器链(Filter Chain)。在这里,过滤器可以对请求进行“预处理”。
  3. 进入 Spring:请求通过过滤器后,到达 Spring MVC 的核心——DispatcherServlet
  4. 拦截器 (Interceptor)DispatcherServlet 会根据请求路径找到对应的 Handler(即Controller方法),但在执行之前,会先经过配置的拦截器链(Interceptor Chain)的 preHandle 方法。
  5. 执行控制器:如果所有拦截器的 preHandle 都返回 true,则执行真正的 Controller 方法。
  6. 后处理:Controller 方法执行完毕后,会依次经过拦截器链的 postHandle 方法(视图渲染前)。
  7. 视图渲染:进行视图渲染(如果是 MVC 模式)。
  8. 最终处理:视图渲染完成后(或完成后),会执行拦截器链的 afterCompletion 方法(请求完成后,可用于资源清理)。
  9. 返回响应:处理后的响应再次经过过滤器链,过滤器可以对响应进行“后处理”。
  10. 响应返回:最终,响应通过 Tomcat 返回给客户端。

简单比喻

  • 过滤器:相当于小区的大门保安,对所有进出小区(Web应用)的人和物(HTTP请求/响应)进行宏观检查。
  • 拦截器:相当于楼下的单元门禁,只对进入你这栋楼(Spring MVC控制器)的人进行更具体的检查和登记。

三、区别与联系总结

特性过滤器 (Filter)拦截器 (Interceptor)
归属规范/框架Servlet 规范 (javax.servlet)Spring MVC 框架 (org.springframework.web.servlet)
依赖关系不依赖 Spring 容器,在 Web 服务器中运行强烈依赖 Spring 容器,可以调用 Spring 中的任何 Bean(如 Service)
作用范围作用于所有请求(包括静态资源,如 /css/, /js/只作用于进入 Spring MVC 控制器的请求(通常由 DispatcherServlet 处理)
获取 Bean无法直接注入 Spring Bean,需要通过其他方式(如 Spring 工具类)可以方便地使用 @Autowired 注入 Spring Bean
实现方式实现 javax.servlet.Filter 接口,重写 doFilter 方法实现 HandlerInterceptor 接口,重写 preHandle, postHandle, afterCompletion
控制粒度较粗,基于 ServletRequest 和 ServletResponse较细,可以获取到处理请求的控制器方法(HandlerMethod) 等信息
执行时机在 Servlet 之前和之后执行在 Controller 方法之前、之后、以及视图渲染完成后执行
异常处理在过滤器中发生的异常,可以在过滤链中进行处理在拦截器中发生的异常,可以被 Spring 的全局异常处理器(@ControllerAdvice)捕获

联系

  1. 功能相似:两者都实现了“横切关注点”的功能,用于实现与业务逻辑无关的通用功能(如日志、安全)。
  2. 执行顺序协作:它们在同一次请求处理流程中协同工作,过滤器在外层,拦截器在内层。

四、代码示例

1. 过滤器 (Filter) 示例
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;

// 使用注解注册过滤器,并指定过滤的 URL 模式
@WebFilter(urlPatterns = "/*")
public class MyFilter implements Filter {

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        long startTime = System.currentTimeMillis();
        System.out.println("Filter: 请求预处理 - 设置字符编码");

        // 设置请求和响应编码
        request.setCharacterEncoding("UTF-8");
        response.setCharacterEncoding("UTF-8");

        // 继续执行过滤器链,最终会到达 Servlet
        chain.doFilter(request, response);

        // 响应后处理
        long endTime = System.currentTimeMillis();
        System.out.println("Filter: 响应后处理 - 请求耗时: " + (endTime - startTime) + "ms");
    }

    // ... 其他 init 和 destroy 方法
}

注意:在 Spring Boot 中,通常使用 @Component 或配置类来注册 Filter,@WebFilter 有时需要与 @ServletComponentScan 配合使用。

2. 拦截器 (Interceptor) 示例
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@Component
public class MyInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("Interceptor: preHandle - 在控制器方法执行之前");
        // 登录校验逻辑
        // if (!isLogin(request)) {
        //     response.sendRedirect("/login");
        //     return false; // 中断执行,不会到达 Controller
        // }
        System.out.println("用户已登录,放行");
        return true; // 继续执行,到达 Controller
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("Interceptor: postHandle - 控制器方法执行完毕,视图渲染之前");
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("Interceptor: afterCompletion - 整个请求已完成,视图已渲染");
        // 资源清理等工作
    }
}

还需要一个配置类来注册拦截器并指定拦截路径:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class WebConfig implements WebMvcConfigurer {

    @Autowired
    private MyInterceptor myInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(myInterceptor)
                .addPathPatterns("/api/**") // 拦截所有 /api 开头的路径
                .excludePathPatterns("/api/login"); // 排除登录接口
    }
}

五、如何选择?

  • 使用过滤器 (Filter) 当:你的功能与 Spring 无关(例如,处理静态资源),或者你需要处理非常底层的 ServletRequest/ServletResponse 对象(如包装请求体),或者你的逻辑非常通用且不需要 Spring 容器的支持。
  • 使用拦截器 (Interceptor) 当:你的功能需要与 Spring MVC 深度集成,例如需要访问 HandlerMethod 信息、需要注入 Spring Bean(如 Service 来进行权限校验)、或者你的拦截逻辑只针对进入控制器的业务请求。

在大多数基于 Spring Boot 的业务开发中,拦截器是更常用和更强大的选择,尤其是处理权限、日志等业务相关切面。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值