开发笔记-04-统一异常处理

开发笔记-03-SpringBoot统一异常处理

前言

  • 在做前后端分离的项目时,后端通常都会拆分成多个独立的微服务,这时候就会涉及每个服务返回给前端的数据格式问题了。

  • 下面就来实现一个比较常用的数据格式,统一所有服务的返回值格式。

  • 一般返回的数据格式会包括4个部分

    • 第一部分:请求处理是否成功
    • 第二部分:服务处理结果编码
    • 第三部分:编码对应的文本信息
    • 第四部分:返回值
1
2
3
4
5
6
7
8
9
10
{
"result": true,
"code": 1000,
"message": "SUCCESS",
"data": {
"lantian": 17,
"qingfen": 16,
"baiyun": 18
}
}
  • 对于异常处理情况,我们也需要统一成上面的格式:
    • 如果在controller中通过try catch来处理异常的话,会出现一个问题就是每个函数里都加一个Try catch,代码会变的很乱。
      • 这个全局异常拦截器的目的是要把异常转化为通用的json结构,给到前端,前端根据不同的状态码。做出不同的业务逻辑
      • 举例子,后端给前端未登录,前端跳登录页面
      • 后端给前端服务器异常,接口超时,前端重新调用,或者弹出提示给用户
      • 测试就是手动抛出这样一个异常,然后能看到对应的一个异常展示
    • 下面我们就通过spring boot的注解来省略掉controller中的try-catch帮助我们来封装异常信息并返回给前端,这样用户也不会得到一些奇奇怪怪的错误提示。

1. 实战练习

1.1 定义返回值结构信息(get,set省略)

1
2
3
4
5
6
public class CallResultMsg<T> {
private boolean result;
private int code;
private String message;
private T data;
}

1.2 定义返回值和对应的code信息(get,set省略)

1
2
3
4
5
6
7
8
9
10
11
12
13
public enum CodeAndMsg {
SUCCESS(1000, "SUCCESS"),
METHODFAIL(2000, "ENCOUNTER AN ERROR WHEN EXECUTE METHOD"),
UNKNOWEXCEPTION(3000, "THIS IS AN UNKNOW EXCEPTION");

private int code;
private String msg;

CodeAndMsg(int code, String msg){
this.code = code;
this.msg = msg;
}
}

1.3 自定义异常

  • 对于一些特别的异常,可以自定义ExceptionError Code,这里自定义一个异常(需要继承RuntimeException
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class UserDefinedException extends RuntimeException {
private CodeAndMsg exception;

public UserDefinedException(CodeAndMsg exception){
this.exception = exception;
}

public CodeAndMsg getException() {
return exception;
}

public void setException(CodeAndMsg exception) {
this.exception = exception;
}
}

1.4 @RestControllerAdvice 捕获全局异常

  • @RestControllerAdvice都是对Controller进行增强的,可以全局捕获spring mvc抛的异常。
  • @ExceptionHandler(value = Exception.class)
    • ExceptionHandler的作用是用来捕获指定的异常。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
@RestControllerAdvice(annotations = RestController.class)
public class UniformReponseHandler<T> {

@ResponseStatus(HttpStatus.OK)
public CallResultMsg sendSuccessResponse(){
return new CallResultMsg(true, CodeAndMsg.SUCCESS, null);
}

@ResponseStatus(HttpStatus.OK)
public CallResultMsg sendSuccessResponse(T data) {
return new CallResultMsg(true, CodeAndMsg.SUCCESS, data);
}

@ExceptionHandler(UserDefinedException.class)
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
public CallResultMsg sendErrorResponse_UserDefined(Exception exception){
return new CallResultMsg(false, ((UserDefinedException)exception).getException(), null);
}

@ExceptionHandler(Exception.class)
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
public CallResultMsg sendErrorResponse_System(Exception exception){
if (exception instanceof UserDefinedException) {
return this.sendErrorResponse_UserDefined(exception);
}

return new CallResultMsg(false, CodeAndMsg.UNKNOWEXCEPTION, null);
}
}
  • 通过上面的一波操作,我们的controller中就不需要再去写大量的try-catch
  • RestControllerAdvice会自动帮助catch,并匹配相应的ExceptionHandler,然后重新封装异常信息,返回值,统一格式返回给前端。
  • 当然也可以写成一个jar包,供其他微服务使用

1.5 ControllerAdvice 和 RestControllerAdvice的区别

  • @ControllerAdvice@RestControllerAdvice都是对Controller进行增强的,可以全局捕获spring mvc抛的异常。
  • RestControllerAdvice = ControllerAdvice + ResponseBody

1.6 测试统一异常捕获功能

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@GetMapping("/doTestObject")
public CallResultMsg testObjectReturn(){
Map<String, Integer> map = new HashMap();
map.put("qingfen", 16);
map.put("lantian", 17);
map.put("baiyun", 18);
return new UniformReponseHandler<Map>().sendSuccessResponse(map);
}


@GetMapping("/doTestException/{x}")
public int testExceptionResturn(@PathVariable int x){
if (0 < x && x < 10){
throw new UserDefinedException(CodeAndMsg.METHODFAIL);
} else {
return 1/0;
}
}

返回结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
{
"result": true,
"code": 1000,
"message": "SUCCESS",
"data": {
"lantian": 17,
"qingfen": 16,
"baiyun": 18
}
}
{
"result": false,
"code": 2000,
"message": "ENCOUNTER AN ERROR WHEN EXECUTE METHOD ",
"data": null
}
打赏
  • 版权声明: 本博客所有文章除特别声明外,均采用 Apache License 2.0 许可协议。转载请注明出处!
  • © 2019-2022 Zhuuu
  • PV: UV:

请我喝杯咖啡吧~

支付宝
微信