springboot异常统一处理_SpringMVC中如何统一处理异常?

今天和大家谈谈SpringMVC中如何统一处理异常。本篇文章我们还是以简单明了的风格和大家介绍。

我们使用SpringBoot来进行讲解,其版本为2.2.1.RELEASE。首先来谈一下SpringMVC和Http状态码的关系。

把异常映射为HTTP状态码

需要提到的是在SpringMVC中出现以下异常时,SpringMVC就会把这些异常自动转换成特定的Http状态码。异常和状态码的映射关系如下:

  1. BindException->400:BadRequest
  2. ConversionNotSupportedException->500:Internal Server Error
  3. HttpMediaTypeNotAcceptableException->406:Not Acceptable
  4. HttpMediaTypeNotSupportedException->415:Unsupported Media Type
  5. HttpMessageNotReadableException->400:BadRequest
  6. HttpMessageNotWritableException->500:Internal Server Error
  7. HttpRequestMethodNotSupportedException->405:Method Not Allowed
  8. MethodArgumentNotValidException->500:Internal Server Error
  9. MissingServletRequestParameterException->400:BadRequest
  10. MissingServletRequestPartException->400:BadRequest
  11. TypeMismatchException->400:BadRequest

除此之外,我们还可以把我们自定义的异常也映射为HTTP状态码。达到这种目的的方式是用一个注解来标记这个我们自定义的异常,这个注解就是@ResponseStatus,用法如下:

49ae8a9b680bf58d5925168e8cabbfcc.png

@ResponseStatus标记异常类

@ResponseStatus注解的value属性表示返回的HTTP状态码,reason表示消息。当Controller抛出ParamException异常时,SpringMVC会返回一个400的HTTP状态码,因为HttpStatus.BAD_REQUEST的值是400。

5d4a0e7e4293aa4430f6867ae79cbd05.png

抛出ParamException

请求index3路径之后浏览器会收到400的响应,如图:

5c630bf9a47f04573f87ac2b4ae88a4c.png

type=Bad Request, status=400

那么如果我们把ParamException异常类的注解@ResponseStatus去掉,浏览器又会收到什么状态码呢?去掉后如图:

e8f4adf7bc89d594b8af36df73b48d87.png

注释掉@ResponseStatus

浏览器得到的状态如下,我们可以从图中看到HTTP状态是500:

3460c1a9c05bef8dce7a56a734c17a9c.png

type=Internal Server Error, status=500

这就说明了我们是可以通过@ResponseStatus注解把ParamException异常映射为400状态码的。

在SpringMVC的开发过程中仅仅把特定的异常映射为HTTP状态码是远远不够的,我们还需要统一处理Controller中抛出的异常。那么如何实现呢?我们在这里提供2种方式,下面我们一一来看。

第一种:在Controller的基类中统一处理

首先要说明的是@ExceptionHandler注解,这个注解是用来标记一个方法是异常处理器。这个注解标记的方法能够处理当前Controller中所有映射地址抛出的异常,如果把这个注解用在一个Controller的基类中,让所有的Controller都继承这个基类,那么这个被@ExceptionHandler注解标记的方法就能处理所有Controller抛出的异常了。

先看一下基类如何设置:

468b58b765fee5b43958e3effaf8ef61.png

基类Controller

从图中可以看到这个基类非常简单,仅仅一个方法,而且这个方法被@ExceptionHandler注解标记,括号中的参数表示这个方法用于处理什么类型的异常。这个方法有一个参数,这个参数可以接收到抛出的异常。

再让其他的具体的Controller继承这个基类就可以了,如图:

6aaa5143fcc06849398d539677a8a2a3.png

继承基类

这样就完成了,在基类的myExceptionHandler方法中就可以统一处理所有Controller中抛出的异常了。

第二种:在Controller的切面中统一处理

这种方式就是为Controller设置一个切面,在切面中处理异常。

首先定义一个切面,定义切面的方式是在切面类上添加@ControllerAdvice注解就可以了,标记完切面之后再通过@ExceptionHandler注解定义异常处理方法,如图:

5c167fdcf9e0f495e921157a93a90734.png

Controller的切面

然后我们就可以定义控制器了,而且我们的控制器也不用继承基类控制器了,如图:

c6c20892f0bae79401c7bb3bf47e7b86.png

一个普通的Controller

这样所有Controller抛出的异常都能被Controller的切面中的异常处理器捕获到了,是不是很简单呢?

结束语

今天简单和大家分享了如果统一处理Controller的异常,在这里简单总结一下,第一点就是定义处理异常的handler,这是必须的,而且无论你是通过基类处理还是通过切面处理这都是不能缺少的。在这两种方式中定义异常handler的方式都是通过@ExceptionHandler注解完成的。

好啦,就这些了,希望对大家能有帮助。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值