up:: SpringBoot电商项目用户模块注册接口开发之自定义异常类
说明:
(1) 为什么写这篇博客?:在【SpringBoot电商项目用户模块注册接口开发】中,在Service层中遇到了【用户名重复】的情况,然后Service层把这个情况做成了一个异常,并向上抛出;Controller获得了这个异常,继续向上抛出;
那么,就出现了以下问题:【接口返回格式,不符合,接口文档定义的统一规范】,【暴露异常的具体信息,不安全】;
所以,我们要对Controller继续抛的异常,进行统一处理;
(2) 本篇博客的点:
●【GlobalExceptionHandler】的书写;其中用到了【@ControllerAdvice】注解和【@ExceptionHandler(Exception.class)】注解;
● 在实际开发中,无论是【系统异常】还是【自定义异常】,需要细分一下;
(3) 本篇博客参考的博客有:
● 【Springboot全局异常处理GlobalExceptionHandler】,该文的作者是【weixin_33910460】;但,该文亦是转载博客;
● 【SpringBoot处理全局统一异常】,该文的作者是【冬眠的山谷】;
● 【项目使用 GlobalExceptionHandler 自定义异常 一】,该文的作者是【香吧香】;
● 【GlobalExceptionHandle(全局统一异常处理)】,该文的作者是【knock】;
一:创建【GlobalExceptionHandler】去解决上述问题;
1.创建【GlobalExceptionHandler】,去捕获、拦截、并处理Controller抛出的异常;
GlobalExceptionHandler类:
说明:
(1) 内容整体说明;
(2) 细节分析:【@ControllerAdvice】注解;
●【@ControllerAdvice】相当于是一个Controller增强器,可对controller中被 @RequestMapping注解的方法(也就是Controller中,那些设置了url,可以接受并处理前端请求的方法),加一些逻辑处理;
● 即,如果Controller中的方法如果满足这两个条件:【这个方法使用了@RequestMapping、 @GetMapping或@PosttMapping注解:也就是这个方法是一个设置了url,可以接受并处理前端请求的方法】+【这个方法抛出了异常】;那么这个Controller中的方法,就会被【使用了@ControllerAdvice注解的,GlobalExceptionHandler类】给捕获;然后,就会根据【GlobalExceptionHandler类】中编写的具体内容,去拦截异常,给这个方法添加一些处理逻辑;(对于,这儿的情况来说,这个处理逻辑就是:提取异常信息,构建API统一返回对象;)
● 即,【@ControllerAdvice】注解的主要作用是:捕获;但是,只捕获,而不去处理可不行;所以,如果想要处理的话,就需要下面介绍的【@ExceptionHandler(Exception.class)】去拦截异常,并对其做相应的处理;
(3) 细节分析:【@ExceptionHandler(Exception.class)】注解;
●【@ExceptionHandler】用来统一处理方法抛出的异常,可以给注解添加参数,参数是某个异常类的class,代表这个方法专门处理该类异常。
如下图所示:
(4) 既然【GlobalExceptionHandler】的目的是,处理异常,把其转化为符合接口返回格式的API统一返回对象的格式;所以,这儿我们也是返回的API统一返回对象;
(5) 又因为,返回格式要求是JSON格式;所以,这个方法处理完后,返回的格式自然要求是JSON格式;所以这儿我们在方法上使用了@ResponseBody注解;
● @ControllerAdvice 捕获 Controller 层抛出的异常,如果添加 @ResponseBody 返回信息则为JSON格式。
● @RestControllerAdvice 相当于 @ControllerAdvice 与 @ResponseBody 的结合体。
(6) 因为,系统异常我们也需要得到对应API统一返回对象,同样为了快速构建对应的ApiRestResponse对象;系统异常对应的错误信息,我们也放在了枚举类中;
2.效果;
(1)这是原先的情况;
(2)这是现在的情况;
3.创建【GlobalExceptionHandler】后的:一切就会很给力了;
这样以后,以后我们如果在Service层遇到了异常后;Service层大胆的向上抛就行了,Controller接到这个异常后,也继续抛就行了,完全不用怕,因为,我们上面编写的【GlobalExceptionHandler】会很友好的去处理这个异常,把其转化为API统一返回对象,以符合接口返回的格式;
二:进一步,补充说明;
这儿的内容,参考的文章有:
● 【Springboot全局异常处理GlobalExceptionHandler】,该文的作者是【weixin_33910460】;但,该文亦是转载博客;
● 【SpringBoot处理全局统一异常】,该文的作者是【冬眠的山谷】;
● 【项目使用 GlobalExceptionHandler 自定义异常 一】,该文的作者是【香吧香】;
● 【GlobalExceptionHandle(全局统一异常处理)】,该文的作者是【knock】;
通过上面四篇博客,主要给自己以下启发:
启发1:
在实际项目中,对于一个复杂的系统,其业务往往会很复杂,为了应对各种业务情况;我们往往需要定义多种【自定义异常】,来表征不同的业务错误的情况;
启发2:
即使,对于系统异常,我们不能全部用顶级的Exception来统一处理;而是要细分处理,比如细分为【RuntimeException】、【IOException】;(即,有的时候,我们也需要对其分开处理,而不是仅仅只用Exception去处理;)
应对措施:
自然,为了应对【细粒度上的,系统异常】和【多种自定义异常】;我们在【GlobalExceptionHandler】也要分别的去处理;(自然,为了在快速构建这些【细粒度上的 ,系统异常】和【多种自定义异常】的对象,以及,对应上接口返回格式;→ 我们自定义异常的属性也要符合接口返回格式的要求;同时,可以在枚举类来统一管理【细粒度上的 ,系统异常】和【多种自定义异常】这些异常对应的错误信息;)
即,更加符合实际的做法是,如
【GlobalExceptionHandle(全局统一异常处理)】中的代码所示:
稍微看下,应该能懂哈,能明白这个意思;