一、前话
看本文之前请先看《前后端分离开发:Spring Boot返回统一的数据格式》了解如何统一返回结果类。本文是基于统一返回结果类实现的统一异常处理。
二、什么是统一异常处理
- 在上述的另外一篇文章中,介绍了前后端分离中如何把后端的返回数据封装为统一的结果类。我们想让异常结果也显示为统一的返回结果对象,并且统一处理系统的异常信息,那么需要统一异常处理。这样从后端返回结果就真正意义上统一了。
1 为统一异常处理前的后端返回的默认异常信息
三、统一异常处理
1 分析
- 一般在微服务架构的应用中,有许多的服务模块,如果要统一异常处理需要对每一个模块都进行统一。因此好的做法是,在服务模块之外另外建一个模块,这个模块通过依赖引入成为所有服务模块的依赖。
- 如下在service中有多个服务模块。在common中都是服务模块的依赖,例如工具模块等。我们可以在service-base模块中,做统一异常处理,然后将service-base作为依赖引入service的pom文件中,这样所有的服务模块都可以继承到统一异常处理。
2 创建统一异常处理器
- 创建如上图所示的模块(具体以读者的实际项目需要为准,我们之所以这样子建项目模块的原因已经在上方阐述清楚)。在service-base中创建统一异常处理类GlobalExceptionHandler.java:
/**
* 统一异常处理类
*/
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(Exception.class)
@ResponseBody
public R error(Exception e){
e.printStackTrace();
return R.error();
}
}
- 注意点如下:
- @ControllerAdvice
- @ExceptionHandler(Exception.class) 表示对何种异常进行处理 这里指所有的异常
- @ResponseBody 用来返回R对象
- 制造异常,测试返回结果如下:
四、处理特定异常
1. 在上述的GlobalExceptionHandler.java添加异常处理方法
/**
* 统一异常处理类
*/
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(Exception.class)
@ResponseBody
public R error(Exception e){
e.printStackTrace();
return R.error();
}
@ExceptionHandler(ArithmeticException.class)
@ResponseBody
public R error(ArithmeticException e){
e.printStackTrace();
return R.error().message("执行了自定义异常");
}
}
- 注意点:
- @ExceptionHandler(ArithmeticException.class) 表示指定处理ArithmeticException异常
- 在这里因为第二个方法已经指定了ArithmeticException的异常处理,因此若产生了ArithmeticException异常就会按照指定的方法处理异常,其他异常会按照第一个方法处理其他异常。也就是有指定特定异常的处理方法就按照该方法处理,否则按照第一个方法(代表处理所有异常)处理。
- 制造异常,测试返回结果如下:
五、自定义异常
1 创建自定义异常类
- 自定义异常处理与上述异常处理的区别在于需要自己写一个异常类,继承RuntimeException 。自定义异常类如下代码:
@Data
@AllArgsConstructor
@NoArgsConstructor
public class MyException extends RuntimeException {
@ApiModelProperty(value = "状态码")
private Integer code;
private String msg;
}
2. 在上述的GlobalExceptionHandler.java中添加自定义异常处理的方法
- GlobalExceptionHandler.java中添加
/**
* 统一异常处理类
*/
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(Exception.class)
@ResponseBody
public R error(Exception e){
e.printStackTrace();
return R.error();
}
@ExceptionHandler(ArithmeticException.class)
@ResponseBody
public R error(ArithmeticException e){
e.printStackTrace();
return R.error().message("执行了自定义异常");
}
@ExceptionHandler(MyException.class)
@ResponseBody
public R error(MyException e){
e.printStackTrace();
return R.error().message(e.getMsg()).code(e.getCode());
}
}
- 注意点:
- @ExceptionHandler(MyException.class) 第三个方法指定处理的是我们自定义的异常
- 处理异常是将异常的信息和异常的状态码设置给R对象中message和状态码。
3.业务中需要的位置如何抛出GuliException
try {
int a = 10/0;
}catch(Exception e) {
throw new MyException(20001,"出现自定义异常");
}
- 抛出异常的时候使用全参构造new了一个自定义异常对象,并设置了自定义异常对象的状态码和异常信息。