详解Spring MVC优雅处理异常的6种方式
异常处理是每个 Java程序员需要面对的一个问题,在Spring中,提供了多种机制来处理控制器抛出的异常,确保应用程序在面对各种错误情况时能够优雅地响应。这篇文章,我们来详细分析Spring MVC中,几种优雅处理异常的方式。
1. 使用@ExceptionHandler注解
@ExceptionHandler
注解允许在单个Controller中定义处理特定异常的方法。当 Controller的方法抛出指定的异常时,Spring会调用相应的处理方法。
如下示例,展示了如何在 Controller层优雅处理异常:
@Controller public class MyController { @RequestMapping("/example") public String example() { // 可能抛出异常的业务逻辑 if (1/0) { throw new CustomException("自定义异常发生"); } return "success"; } @ExceptionHandler(CustomException.class) public ModelAndView handleCustomException(CustomException ex) { ModelAndView mav = new ModelAndView(); mav.addObject("message", ex.getMessage()); mav.setViewName("errorPage"); return mav; } }
优点: 简单直观,适用于单个控制器的异常处理。
缺点: 如果多个控制器需要相同的异常处理逻辑,需要在每个控制器中重复定义。
2. 使用@ControllerAdvice注解
@ControllerAdvice
是一种全局的异常处理方式,可以应用于所有 Controller。通过将异常处理逻辑集中在一个地方,可以避免代码重复,提高维护性。
如下示例,展示了如何使用@ControllerAdvice
优雅处理全局异常:
@ControllerAdvice public class GlobalExceptionHandler { @ExceptionHandler(CustomException.class) public ModelAndView handleCustomException(CustomException ex) { ModelAndView mav = new ModelAndView(); mav.addObject("message", ex.getMessage()); mav.setViewName("errorPage"); return mav; } @ExceptionHandler(Exception.class) public ModelAndView handleGeneralException(Exception ex) { ModelAndView mav = new ModelAndView(); mav.addObject("message", "发生了一个错误: " + ex.getMessage()); mav.setViewName("errorPage"); return mav; } }
优点:
- 全局统一管理异常处理逻辑。
- 代码更清晰,易于维护。
缺点:
- 全局处理不适用于需要针对某些控制器有特殊处理需求的情况,需结合其他方法使用。
3. 实现HandlerExceptionResolver接口
HandlerExceptionResolver
是一种更底层的异常处理机制,通过实现该接口,开发者可以自定义异常解析逻辑。
如下示例,展示了如何实现HandlerExceptionResolver
接口优雅处理异常:
public class MyExceptionResolver implements HandlerExceptionResolver { @Override public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) { ModelAndView mav = new ModelAndView(); if (ex instanceof CustomException) { mav.addObject("message", ex.getMessage()); mav.setViewName("customErrorPage"); } else { mav.addObject("message", "未知错误"); mav.setViewName("errorPage"); } return mav; } }
配置:
在 Spring 配置文件中注册自定义异常解析器:
<bean class="com.example.MyExceptionResolver"/>
优点:
高度灵活,可以处理各种复杂的异常情景。
缺点:
- 需要更多的配置和实现工作。
- 不如注解方式直观,适用性较低。
4. 使用@ResponseStatus注解
@ResponseStatus
注解可以用于自定义异常对应的 HTTP 状态码和错误信息,当抛出带有该注解的异常时,Spring会自动设置相应的状态码。
如下示例,展示了如何使用@ResponseStatus
注解优雅处理异常:
@ResponseStatus(value = HttpStatus.NOT_FOUND, reason = "资源未找到") public class ResourceNotFoundException extends RuntimeException { public ResourceNotFoundException(String message) { super(message); } }
使用:
@Controller public class MyController { @RequestMapping("/resource") public String getResource() { // 假设资源未找到 throw new ResourceNotFoundException("资源ID不存在"); } }
优点:
简单快捷,适用于直接映射到特定 HTTP 状态码的异常情况。
缺点:
无法返回自定义的错误页面或更复杂的错误信息。
5. 使用ResponseEntity和@RestControllerAdvice
在构建 RESTful API时,常用ResponseEntity
来返回自定义的错误响应,并结合@RestControllerAdvice
可以全局处理异常并返回 JSON 格式的错误信息。
如下示例,展示了如何使用ResponseEntity
和@RestControllerAdvice
来处理 RESTful API的异常:
@RestControllerAdvice public class RestExceptionHandler { @ExceptionHandler(CustomException.class) public ResponseEntity<ErrorResponse> handleCustomException(CustomException ex) { ErrorResponse error = new ErrorResponse("CUSTOM_ERROR", ex.getMessage()); return new ResponseEntity<>(error, HttpStatus.BAD_REQUEST); } @ExceptionHandler(Exception.class) public ResponseEntity<ErrorResponse> handleGeneralException(Exception ex) { ErrorResponse error = new ErrorResponse("GENERAL_ERROR", "内部服务器错误"); return new ResponseEntity<>(error, HttpStatus.INTERNAL_SERVER_ERROR); } } public class ErrorResponse { private String errorCode; private String errorMessage; // 构造方法、getter 和 setter }
优点:
- 适用于 RESTful 服务,能够返回结构化的错误信息(如 JSON)。
- 全局统一管理,易于维护。
缺点:
需要定义额外的错误响应类。
6. 使用@ControllerAdvice和@ExceptionHandler
如果使用 Spring Boot,可以更便捷地使用 @ControllerAdvice
结合自动配置实现异常处理。
如下示例,展示了如何使用@ControllerAdvice
和@ExceptionHandler
来处理异常:
@RestControllerAdvice public class GlobalExceptionHandler { @ExceptionHandler(MethodArgumentNotValidException.class) public ResponseEntity<ValidationErrorResponse> handleValidationExceptions( MethodArgumentNotValidException ex) { ValidationErrorResponse errors = new ValidationErrorResponse(); ex.getBindingResult().getAllErrors().forEach((error) -> { errors.addError(((FieldError) error).getField(), error.getDefaultMessage()); }); return new ResponseEntity<>(errors, HttpStatus.BAD_REQUEST); } // 其它异常处理方法 }
优点:
- 与 Spring Boot 无缝集成,减少配置。
- 提供了诸多便利的功能,如自动处理验证错误等。
7. 总结
本文,我们分析了 Spring MVC优雅处理异常的几种方法以及代码示例,我们可以根据具体需求选择合适的方法:
- 局部控制器处理:使用
@ExceptionHandler
注解,适用于单个控制器的特定异常处理。 - 全局处理:使用
@ControllerAdvice
或@RestControllerAdvice
,适用于跨多个控制器的统一异常处理。 - 自定义解析:实现
HandlerExceptionResolver
接口,适用于需要高度自定义的异常处理逻辑。 - 状态码注解:使用
@ResponseStatus
注解,适用于简单的异常状态码映射。 - RESTful API:结合
ResponseEntity
和全局异常处理,返回结构化的错误响应。
从实际工作来看,@ControllerAdvice
或 @RestControllerAdvice
是使用频率最高的一种方式。
到此这篇关于详解Spring MVC优雅处理异常的6种方式的文章就介绍到这了,更多相关Spring MVC处理异常内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
相关文章
注意Java中 new BigDecimal(double val) 的使用
这篇文章主要介绍了注意Java中 new BigDecimal(double val) 的使用,文章围绕主题展开详细的内容介绍,具有一定的参考价值,需要的朋友可以参考一下2022-07-07Springboot+ElementUi实现评论、回复、点赞功能
这篇文章主要介绍了通过Springboot ElementUi实现评论、回复、点赞功能。如果是自己评论的还可以删除,删除的规则是如果该评论下还有回复,也一并删除。需要的可以参考一下2022-01-01
最新评论