资讯详情

Spring MVC拦截器异常处理与跨域详解

📅 2026/10/11 18:55:47 | 华诺云谱 👁 阅读
Spring MVC拦截器异常处理与跨域详解
Spring MVC拦截器异常处理与跨域详解定位第 04 篇讲透拦截器三回调与过滤器对比、全局异常处理体系、CORS 跨域原理与配置适用版本Spring Framework 6.xJDK 17目录一、拦截器体系二、全局异常处理三、CORS 跨域四、总结五、常见高频面试题一、拦截器体系1.1 三个回调publicclassAuthInterceptorimplementsHandlerInterceptor{publicbooleanpreHandle(HttpServletRequestreq,...){// 执行前鉴权检查返回 false 则中断不再执行后续与 Handlerreturntrue;}publicvoidpostHandle(...){// Handler 执行后、视图渲染前可修改 Model}publicvoidafterCompletion(...){// 完成后含异常清理资源如解绑 ThreadLocal}}执行时序洋葱模型preHandle → Handler → postHandle → 视图/响应 → afterCompletion preHandle 返回 false后续拦截器与 Handler 都不执行1.2 注册与顺序ConfigurationpublicclassWebConfigimplementsWebMvcConfigurer{publicvoidaddInterceptors(InterceptorRegistryreg){reg.addInterceptor(newAuthInterceptor()).addPathPatterns(/api/**)// 拦截路径.excludePathPatterns(/api/login)// 排除.order(1);// 多个拦截器的顺序}}1.3 拦截器与过滤器的对比高频维度Filter过滤器HandlerInterceptor拦截器所属层Servlet 规范容器层Spring MVC框架层位置在 DispatcherServlet 之外在 DispatcherServlet 之内能拿到原始请求/响应还能拿到 Handler/方法信息典型用途编码、鉴权(粗)、压缩、跨域登录校验、权限、日志、埋点生效范围所有请求含静态进入 MVC 处理的请求记忆过滤器在外圈管请求拦截器在内圈管处理器。二、全局异常处理2.1 异常解析链DispatcherServlet 捕获到 Handler 抛出的异常后交给HandlerExceptionResolver链① ExceptionHandlerExceptionResolver → 找 ExceptionHandler方法级/全局 ② ResponseStatusExceptionResolver → ResponseStatus 注解 ③ DefaultHandlerExceptionResolver → 标准 Spring 异常映射404/405 等 都处理不了 → 转发 /errorBoot2.2 RestControllerAdvice 全局处理RestControllerAdvicepublicclassGlobalExceptionHandler{ExceptionHandler(MethodArgumentNotValidException.class)// 校验ResponseEntityApiErrorinvalid(MethodArgumentNotValidExceptione){returnbadRequest(字段级错误明细);}ExceptionHandler(BizException.class)// 业务ResponseEntityApiErrorbiz(BizExceptione){returnstatus(e.httpStatus()).body(ApiError.of(e.getCode(),e.getMessage()));}ExceptionHandler(Exception.class)// 兜底ResponseEntityApiErrorfallback(Exceptione){log.error(unhandled,e);// 记录不外泄堆栈returninternal(ApiError.of(SYSTEM_ERROR,系统繁忙));}}2.3 分层处理策略异常类别状态码响应内容是否告警参数校验400字段级明细否业务异常400/409 等业务错误码 消息视情况认证/授权401/403标准消息否/监控未知异常500通用消息不回传堆栈是告警纪律异常分类处理、堆栈只进日志不进响应、未知异常必须告警。三、CORS 跨域3.1 同源策略浏览器的安全约束脚本只能请求同源协议 域名 端口一致的资源跨源请求默认被拦截。注意这是浏览器的行为服务端间调用不存在跨域问题。3.2 CORS 机制CORS 是服务端通过响应头声明允许哪些跨源访问简单请求GET/部分 POST 等直接发靠响应头判定 非简单请求先发预检OPTIONS询问 → 服务端允许后才发真实请求关键头头含义Access-Control-Allow-Origin允许的源*或具体域名Access-Control-Allow-Methods允许的方法Access-Control-Allow-Headers允许的自定义头Access-Control-Allow-Credentials是否允许带 Cookie3.3 Spring 的三种配置① 注解CrossOrigin(origins https://web.example.com) // 单接口 ② 全局WebMvcConfigurer#addCorsMappings registry.addMapping(/api/**) .allowedOrigins(https://web.example.com) .allowedMethods(*); ③ CorsFilter过滤器位置最外适合与安全框架共存注意Allow-Credentialstrue时Allow-Origin不能是*必须指定具体域名。四、总结拦截器preHandle可中断/postHandle/afterCompletion 三回调注册指定路径与顺序与过滤器分层不同——过滤器在 Servlet 外圈拦截器在 MVC 内圈。异常处理HandlerExceptionResolver 链RestControllerAdvice 全局按类别转统一错误响应未知异常记日志告警、不外泄堆栈。CORS浏览器同源策略的例外机制靠响应头声明简单请求直发、非简单先预检OPTIONS配置三种方式带凭证时不能*。五、常见高频面试题1. HandlerInterceptor 的三个方法分别在什么时候执行要点preHandle 在 Handler 执行前调用返回 false 则中断后续拦截器与 Handler 都不执行常用于鉴权postHandle 在 Handler 执行后、视图渲染前可修改 ModelafterCompletion 在请求完全完成后含异常用于清理资源如解绑 ThreadLocal。多个拦截器按注册顺序形成链整体是洋葱模型。2. 过滤器Filter和拦截器Interceptor的区别要点所属层与位置不同。Filter 是 Servlet 规范在容器层、DispatcherServlet 之外对所有请求生效含静态资源只能拿到原始请求响应常用于编码、压缩、粗粒度鉴权、跨域HandlerInterceptor 是 Spring MVC 层在 DispatcherServlet 之内能拿到 Handler/方法信息作用于进入 MVC 的请求常用于登录校验、权限、埋点。简记过滤器在外圈管请求拦截器在内圈管处理器。3. Spring MVC 的异常处理机制是怎样的要点Handler 抛出的异常被 DispatcherServlet 交给 HandlerExceptionResolver 链先找 ExceptionHandler方法级再到 ControllerAdvice 全局再看 ResponseStatus最后 DefaultHandlerExceptionResolver 映射标准异常如 NoHandlerFound→404都处理不了转发 /error。实践用 RestControllerAdvice 统一处理按异常类型返回统一错误响应。4. ControllerAdvice 的原理和用途要点ControllerAdvice 是一个特殊的 Component通过 AOP 横切所有 Controller提供全局的异常处理ExceptionHandler、数据绑定ModelAttribute、数据预处理InitBinder。配合 ResponseBody 的 RestControllerAdvice 是全局异常处理的标准实现把各类异常统一转为规范错误响应避免每个控制器重复写异常逻辑。5. 什么是 CORS为什么会有跨域问题要点浏览器同源策略限制脚本跨源协议域名端口不同访问资源是安全机制。跨源 XHR/fetch 默认被拦截。CORS 让服务端用响应头声明允许的跨源访问Access-Control-Allow-Origin 等。注意跨域是浏览器行为服务端间调用无此问题。非简单请求会先发 OPTIONS 预检服务端放行后才发真实请求。6. 简单请求和非简单请求的区别预检请求是什么要点简单请求满足方法为 GET/HEAD/部分 POST且头与 Content-Type 在安全集合内——直接发出靠响应头判定是否允许。非简单请求如 PUT/DELETE、带自定义头、application/json会先发 OPTIONS 预检携带将要用的方法与头服务端以 Access-Control-Allow-* 响应允许后浏览器才发真实请求。预检可被缓存Access-Control-Max-Age减少开销。7. 跨域时携带 Cookie 要注意什么要点需要服务端 Access-Control-Allow-Credentials: true且请求带 withCredentialstrue此时 Access-Control-Allow-Origin 不能是通配符 *必须指定具体域名浏览器强制。另外 SameSite Cookie 属性也会影响跨站携带。安全上要谨慎允许跨源携带凭证等于把接口暴露给该源的前端确保源可信。8. 全局异常处理时未知异常Exception该怎么处理要点兜底捕获但严格处理① 记录完整堆栈到日志并触发告警这是唯一能发现未预期错误的信号② 响应返回通用友好消息如系统繁忙 错误码/追踪 ID绝不回传堆栈安全体验③ 可返回追踪 ID 便于用户反馈与日志关联。区分对待业务异常返回具体码校验异常返回字段明细未知异常通用化。9. 登录校验、权限控制应该放在过滤器还是拦截器要点取决于层次与需求。粗粒度/与容器能力相关的如 Token 解码、跨域、编码放过滤器与业务路由相关的按路径的登录态校验、细粒度权限、访问日志埋点放拦截器——它能拿到 Handler 信息如方法上的权限注解。若用 Spring Security则由过滤器链统一承担认证授权。关键避免同一逻辑两处重复。10. afterCompletion 和 postHandle 的区别资源清理放哪个要点postHandle 在 Handler 执行后、视图/响应处理前调用——若 Handler 抛异常则不执行afterCompletion 在请求完全完成后调用无论是否异常都会执行。所以资源清理解绑 ThreadLocal、释放上下文必须放 afterCompletion——放 postHandle 会在异常路径漏清理造成内存泄漏或上下文串扰。
📝

华诺云谱内容团队

资深建站顾问 · 行业研究员

10年+企业数字化服务经验,专注智能建站、SEO优化与品牌营销,持续输出建站技巧、行业洞察与营销干货,已帮助5000+企业实现数字化增长。

你可能需要的服务

订阅华诺云谱资讯周报

每周一封,精选建站技巧、SEO与营销干货,直达邮箱。已有 8,000+ 企业主订阅,助你少走弯路。

↑