如何使用 Spring Boot 实现异常处理?
这些是 Spring Boot 处理异常 的几种方式。我们来逐步拆解,看懂每种方式的用途和区别。
1、@ExceptionHandler
处理局部异常
这是最简单的方式,在 当前 Controller 内 处理异常。
@Controller
public class ExceptionHandlerController {
@RequestMapping("/excep")
public String exceptionMethod(Model model) throws Exception {
String a = null;
System.out.println(a.charAt(1)); // NullPointerException
int num = 1 / 0; // ArithmeticException
model.addAttribute("message", "没有抛出异常");
return "index";
}
@ExceptionHandler(value = {ArithmeticException.class, NullPointerException.class})
public String arithmeticExceptionHandle(Model model, Exception e) {
model.addAttribute("message", "@ExceptionHandler 处理的异常:" + e.getMessage());
return "index";
}
}
📌 重点
@ExceptionHandler
用来捕获指定类型的异常(这里只能处理ArithmeticException
和NullPointerException
)。- 仅限当前 Controller 内,其他 Controller 发生异常不会被这个方法处理。
- 处理完异常后,返回一个指定的视图(这里返回
"index"
页面)。
2、@ControllerAdvice + @ExceptionHandler
处理全局异常
上面的 @ExceptionHandler
只能处理单个 Controller 内的异常,如果想要在全局范围内处理异常,就可以用 @ControllerAdvice
。
@ControllerAdvice
public class ControllerAdviceException {
@ExceptionHandler(value = {NullPointerException.class})
public String NullPointerExceptionHandler(Model model, Exception e) {
model.addAttribute("message", "@ControllerAdvice + @ExceptionHandler 处理的异常:" + e.getMessage());
return "index";
}
}
📌 重点
@ControllerAdvice
作用于所有 Controller,可以统一处理全局异常。@ExceptionHandler(value = {NullPointerException.class})
只捕获NullPointerException
。- 发生异常后,会跳转到
"index"
页面,并在 model 里添加异常信息。
3、使用 SimpleMappingExceptionResolver
统一映射异常
前面两种方式是通过 方法 处理异常,这种方式是通过配置来映射异常到页面。
@Configuration
public class SimpleMappingException {
@Bean
public SimpleMappingExceptionResolver getSimpleMappingExceptionResolver() {
SimpleMappingExceptionResolver resolver = new SimpleMappingExceptionResolver();
Properties mappings = new Properties();
// 定义异常和页面的映射关系
mappings.put("java.lang.NullPointerException", "index");
mappings.put("java.lang.ArithmeticException", "index");
resolver.setExceptionMappings(mappings); // 设置异常映射
return resolver;
}
}
📌 重点
- 自动匹配异常,
NullPointerException
和ArithmeticException
发生时,直接跳转"index"
页面。 - 不需要手动写
@ExceptionHandler
方法,通过配置Properties
直接映射。
适合场景
- 只需要简单页面跳转,不需要动态返回错误信息。
4、实现 HandlerExceptionResolver
处理异常
如果想要更灵活地控制异常处理逻辑,可以实现 HandlerExceptionResolver
接口。
@Configuration
public class HandlerException implements HandlerExceptionResolver {
@Override
public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("message", "HandlerExceptionResolver 处理的异常");
// 根据异常类型,跳转到不同的页面
if (ex instanceof NullPointerException) {
modelAndView.setViewName("index");
}
if (ex instanceof ArithmeticException) {
modelAndView.setViewName("index");
}
return modelAndView;
}
}
📌 重点
- 比
SimpleMappingExceptionResolver
更灵活,可以对不同异常执行不同的逻辑。 - 可以修改 HTTP 响应状态,比如
response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
- 适用于复杂的异常处理需求,比如:
- 记录日志
- 返回不同的错误页面
- 发送错误信息到前端 API
总结
方式 | 作用范围 | 适用场景 | 缺点 |
---|---|---|---|
@ExceptionHandler | 只能处理当前 Controller 的异常 | 处理局部异常,简单的 Controller 级异常处理 | 只能用于当前 Controller,无法全局使用 |
@ControllerAdvice + @ExceptionHandler | 作用于所有 Controller | 处理全局异常,适用于统一异常处理 | 需要写多个方法分别处理不同的异常 |
SimpleMappingExceptionResolver | 作用于全局 | 仅用于异常 → 页面跳转,适用于简单场景 | 不能自定义返回 JSON 响应,无法进行复杂异常处理 |
HandlerExceptionResolver | 作用于全局 | 需要灵活处理异常,如记录日志、返回 JSON、跳转不同页面等 | 需要手动编写逻辑 |
如果是 Spring Boot + 前后端分离的项目,一般会用 @ControllerAdvice
+ @ExceptionHandler
返回 JSON 格式的错误信息,比如:
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(NullPointerException.class)
public ResponseEntity<String> handleNullPointerException(Exception e) {
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body("发生空指针异常:" + e.getMessage());
}
@ExceptionHandler(ArithmeticException.class)
public ResponseEntity<String> handleArithmeticException(Exception e) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("发生算术异常:" + e.getMessage());
}
}
🚀 最佳实践
- 前后端分离项目,推荐使用
@ControllerAdvice + @ExceptionHandler
返回 JSON。 - 后端渲染页面(如
Thymeleaf
),可以用SimpleMappingExceptionResolver
简单映射异常到错误页面。 - 需要复杂逻辑(比如日志、发送邮件通知),可以用
HandlerExceptionResolver
自定义处理。