Spring boot2.x-第02讲:全局异常处理
1.前言
springboot中,默认在发送异常时,会跳转值/error请求进行错误的展现,根据不同的Content-Type展现不同的错误结果,如json请求时,直接返回json格式参数。
浏览器访问异常时:
Whitelabel Error Page
This application has no explicit mapping for /error, so you are seeing this as a fallback.
Thu Sep 19 23:14:40 CST 2019
There was an unexpected error (type=Not Found, status=404).
No message available
2.全局统一异常处理
利用@ControllerAdvice和@ExceptionHandler定义一个统一异常处理类。
-
@ControllerAdvice:控制器增强,被@ExceptionHandler、@InitBinder、@ModelAttribute注解的方法,都会作用在被 @RequestMapping注解的方法上。
-
@ExceptionHandler:异常处理器,此注解的作用是当出现其定义的异常时进行处理的方法。该注解拦截异常,我们可以通过该注解实现自定义异常处理。其中,@ExceptionHandler 配置的 value 指定需要拦截的异常类型。
2.1自定义异常类
代码如下:
/**
* 平台级异常基类(存储异常码和异常消息)
**/
@Setter
@Getter
public class TongPlatformException extends RuntimeException {
private static final long serialVersionUID = -8252342484961827798L;
private String exceptionCode;
private String exceptionMessage;
public TongPlatformException(String exceptionCode, String exceptionMessage) {
// 在打印堆栈信息时会打印出来,示例:[{"exceptionCode":"123456", "exceptionMessage":"异常测试"}]
super("[{\"exceptionCode\" : \"".concat(exceptionCode).concat("\", \"exceptionMessage\" : \"").concat(exceptionMessage).concat("\"}]"));
this.exceptionCode = exceptionCode;
this.exceptionMessage = exceptionMessage;
}
}
【注意】:Spring 对于 RuntimeException类的异常才会进行事务回滚,所以我们一般自定义异常都继承该异常类。
/**
* 业务异常类
**/
public class BusinessException extends TongPlatformException {
private static final long serialVersionUID = 5964974489633380622L;
public BusinessException(String exceptionCode, String exceptionMessage) {
super(exceptionCode, exceptionMessage);
}
}
2.2异常数据模型
该模型的作用:全局异常处理类中需要使用该模型存储错误码和错误消息,然后返回给调用系统or前端页面。
@Setter
@Getter
public class ExceptionResult implements Serializable {
private static final long serialVersionUID = -7393066081035082131L;
private String retCode;
private String retMsg;
private ExceptionResult(String retCode, String retMsg) {
this.retCode = retCode;
this.retMsg = retMsg;
}
public static ExceptionResult exception(String retCode, String retMsg) {
return new ExceptionResult(retCode, retMsg);
}
}
2.3异常枚举类
public enum ExceptionEnum {
FAILED("999999", "业务执行异常!");
//自定义异常码
private String code;
//异常信息说明
private String message;
ExceptionEnum(String code, String message) {
this.code = code;
this.message = message;
}
public String getCode() {
return code;
}
public String getMessage() {
return message;
}
}
【注意】:该枚举类没有setter方法。原因:尽量不要让其他类改变预先规划好的错误码和错误消息。
2.4全局异常处理类
@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {
/**
* ExceptionHandler拦截了异常,我们可以通过该注解实现自定义异常处理。
* 其中,@ExceptionHandler 配置的 value 指定需要拦截的异常类型。
*/
@ExceptionHandler(value = {Exception.class})
// @ResponseBody
public ExceptionResult handlerException(Exception ex) {
log.info("com.tong.hao.online.service.handler.GlobalExceptionHandler.handlerException");
log.info(ex.getMessage(), ex);
if (ex instanceof BusinessException) {
BusinessException businessException = (BusinessException) ex;
return ExceptionResult.exception(businessException.getExceptionCode(), businessException.getExceptionMessage());
}
return ExceptionResult.exception(ExceptionEnum.FAILED.getCode(), ExceptionEnum.FAILED.getMessage());
}
}
【注意】:这里我使用的是@RestControllerAdvice,@RestControllerAdvice是一个组合注解,组合了@ControllerAdvice、@ResponseBody,因为我这里是演示直接返回的是内容,所以为了方便使用@RestControllerAdvice,如果你们的异常需要返回页面啊之类的,你可以使用@ControllerAdvice分别定制。
2.5Controller
@RestController
@Slf4j
@RequestMapping(value = "/test")
public class TestController {
@ApiOperation(value = "业务异常测试")
@RequestMapping(value = "/exception")
public String testException() {
StringBuilder strBuilder = new StringBuilder("abc");
try {
int a = Integer.valueOf(strBuilder.toString());
} catch (NumberFormatException e) {
// 此处抛出业务异常,会被GlobalExceptionHandler中的ExceptionHandler拦截进行后续处理
throw BusinessUtils.createBusinessException("123456", "异常测试");
}
return strBuilder.toString();
}
}
2.6测试
在浏览器地址栏输入 http://127.0.0.1:9090/tong/test/exception
页面返回如下:
{“retCode”:“123456”,“retMsg”:“异常测试”}
2.7执行流程
本人见解:
- 浏览器访问/test/exception;
- TestController.testException()方法中抛出自定义业务异常BusinessException;
- 然后被全局异常处理类GlobalExceptionHandler拦截;
- 再然后返回ExceptionResult(存储了自定义异常的错误码和错误消息);
- 由于GlobalExceptionHandler使用的controller增强器使用的是@RestControllerAdvice注解,所以,最终返回的是json格式的数据。
参考:
SpringBoot | 第八章:统一异常、数据校验处理
https://blog.lqdev.cn/2018/07/20/springboot/chapter-eight/
Spring Boot 系列 - @ControllerAdvice & 拦截异常并统一处理
https://my.oschina.net/magicalSam/blog/1456337
9.玩转Spring Boot 全局异常处理@ControllerAdvice
https://blog.youkuaiyun.com/cl_andywin/article/details/53790510
本文详细介绍SpringBoot中全局异常处理的实现方法,包括自定义异常类、异常数据模型、异常枚举类及全局异常处理类的设计。通过具体示例展示如何在Controller中抛出异常,并由全局异常处理类统一捕获和处理。

被折叠的 条评论
为什么被折叠?



