这是我参与11月更文挑战的第2天,活动详情查看:2021最后一次更文挑战
前言
当前端向后端请求数据的时候,正常情况下,接口会返回我们理想的格式.但是在后端程序出现问题的情况下,返回的默认的数据不一定是我们想要的类型,所有当程序出现异常时,我们需要有一个统一的全局异常处理器,将异常数据处理成,我们需要的格式,并返回前台
需要处理异常的位置
(一) 通过controller抛出的异常
该异常是业务运行时导致的异常,在controller发生,或者能向上抛出到controller的异常,这种异常通过自定义异常类并注解@ControllerAdvice
或者@RestControllerAdvice
即可达到目的:
1 | java复制代码@RestControllerAdvice |
使用注意
@RestControllerAdvice
注解,可以用于定义@ExceptionHandler
、@InitBinder
、@ModelAttribute
,并应用到所有@RequestMapping
中@RestControllerAdvice
继承了@ControllerAdvice
功能的子类,将返回信息写入到Response的Body中(因为也注解了@ResponseBody
),因此如果是json交互的前后单分离项目直接用@RestControllerAdvice
的更好.@RestControllerAdvice
和@ControllerAdvice
注解包含一些属性:
属性 | 解释 |
---|---|
@ControllerAdvice(“org.zdc.controllers”) | 捕获指定包中的控制器的异常 |
@ControllerAdvice(annotations = RestController.class) | 捕获带有注解@RestController的控制器的异常 |
@ControllerAdvice(assignableTypes = {AbstractController.class}) | 捕获有带有指定签名的控制器异常 |
4. 如果不生效,则需要注意观察是否被filter,Aspect等拦截,或者异常不是在扫描的包下抛出的. | |
5. 可以定义多个@ExceptionHandler , 当异常出现的时候,程序会从上到下依次进行匹配,匹配成功之后就会终止继续匹配,因此最后一个@ExceptionHandler 应该定义为Exception.class |
|
6. @ExceptionHandler 定义的原则: 除了最后一个Exception.class 外, 其他的异常则需要按需实现.比如:CustomException.class 是业务异常,返回的错误信息,只包含e.getMessage() 即可,而@Validated 参数验证异常BindException.class ,则需要解析异常愿意,好让用户明白具体是哪个参数异常导致的 |
(二) 拦截404或者服务器错误等未进入controller的异常
当请求了一个未定义的请求或解析请求报错的时候,程序会抛出错误,并把错误转发到/error
接口上,然后该返回错误的数据,但是返回的数据格式可能不是我们想要的,所以需要实现一个默认的controller并实现该/error
方法.
1 | typescript复制代码@RestController |
看到这里你应该看到了转发过来的自定义CustomException异常
,实际上我们可以手动将异常转发到这里(比如自定义filter中), 使用方法请文章全局搜索手动转发到/error接口
(三) filter等自定义代码中异常
在自定义的filter中,业务判断不符的时候需要中断操作抛出异常、
在自定义的Aspect中,代理方法报错需要抛出异常,等等,一次我们需要注意处理这里的异常
filter中使用
1 | vbscript复制代码@Component |
当然在这里我们基本上都时使用第三种方式直接通过response写回去.
1 | arduino复制代码 作者:ZOUZDC |
本文转载自: 掘金