springboot中的拦截器和过滤器的作用、区别解析
作者:bindabin
这篇文章主要介绍了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
- 请求到达:HTTP 请求首先被 Tomcat 等 Servlet 容器接收。
- 过滤器 (Filter):请求会依次经过配置的过滤器链(Filter Chain)。在这里,过滤器可以对请求进行“预处理”。
- 进入 Spring:请求通过过滤器后,到达 Spring MVC 的核心——
DispatcherServlet
。 - 拦截器 (Interceptor):
DispatcherServlet
会根据请求路径找到对应的Handler
(即Controller方法),但在执行之前,会先经过配置的拦截器链(Interceptor Chain)的preHandle
方法。 - 执行控制器:如果所有拦截器的
preHandle
都返回true
,则执行真正的 Controller 方法。 - 后处理:Controller 方法执行完毕后,会依次经过拦截器链的
postHandle
方法(视图渲染前)。 - 视图渲染:进行视图渲染(如果是 MVC 模式)。
- 最终处理:视图渲染完成后(或完成后),会执行拦截器链的
afterCompletion
方法(请求完成后,可用于资源清理)。 - 返回响应:处理后的响应再次经过过滤器链,过滤器可以对响应进行“后处理”。
- 响应返回:最终,响应通过 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. 过滤器 (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 的业务开发中,拦截器是更常用和更强大的选择,尤其是处理权限、日志等业务相关切面。
到此这篇关于java springboot中的拦截器和过滤器的作用、区别和联系的文章就介绍到这了,更多相关springboot拦截器和过滤器区别内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!