web中的过滤器和拦截器
过滤器和拦截器
- 区别
- 执行顺序
- 使用场景
- 代码示例
区别
过滤器 (Filter)是Java Servlet 规范的一部分,不依赖Spring,可以过滤几乎所有请求;拦截器(Interceptor)是Spring MVC 框架的一部分,依赖Spring容器,只能拦截DispatcherServlet分配的、指向Controller的请求。
执行顺序
1. 请求进入 (Request)
2. → 过滤器 (Filter) 的 doFilter() 方法
3. → DispatcherServlet (Spring MVC 核心控制器)
4. → 拦截器 (Interceptor) 的 preHandle() 方法
5. → 执行目标 Controller 方法
6. → 拦截器 (Interceptor) 的 postHandle() 方法
7. → 渲染视图 (ViewResolver)
8. → 拦截器 (Interceptor) 的 afterCompletion() 方法
9. → 过滤器 (Filter) 的 doFilter() 方法后续逻辑
10. → 响应返回 (Response)
使用场景
过滤器:处理HTTP请求和响应最底层的操作(如修改流、压缩、统一编码、全站安全校验)
拦截器:处理与Spring MVC的请求处理生命周期紧密相关(如Controller方法执行前、后),或者需要操作HandlerMethod和ModelAndView
代码示例
自定义过滤器
@Component
@Order(1) // 定义过滤器的执行顺序
@WebFilter(urlPatterns = "/*")
public class MyFilter implements Filter {// 注意:这里直接@Autowired可能失效,因为Filter不由Spring管理// 需要通过其他方式获取Spring Bean(如WebApplicationContextUtils)@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {// 1. 在Controller处理之前执行 (预处理)System.out.println("Filter: Before controller");HttpServletRequest req = (HttpServletRequest) request;// 例如:设置统一编码req.setCharacterEncoding("UTF-8");// 继续执行过滤器链,最终会到达Servletchain.doFilter(request, response); // 这一句非常关键,相当于放行// 2. 在Controller处理之后执行 (后处理)System.out.println("Filter: After controller");// 例如:可以对Response进行操作HttpServletResponse resp = (HttpServletResponse) response;resp.setHeader("X-Custom-Header", "Hello");}// init 和 destroy 方法...
}
自定义拦截器
@Component
public class MyInterceptor implements HandlerInterceptor {// 可以方便地注入Spring管理的Bean@Autowiredprivate UserService userService;@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {// Controller方法执行之前调用System.out.println("Interceptor: preHandle - " + request.getRequestURI());// 权限检查示例String token = request.getHeader("Authorization");if (!userService.isValidToken(token)) {response.sendError(401, "Unauthorized");return false; // 中断执行,不会再到Controller}return true; // 继续执行,到Controller}@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {// Controller方法执行之后、视图渲染之前调用System.out.println("Interceptor: postHandle");// 可以修改ModelAndViewif (modelAndView != null) {modelAndView.addObject("extraData", "added by interceptor");}}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {// 整个请求完成之后(视图已渲染)调用,常用于资源清理、日志记录异常System.out.println("Interceptor: afterCompletion");if (ex != null) {// 记录异常日志System.err.println("Request failed with exception: " + ex.getMessage());}}
}// 还需要一个配置类来注册拦截器并指定路径
@Configuration
public class WebConfig implements WebMvcConfigurer {@Autowiredprivate MyInterceptor myInterceptor;@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(myInterceptor).addPathPatterns("/api/**") // 只拦截/api开头的请求.excludePathPatterns("/api/login"); // 排除登录接口}
}