spring MVC统一异常处理的几种方式

╰+哭是因爲堅強的太久メ 2021-09-18 16:30 499阅读 0赞

异常统一处理分为三种方式:

1.使用@ExceptionHandler + @ControllerAdvice注解

2.使用spring AOP (@AfterThrowing + @Aspect)

3.继承HandlerExceptionResolver 接口

4.使用@ExceptionHandler注解

1.使用@ExceptionHandler + @ControllerAdvice注解

此方法需要进行异常处理的方法必须与出错的方法在同一个Controller里面。那么当代码加入了 @ControllerAdvice,则不需要必须在同一个 controller 中了。这也是 Spring 3.2 带来的新特性。从名字上可以看出大体意思是控制器增强。 也就是说,@controlleradvice + @ ExceptionHandler 也可以实现全局的异常捕捉。

请确保此WebExceptionHandle 类能被扫描到并装载进 Spring 容器中。

  1. @RestControllerAdvice
  2. public class RestMyExceptionHandler {
  3. private static final Logger log = LoggerFactory.getLogger(RestMyExceptionHandler.class);
  4. @ExceptionHandler(value = Exception.class)
  5. public String handle(Exception e){
  6. log.info("参数异常:"+e.getMessage());
  7. return e.getMessage();
  8. }
  9. }

继承 ResponseEntityExceptionHandler 类来实现针对 Rest 接口 的全局异常捕获,并且可以返回自定义格式:

  1. @Slf4j
  2. @ControllerAdvice
  3. public class ExceptionHandlerBean extends ResponseEntityExceptionHandler {
  4. /**
  5. * 数据找不到异常
  6. * @param ex
  7. * @param request
  8. * @return
  9. * @throws IOException
  10. */
  11. @ExceptionHandler({DataNotFoundException.class})
  12. public ResponseEntity<Object> handleDataNotFoundException(RuntimeException ex, WebRequest request) throws IOException {
  13. return getResponseEntity(ex,request,ReturnStatusCode.DataNotFoundException);
  14. }
  15. /**
  16. * 根据各种异常构建 ResponseEntity 实体. 服务于以上各种异常
  17. * @param ex
  18. * @param request
  19. * @param specificException
  20. * @return
  21. */
  22. private ResponseEntity<Object> getResponseEntity(RuntimeException ex, WebRequest request, ReturnStatusCode specificException) {
  23. ReturnTemplate returnTemplate = new ReturnTemplate();
  24. returnTemplate.setStatusCode(specificException);
  25. returnTemplate.setErrorMsg(ex.getMessage());
  26. return handleExceptionInternal(ex, returnTemplate,
  27. new HttpHeaders(), HttpStatus.OK, request);
  28. }
  29. }

2.使用spring AOP (@AfterThrowing + @Aspect)

  1. @Aspect
  2. @Component
  3. public class WebExceptionAspect {
  4. private static final Logger logger = LoggerFactory.getLogger(WebExceptionAspect.class);
  5. //凡是注解了RequestMapping的方法都被拦截
  6. @Pointcut("@annotation(org.springframework.web.bind.annotation.RequestMapping)")
  7. private void webPointcut() {
  8. }
  9. /**
  10. * 拦截web层异常,记录异常日志,并返回友好信息到前端 目前只拦截Exception,是否要拦截Error需再做考虑
  11. * @param e 异常对象
  12. */
  13. @AfterThrowing(pointcut = "webPointcut()", throwing = "e")
  14. public void handleThrowing(Exception e) {
  15. e.printStackTrace();
  16. logger.error("发现异常!" + e.getMessage());
  17. logger.error(JSON.toJSONString(e.getStackTrace()));
  18. //这里输入友好性信息
  19. writeContent("出现异常");
  20. }
  21. /**
  22. * 将内容输出到浏览器
  23. *
  24. * @param content 输出内容
  25. */
  26. private void writeContent(String content) {
  27. HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes())
  28. .getResponse();
  29. response.reset();
  30. response.setCharacterEncoding("UTF-8");
  31. response.setHeader("Content-Type", "text/plain;charset=UTF-8");
  32. response.setHeader("icop-content-type", "exception");
  33. PrintWriter writer = null;
  34. try {
  35. writer = response.getWriter();
  36. } catch (IOException e) {
  37. e.printStackTrace();
  38. }
  39. writer.print(content);
  40. writer.flush();
  41. writer.close();
  42. }
  43. }

3.继承HandlerExceptionResolver 接口

这种方式可以进行全局的异常控制。例如:

  1. @Component
  2. public class ExceptionTest implements HandlerExceptionResolver{
  3. /**
  4. * TODO 简单描述该方法的实现功能(可选).
  5. * @see org.springframework.web.servlet.HandlerExceptionResolver#resolveException(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, java.lang.Object, java.lang.Exception)
  6. */
  7. public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
  8. System.out.println("This is exception handler method!");
  9. return null;
  10. }
  11. }

4.使用@ExceptionHandler注解

使用该注解有一个不好的地方就是:进行异常处理的方法必须与出错的方法在同一个Controller里面。使用如下:

  1. @Controller
  2. public class GlobalController {
  3. /**
  4. * 用于处理异常的
  5. * @return
  6. */
  7. @ExceptionHandler({MyException.class})
  8. public String exception(MyException e) {
  9. System.out.println(e.getMessage());
  10. e.printStackTrace();
  11. return "exception";
  12. }
  13. @RequestMapping("test")
  14. public void test() {
  15. throw new MyException("出错了!");
  16. }
  17. }

可以看到,这种方式最大的缺陷就是不能全局控制异常。每个类都要写一遍。

发表评论

表情:
评论列表 (有 0 条评论,499人围观)

还没有评论,来说两句吧...

相关阅读

    相关 Spring MVC统一异常处理实战

    1 描述  在J2EE项目的开发中,不管是对底层的数据库操作过程,还是业务层的处理过程,还是控制层的处理过程,都不可避免会遇到各种可预知的、不可预知的异常需要处理。每个过程