Spring MVC 多种异常处理
Spring MVC 提供了多种灵活的异常处理机制,确保应用能够优雅地处理错误并返回友好的响应。
异常处理方式概览
| 方式 | 适用场景 | 特点 |
|---|---|---|
| @ExceptionHandler | 单个Controller内 | 局部处理,优先级最高 |
| @ControllerAdvice | 全局跨Controller | 统一处理,推荐使用 |
| HandlerExceptionResolver | 底层接口 | 灵活定制,适合框架级 |
| SimpleMappingExceptionResolver | 页面跳转 | 配置式,适合传统Web |
@ExceptionHandler 局部处理
在Controller内部声明异常处理方法:
Java
@RestController
@RequestMapping("/user")
public class UserController {
@GetMapping("/{id}")
public User getUser(@PathVariable Long id) {
User user = userService.findById(id);
if (user == null) {
throw new UserNotFoundException("用户不存在");
}
return user;
}
@ExceptionHandler(UserNotFoundException.class)
public ResponseEntity<String> handleUserNotFound(UserNotFoundException e) {
return ResponseEntity.status(404).body(e.getMessage());
}
@ExceptionHandler(Exception.class)
public ResponseEntity<String> handleException(Exception e) {
return ResponseEntity.status(500).body("服务器内部错误");
}
}
@ControllerAdvice 全局处理
创建全局异常处理类,统一管理所有Controller异常:
Java
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(RuntimeException.class)
@ResponseBody
public ResponseEntity<Map<String, Object>> handleRuntimeException(RuntimeException e) {
Map<String, Object> result = new HashMap<>();
result.put("code", 500);
result.put("message", e.getMessage());
result.put("timestamp", System.currentTimeMillis());
return ResponseEntity.status(500).body(result);
}
@ExceptionHandler(IllegalArgumentException.class)
@ResponseBody
public ResponseEntity<Map<String, Object>> handleIllegalArgument(IllegalArgumentException e) {
Map<String, Object> result = new HashMap<>();
result.put("code", 400);
result.put("message", e.getMessage());
return ResponseEntity.badRequest().body(result);
}
@ExceptionHandler(MethodArgumentNotValidException.class)
@ResponseBody
public ResponseEntity<Map<String, Object>> handleValidation(MethodArgumentNotValidException e) {
Map<String, Object> result = new HashMap<>();
result.put("code", 400);
result.put("message", "参数校验失败");
result.put("errors", e.getBindingResult().getFieldErrors());
return ResponseEntity.badRequest().body(result);
}
}
HandlerExceptionResolver 接口实现
实现自定义异常解析器:
Java
@Component
public class CustomExceptionResolver implements HandlerExceptionResolver {
@Override
public ModelAndView resolveException(HttpServletRequest request,
HttpServletResponse response,
Object handler,
Exception ex) {
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
response.setContentType("application/json;charset=UTF-8");
try {
Map<String, Object> error = new HashMap<>();
error.put("code", 500);
error.put("message", ex.getMessage());
error.put("path", request.getRequestURI());
ObjectMapper mapper = new ObjectMapper();
response.getWriter().write(mapper.writeValueAsString(error));
} catch (IOException e) {
e.printStackTrace();
}
return new ModelAndView();
}
}
SimpleMappingExceptionResolver 配置
适用于传统Web应用,异常发生时跳转到指定错误页面:
Java
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Bean
public SimpleMappingExceptionResolver exceptionResolver() {
SimpleMappingExceptionResolver resolver = new SimpleMappingExceptionResolver();
Properties mappings = new Properties();
mappings.setProperty("UserNotFoundException", "error/404");
mappings.setProperty("UnauthorizedException", "error/403");
mappings.setProperty("Exception", "error/500");
resolver.setExceptionMappings(mappings);
resolver.setDefaultErrorView("error/default");
resolver.setExceptionAttribute("exception");
return resolver;
}
}
异常处理优先级
- @ExceptionHandler(Controller内) - 最高优先级
- @ControllerAdvice中的@ExceptionHandler - 次优先级
- HandlerExceptionResolver - 最低优先级
局部@ExceptionHandler会覆盖全局@ControllerAdvice中的同类型异常处理。
要点总结
- @ExceptionHandler适用于Controller内部特定异常处理
- @ControllerAdvice是推荐的全局异常处理方式
- HandlerExceptionResolver提供底层定制能力
- SimpleMappingExceptionResolver适合传统页面跳转场景
- 优先级:局部 > 全局 > 框架默认
📝 发现内容有误?点击此处直接编辑