
文章目录一、过滤器与拦截器核心概念及层级区别1.1 过滤器Filter1.2 拦截器Interceptor1.3 核心差异对比表二、过滤器实战开发2.1 全局通用过滤器完整代码三、拦截器实战开发3.1 登录权限拦截器实现3.2 拦截器注册配置类四、跨域问题两种主流解决方案4.1 方案一Spring全局跨域配置推荐4.2 方案二自定义跨域过滤器五、请求全链路执行顺序与生产避坑指南5.1 完整请求执行链路5.2 高频生产避坑要点六、生产级高阶实战干货6.1 高阶一Spring托管过滤器解决Bean注入为空6.2 高阶二请求体重复读取解决方案6.3 高阶三多环境动态跨域配置生产级安全方案八、高频面试题集锦九、总结在SpringBoot前后端分离项目开发中过滤器、拦截器是实现请求预处理、权限校验、接口日志统计、参数统一处理的核心组件跨域处理则是项目上线必须解决的基础问题。三者执行层级不同、适用场景各异也是日常开发中极易混淆的知识点。一、过滤器与拦截器核心概念及层级区别过滤器Filter与拦截器Interceptor均用于拦截HTTP请求实现请求统一预处理但二者底层规范、容器依赖、拦截范围、执行时机完全不同是区分业务使用场景的核心依据。1.1 过滤器Filter过滤器是Servlet原生规范组件不依赖Spring框架由Tomcat等Servlet容器负责初始化与管理。其拦截层级最高可拦截容器接收的所有HTTP请求包括静态资源、非法请求、未映射接口请求执行时机在Spring MVC核心分发器DispatcherServlet之前。核心特点全局拦截、优先级最高、无Spring容器依赖、性能损耗低默认无法注入Spring Bean适合通用底层处理逻辑。1.2 拦截器Interceptor拦截器是Spring MVC专属组件由Spring容器初始化管理仅拦截DispatcherServlet分发的Controller接口请求不拦截静态资源、非法映射请求。执行时机位于过滤器之后、Controller方法执行前后。核心特点依托Spring容器、支持依赖注入、可精准获取接口方法信息、仅拦截业务接口专注业务层级的请求处理逻辑。1.3 核心差异对比表对比维度过滤器Filter拦截器Interceptor底层依赖Servlet规范、容器管理Spring MVC框架、Spring容器管理拦截范围全部HTTP请求接口、静态资源仅Controller映射接口请求执行顺序DispatcherServlet 执行之前DispatcherServlet 执行之后依赖注入默认不支持 Autowired完全支持Spring Bean注入核心场景跨域处理、全局编码、请求过滤权限校验、登录拦截、接口日志、参数预处理二、过滤器实战开发自定义过滤器需实现Servlet的Filter接口重写初始化、过滤、销毁三个核心方法。可通过注解快速注册适用于全局统一编码、请求日志、基础过滤等通用场景。2.1 全局通用过滤器完整代码importjakarta.servlet.*;importjakarta.servlet.http.HttpServletRequest;importlombok.extern.slf4j.Slf4j;importorg.springframework.core.annotation.Order;importorg.springframework.stereotype.Component;importjava.io.IOException;/** * 全局自定义过滤器 * 实现全局编码统一、请求基础信息打印 */Slf4jComponentOrder(1)// 数值越小过滤器执行优先级越高publicclassGlobalFilterimplementsFilter{/** * 容器启动时执行一次用于初始化资源 */Overridepublicvoidinit(FilterConfigfilterConfig)throwsServletException{log.info(全局过滤器初始化完成);}/** * 核心过滤逻辑每次请求都会执行 */OverridepublicvoiddoFilter(ServletRequestrequest,ServletResponseresponse,FilterChainchain)throwsIOException,ServletException{// 统一全局编码request.setCharacterEncoding(UTF-8);response.setCharacterEncoding(UTF-8);// 打印请求基础信息HttpServletRequesthttpRequest(HttpServletRequest)request;StringrequestUrihttpRequest.getRequestURI();StringmethodhttpRequest.getMethod();log.info(过滤器拦截请求地址{}请求方式{},requestUri,method);// 放行请求必须执行否则请求阻塞chain.doFilter(request,response);}/** * 项目关闭时执行一次用于资源释放 */Overridepublicvoiddestroy(){log.info(全局过滤器销毁释放资源);}}代码说明通过Component将过滤器交由Spring管理Order控制多过滤器执行优先级doFilter为核心方法必须调用chain.doFilter()放行请求否则请求会直接阻塞。三、拦截器实战开发自定义拦截器需实现Spring的HandlerInterceptor接口包含请求前置、后置、完成后三个拦截阶段。拦截器无法直接生效必须通过WebMvc配置类注册并配置拦截规则。3.1 登录权限拦截器实现importjakarta.servlet.http.HttpServletRequest;importjakarta.servlet.http.HttpServletResponse;importlombok.extern.slf4j.Slf4j;importorg.springframework.stereotype.Component;importorg.springframework.web.method.HandlerMethod;importorg.springframework.web.servlet.HandlerInterceptor;importorg.springframework.web.servlet.ModelAndView;/** * 全局接口拦截器 * 实现Token登录校验、接口访问日志记录 */Slf4jComponentpublicclassGlobalInterceptorimplementsHandlerInterceptor{/** * Controller方法执行前执行 * return true 放行请求return false 拦截请求 */OverridepublicbooleanpreHandle(HttpServletRequestrequest,HttpServletResponseresponse,Objecthandler){// 仅拦截接口方法放行静态资源、视图等非业务请求if(!(handlerinstanceofHandlerMethod)){returntrue;}HandlerMethodhandlerMethod(HandlerMethod)handler;log.info(拦截器捕获接口请求{},handlerMethod.getMethod().getName());// 模拟登录Token校验逻辑Stringtokenrequest.getHeader(token);if(tokennull||token.isEmpty()){log.warn(接口请求未携带Token拦截访问);response.setStatus(401);returnfalse;}returntrue;}/** * Controller执行完成、视图渲染前执行 */OverridepublicvoidpostHandle(HttpServletRequestrequest,HttpServletResponseresponse,Objecthandler,ModelAndViewmodelAndView){log.info(接口业务方法执行完成准备响应数据);}/** * 整个请求流程结束资源释放、最终日志记录 */OverridepublicvoidafterCompletion(HttpServletRequestrequest,HttpServletResponseresponse,Objecthandler,Exceptionex){log.info(本次请求流程完全结束);}}3.2 拦截器注册配置类importorg.springframework.context.annotation.Configuration;importorg.springframework.web.servlet.config.annotation.InterceptorRegistry;importorg.springframework.web.servlet.config.annotation.WebMvcConfigurer;/** * 拦截器注册配置类 * 统一配置拦截路径、放行路径 */ConfigurationpublicclassInterceptorConfigimplementsWebMvcConfigurer{privatefinalGlobalInterceptorglobalInterceptor;// 构造器注入自定义拦截器publicInterceptorConfig(GlobalInterceptorglobalInterceptor){this.globalInterceptorglobalInterceptor;}OverridepublicvoidaddInterceptors(InterceptorRegistryregistry){registry.addInterceptor(globalInterceptor).addPathPatterns(/**)// 拦截所有接口请求.excludePathPatterns(/login,/register,/static/**);// 放行登录、注册、静态资源}}四、跨域问题两种主流解决方案跨域问题由浏览器同源策略限制导致前后端协议、域名、端口任一不一致即触发跨域拦截。核心关键点浏览器OPTIONS预检请求不会进入Spring MVC拦截器因此跨域无法通过拦截器实现仅能通过全局配置或过滤器解决。4.1 方案一Spring全局跨域配置推荐配置集中、维护简单、无代码侵入适配绝大多数前后端分离项目是企业开发首选方案。importorg.springframework.context.annotation.Configuration;importorg.springframework.web.servlet.config.annotation.CorsRegistry;importorg.springframework.web.servlet.config.annotation.WebMvcConfigurer;/** * 全局统一跨域配置 */ConfigurationpublicclassCorsConfigimplementsWebMvcConfigurer{OverridepublicvoidaddCorsMappings(CorsRegistryregistry){registry.addMapping(/**).allowedOrigins(*).allowedMethods(GET,POST,PUT,DELETE,OPTIONS).allowedHeaders(*).allowCredentials(true).maxAge(3600);}}4.2 方案二自定义跨域过滤器通过过滤器手动设置跨域响应头优先拦截并放行OPTIONS预检请求适配特殊自定义场景。importjakarta.servlet.*;importjakarta.servlet.http.HttpServletRequest;importjakarta.servlet.http.HttpServletResponse;importlombok.extern.slf4j.Slf4j;importorg.springframework.core.annotation.Order;importorg.springframework.stereotype.Component;importjava.io.IOException;/** * 自定义跨域过滤器 * 优先级最高提前处理跨域预检请求 */Slf4jComponentOrder(0)publicclassCorsFilterimplementsFilter{OverridepublicvoiddoFilter(ServletRequestrequest,ServletResponseresponse,FilterChainchain)throwsIOException,ServletException{HttpServletRequestreq(HttpServletRequest)request;HttpServletResponseres(HttpServletResponse)response;// 设置跨域响应头res.setHeader(Access-Control-Allow-Origin,*);res.setHeader(Access-Control-Allow-Methods,GET,POST,PUT,DELETE,OPTIONS);res.setHeader(Access-Control-Allow-Headers,*);res.setHeader(Access-Control-Allow-Credentials,true);res.setHeader(Access-Control-Max-Age,3600);// 直接放行OPTIONS预检请求if(OPTIONS.equalsIgnoreCase(req.getMethod())){res.setStatus(200);return;}chain.doFilter(request,response);}}五、请求全链路执行顺序与生产避坑指南5.1 完整请求执行链路浏览器发起请求 → 跨域过滤器预处理 → 全局编码过滤器 → DispatcherServlet分发请求 → 拦截器preHandle前置拦截 → Controller业务执行 → 拦截器postHandle后置处理 → 视图渲染 → 拦截器afterCompletion收尾 → 响应返回浏览器5.2 高频生产避坑要点跨域不可用拦截器实现OPTIONS预检请求不进入Spring MVC拦截器链路拦截器配置跨域完全无效。原生Filter无法注入Bean普通Filter由Tomcat容器初始化早于Spring容器启动直接Autowired会出现Bean为null。跨域双方案冲突全局Cors配置与自定义CorsFilter不能同时启用会导致响应头覆盖、跨域报错。通配符与Cookie互斥开启allowCredentials(true)时禁止使用*通配符域名浏览器会直接拦截跨域请求。静态资源拦截问题未配置静态资源放行时拦截器会拦截css、js、图片等资源导致页面样式失效。请求体仅可读一次原生HttpServletRequest输入流只能读取一次拦截器读取Body后Controller会获取空参数。优先级底层原理Filter属于Web底层组件始终在DispatcherServlet之前执行Interceptor属于Spring MVC组件在DispatcherServlet内部执行因此过滤器优先级天然高于拦截器。六、生产级高阶实战干货本章聚焦企业开发刚需高阶解决方案解决过滤器Bean注入、请求体重复读取、多环境动态跨域三大生产级难题所有代码可直接上线使用。6.1 高阶一Spring托管过滤器解决Bean注入为空通过FilterRegistrationBean将过滤器交由Spring容器管理脱离Tomcat原生管理机制完美支持Service、配置类等Bean注入适配复杂业务过滤场景。importjakarta.servlet.Filter;importjakarta.servlet.http.HttpServletRequest;importlombok.extern.slf4j.Slf4j;importorg.springframework.boot.web.servlet.FilterRegistrationBean;importorg.springframework.context.annotation.Bean;importorg.springframework.context.annotation.Configuration;importorg.springframework.core.annotation.Order;/** * Spring托管过滤器配置 * 支持Spring Bean依赖注入 */Slf4jConfigurationpublicclassSpringManagedFilterConfig{// 可直接注入业务Service// private final UserService userService;// public SpringManagedFilterConfig(UserService userService) {this.userService userService;}BeanOrder(1)publicFilterRegistrationBeanFilterbusinessFilter(){FilterRegistrationBeanFilterregistrationBeannewFilterRegistrationBean();registrationBean.setFilter((request,response,chain)-{HttpServletRequesthttpRequest(HttpServletRequest)request;log.info(Spring托管过滤器执行可正常调用业务Bean);// 可实现黑名单拦截、权限二次校验等复杂逻辑chain.doFilter(request,response);});registrationBean.addUrlPatterns(/*);returnregistrationBean;}}6.2 高阶二请求体重复读取解决方案自定义请求包装类缓存请求Body解决拦截器读取JSON参数后Controller参数为空的问题是接口日志、参数校验的通用标准方案。importjakarta.servlet.ReadListener;importjakarta.servlet.ServletInputStream;importjakarta.servlet.http.HttpServletRequest;importjakarta.servlet.http.HttpServletRequestWrapper;importlombok.extern.slf4j.Slf4j;importjava.io.*;/** * 可重复读取请求体的包装类 */Slf4jpublicclassRepeatBodyRequestWrapperextendsHttpServletRequestWrapper{privatefinalbyte[]body;publicRepeatBodyRequestWrapper(HttpServletRequestrequest)throwsIOException{super(request);bodyrequest.getInputStream().readAllBytes();}OverridepublicServletInputStreamgetInputStream(){returnnewByteArrayServletInputStream(body);}OverridepublicBufferedReadergetReader(){returnnewBufferedReader(newInputStreamReader(getInputStream()));}privatestaticclassByteArrayServletInputStreamextendsServletInputStream{privatefinalByteArrayInputStreaminputStream;publicByteArrayServletInputStream(byte[]bytes){this.inputStreamnewByteArrayInputStream(bytes);}OverridepublicbooleanisFinished(){returninputStream.available()0;}OverridepublicbooleanisReady(){returntrue;}OverridepublicvoidsetReadListener(ReadListenerreadListener){}Overridepublicintread(){returninputStream.read();}}}请求包装过滤器全局生效importjakarta.servlet.*;importorg.springframework.core.annotation.Order;importorg.springframework.stereotype.Component;importjava.io.IOException;/** * 全局请求体包装过滤器 * 实现Body数据可重复读取 */ComponentOrder(-100)publicclassRepeatBodyFilterimplementsFilter{OverridepublicvoiddoFilter(ServletRequestrequest,ServletResponseresponse,FilterChainchain)throwsIOException,ServletException{RepeatBodyRequestWrapperrequestWrappernewRepeatBodyRequestWrapper((HttpServletRequest)request);chain.doFilter(requestWrapper,response);}}6.3 高阶三多环境动态跨域配置生产级安全方案摒弃通配符域名通过配置文件动态读取跨域域名支持开发、测试、生产多环境隔离兼顾安全性与灵活性符合企业上线规范。importorg.springframework.context.annotation.Configuration;importorg.springframework.core.env.Environment;importorg.springframework.web.servlet.config.annotation.CorsRegistry;importorg.springframework.web.servlet.config.annotation.WebMvcConfigurer;/** * 生产级动态跨域配置 * 多域名、多环境隔离安全合规 */ConfigurationpublicclassProductionCorsConfigimplementsWebMvcConfigurer{privatefinalEnvironmentenvironment;publicProductionCorsConfig(Environmentenvironment){this.environmentenvironment;}OverridepublicvoidaddCorsMappings(CorsRegistryregistry){// 从配置文件读取可跨域域名StringallowOriginenvironment.getProperty(system.cors.allow-origin,http://localhost:8080,http://127.0.0.1:8080);String[]originsallowOrigin.split(,);registry.addMapping(/**).allowedOrigins(origins).allowedMethods(GET,POST,PUT,DELETE,OPTIONS).allowedHeaders(*).allowCredentials(true).maxAge(3600);}}yml配置文件# 跨域域名配置system:cors:allow-origin:http://localhost:8080,http://test.xxx.com,https://www.xxx.com八、高频面试题集锦1. 说一下 Filter 和 Interceptor 的区别① 底层不同Filter是Servlet原生组件由Tomcat容器管理Interceptor是Spring MVC组件由Spring容器管理。② 执行时机不同Filter在DispatcherServlet之前执行Interceptor在DispatcherServlet之后、Controller前后执行。③ 拦截范围不同Filter拦截所有请求包含静态资源、非法请求Interceptor只拦截Controller映射的接口请求。④ 能力不同原生Filter无法注入BeanInterceptor完美支持Spring依赖注入。⑤ 适用场景不同Filter做底层通用处理跨域、编码、限流Interceptor做业务层处理登录校验、权限拦截、接口日志。2. 为什么拦截器不能处理跨域浏览器跨域复杂请求会先发OPTIONS预检请求该请求只会经过Tomcat过滤器链路不会进入Spring MVC的DispatcherServlet因此不会走到拦截器逻辑。所以跨域只能通过过滤器或全局Cors配置处理拦截器配置跨域完全无效。3. 过滤器、拦截器、Controller、AOP 执行顺序Filter过滤器 → DispatcherServlet → Interceptor前置preHandle → AOP前置通知 → Controller方法执行 → AOP后置通知 → Interceptor后置postHandle → 视图渲染 → Interceptor最终afterCompletion。4. 自定义Filter为什么Autowired注入Bean为null怎么解决原生Filter由Tomcat容器初始化初始化时机早于Spring容器此时Spring Bean还未创建导致注入为空。解决方案使用 FilterRegistrationBean 注册过滤器将过滤器交由Spring容器管理即可正常注入业务Bean。5. 跨域配置 allowCredentialstrue 为什么不能用 * 通配符这是浏览器的安全策略限制。开启允许携带Cookie后若使用通配符匹配所有域名会存在Cookie劫持风险浏览器会直接拦截请求并报错。生产环境必须配置具体的可信域名列表不能使用*。6. 需要做全局接口Token校验选过滤器还是拦截器为什么优先选拦截器。Token校验属于业务层权限逻辑需要注入用户、权限相关业务Bean拦截器天然支持Spring依赖注入且拦截器可精准拦截接口、放行静态资源适配业务场景比过滤器更灵活。7. 说下 FilterRegistrationBean 和 Component 注册过滤器的区别① Component注册的过滤器由Spring自动托管但底层仍依托Tomcat初始化默认无法精准控制过滤规则② FilterRegistrationBean是手动注册方式可精准控制过滤路径、优先级、是否启用最重要的是可以让过滤器完全由Spring容器管理解决Bean注入为空问题适合复杂生产场景。九、总结过滤器专注Web底层全局请求处理性能优异适合跨域、编码统一等基础通用逻辑拦截器专注Spring业务层请求处理支持依赖注入适合权限校验、接口日志、参数预处理等业务逻辑。二者分层执行、各司其职是SpringBoot请求链路处理的核心基石。文章结束喜欢就给个一键三连吧你的肯定是我最大的动力点赞上一千我就是脑瘫也出下章