Spring MVC全局异常处理推荐@ControllerAdvice+@ExceptionHandler方案,集中捕获Controller未处理异常并返回统一JSON响应;传统页面跳转则用HandlerExceptionResolver实现;需定义标准响应体、分级错误码、自定义异常类,并注意静态资源等例外场景。

Spring MVC 处理全局统一异常捕获,核心目标是把所有 Controller 层未处理的异常集中拦截、分类响应,并避免向用户暴露技术细节。不靠每个方法写 try-catch,而是用框架机制解耦业务与错误逻辑。
推荐方式:@ControllerAdvice + @ExceptionHandler
这是目前最主流、最简洁、最符合 REST 风格的方案,适合返回 JSON 响应(如前后端分离项目):
- 新建一个类,加上 @ControllerAdvice 注解,表示它对所有 Controller 生效
- 在类中定义多个方法,分别用 @ExceptionHandler(XXXException.class) 指定要捕获的异常类型
- 每个方法返回统一响应体(如 ApiResponse<Void>),包含 code、msg、data 字段,前端可统一解析
- 支持按异常层级细化处理:比如自定义业务异常(BizException)返回 400 级提示,NullPointerException 返回 500 并记录日志,参数校验异常(MethodArgumentNotValidException)提取字段错误信息
兼容传统页面跳转:实现 HandlerExceptionResolver 接口
如果项目仍使用 JSP/Thymeleaf 渲染 HTML 页面,需要跳转到 error.jsp 这类友好视图,可采用老但稳定的方式:
- 创建类实现 HandlerExceptionResolver 接口,重写 resolveException() 方法
- 在方法内判断异常类型(如 instanceof SysException),设置 ModelAndView 对象,指定视图名和错误信息 model.addAttribute("msg", ex.getMessage())
- 该类需注册为 Spring Bean(加 @Component 或在 spring-mvc.xml 中配置)
- 注意:它对 @ResponseBody 方法无效,只适用于返回视图的 Controller
统一响应格式与错误信息分级
无论用哪种方式,真正“友好”的关键在于响应内容的设计:
立即学习“Java免费学习笔记(深入)”;
- 定义标准响应类(如 Result 或 ApiResponse),code 区分业务码(1001=用户名已存在)和系统码(500=服务器异常)
- 自定义异常类(如 BizException)携带 code 和 message,抛出时直接 new BizException(1002, "手机号格式错误")
- 非自定义异常(如 SQLException、IOException)走兜底处理,返回通用提示("系统繁忙,请稍后再试"),同时后台打 ERROR 日志并告警
- 开发环境可额外返回简单堆栈(通过 profile 控制),生产环境绝对禁止暴露路径、类名、数据库信息
补充建议:别忽略的细节
实际落地时容易踩坑的地方:
- @ControllerAdvice 默认只作用于 @Controller 类;若用了 @RestController,它同样生效(因为 @RestController = @Controller + @ResponseBody)
- 多个 @ExceptionHandler 方法匹配同一异常时,按方法声明顺序执行(Spring 5.3+ 支持 @Order 注解控制优先级)
- 静态资源(/static/**)、WebMvcConfigurer 配置的路径、Filter 抛出的异常不会被 @ControllerAdvice 捕获,需单独处理
- 配合统一日志框架(如 Logback),在异常处理器里记录异常全路径、请求 URL、用户 ID(如有),便于排查


















