最近在看新项目代码里面,出现大量的 try…catch,然后 return 返回结果的冗余代码,想着可不可以通过构造一个全局的异常捕获器对捕获到的异常进行处理。

定义

实体类

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/**
 * @author fangyaxing
 * @date 2023/3/24
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
    /**
     *  主键 id
     */
    private Long id;

    /**
     * 姓名
     */
    private String name;

    /**
     * 年龄
     */
    private Integer age;
}

返回结果

 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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
/**
 * @author fangyaxing
 * @date 2023/3/24
 */
@Data
@AllArgsConstructor
public class ResultVO<T> {
    private String code;

    private String msg;

    private T data;

    public ResultVO(ErrorEnum errorEnum, T data) {
        this.code = errorEnum.getCode();
        this.msg = errorEnum.getMessage();
        this.data = data;
    }

    public static <T> ResultVO<T> success(T data) {
        return new ResultVO<>(ErrorEnum.SUCCESS, data);
    }

    public static <T> ResultVO<T> error(String code, String msg, T data) {
        return new ResultVO<>(code, msg, data);
    }

    public static <T> ResultVO<T> error(String code, String msg) {
        return error(code, msg, null);
    }

    public static <T> ResultVO<T> error(ErrorEnum errorEnum, T data) {
        return new ResultVO<>(errorEnum.getCode(), errorEnum.getMessage(), data);
    }

    public static <T> ResultVO<T> error(ErrorEnum errorEnum) {
        return error(errorEnum, null);
    }

    public static <T> ResultVO<T> error(BizException bizException) {
        return error(bizException.getCode(), bizException.getMessage(), null);
    }

    public static <T> ResultVO<T> error(SysException sysException) {
        return error(sysException.getCode(), sysException.getMessage(), null);
    }
}

业务层

 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
30
31
32
33
34
35
36
37
38
39
40
/**
 * @author fangyaxing
 * @date 2023/3/28
 */
@Slf4j
@Service
public class UserServiceImpl implements UserService {
    @Override
    public void insert(User user) {
        log.info("开始新增……");
        if (user.getName() == null) {
            throw new BizException("-1", "用户姓名不能为空,新增失败!");
        }
        log.info("结束新增……");
    }

    @Override
    public void delete(User user) {
        log.info("开始删除……");
        if (user.getName() == null) {
            throw new SysException("-1", "用户姓名不能为空,删除失败!");
        }
        log.info("结束删除……");
    }

    @Override
    public void update(User user) {
        log.info("开始更新……");
        String str = null;
        str.equals("111");
        log.info("结束更新……");
    }

    @Override
    public void select() {
        log.info("开始查询……");
        Integer.parseInt("abc123");
        log.info("结束查询……");
    }
}

控制层

 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
30
31
32
/**
 * @author fangyaxing
 * @date 2023/3/24
 */
@Slf4j
@RestController
@RequestMapping(value = "/user")
public class UserController {

    @Autowired
    private UserService userService;

    @PutMapping
    public void insert(@RequestBody User user) {
        userService.insert(user);
    }

    @DeleteMapping
    public void delete(@RequestBody User user) {
        userService.delete(user);
    }

    @PostMapping
    public void update(@RequestBody User user) {
        userService.update(user);
    }

    @GetMapping
    public void select() {
        userService.select();
    }
}

错误枚举

 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
30
31
32
33
34
35
/**
 * @author fangyaxing
 * @date 2023/3/24
 */
@Getter
@AllArgsConstructor
public enum ErrorEnum {
    /**
     * 操作成功
     */
    SUCCESS("A000", "操作成功"),
    /**
     * 业务异常
     */
    BIZ_ERROR("B000", "业务异常"),
    /**
     * 系统异常
     */
    SYSTEM_ERROR("C000", "系统异常"),
    /**
     * 系统异常
     */
    UNKNOWN_ERROR("D000", "其他异常"),
    ;

    /**
     * 错误码
     */
    private String code;

    /**
     * 错误信息
     */
    private String message;
}

自定义异常

 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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
/**
 * @author fangyaxing
 * @date 2023/3/24
 */
public class BizException extends RuntimeException {
    /**
     * 错误码
     */
    private String code;

    /**
     * 构造一个没有错误信息的 <code>BizException</code>
     */
    public BizException() {
        super();
    }

    /**
     * 使用指定的 Throwable 和 Throwable.toString() 作为异常信息来构造 BizException
     *
     * @param cause 错误原因, 通过 Throwable.getCause() 方法可以获取传入的 cause信息
     */
    public BizException(Throwable cause) {
        super(cause);
    }

    /**
     * 使用错误信息 message 构造 BizException
     *
     * @param message 错误信息
     */
    public BizException(String message) {
        super(message);
    }

    /**
     * 使用错误码和错误信息构造 BizException
     *
     * @param code    错误码
     * @param message 错误信息
     */
    public BizException(String code, String message) {
        super(message);
        this.code = code;
    }

    /**
     * 使用错误信息和 Throwable 构造 BizException
     *
     * @param message 错误信息
     * @param cause   错误原因
     */
    public BizException(String message, Throwable cause) {
        super(message, cause);
    }

    /**
     * @param code    错误码
     * @param message 错误信息
     * @param cause   错误原因
     */
    public BizException(String code, String message, Throwable cause) {
        super(message, cause);
        this.code = code;
    }

    /**
     * @param errorEnum ErrorEnum
     */
    public BizException(ErrorEnum errorEnum) {
        super(errorEnum.getMessage());
        this.code = errorEnum.getCode();
    }

    /**
     * @param errorEnum ErrorEnum
     * @param cause     错误原因
     */
    public BizException(ErrorEnum errorEnum, Throwable cause) {
        super(errorEnum.getMessage(), cause);
        this.code = errorEnum.getCode();
    }

    /**
     * 获取错误码
     *
     * @return 错误码
     */
    public String getCode() {
        return code;
    }
}

类似,再定义一个 SysException.java。

全局异常捕获

 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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
/**
 * @author fangyaxing
 * @date 2023/3/24
 */
@Slf4j
@RestControllerAdvice("com.yaxing.controller")
public class GlobalExceptionHandler {
    /**
     * 处理自定义的业务异常
     *
     * @param httpServletRequest 请求
     * @param e 异常
     * @return ResultVO
     */
    @ExceptionHandler(value = BizException.class)
    public ResultVO bizExceptionHandler(HttpServletRequest httpServletRequest, BizException e) {
        log.error("业务异常!", e);
        return ResultVO.error(ErrorEnum.BIZ_ERROR);
    }

    /**
     * 处理系统异常
     *
     * @param httpServletRequest 请求
     * @param e 异常
     * @return ResultVO
     */
    @ExceptionHandler(value = SysException.class)
    public ResultVO exceptionHandler(HttpServletRequest httpServletRequest, SysException e) {
        log.error("系统异常!", e);
        return ResultVO.error(ErrorEnum.SYSTEM_ERROR);
    }

    /**
     * 处理其他异常
     *
     * @param httpServletRequest 请求
     * @param e 异常
     * @return ResultVO
     */
    @ExceptionHandler(value = Exception.class)
    public ResultVO exceptionHandler(HttpServletRequest httpServletRequest, Exception e) {
        log.error("其他异常!", e);
        return ResultVO.error(ErrorEnum.UNKNOWN_ERROR);
    }
}

测试

增加

代码

1
2
3
4
5
6
7
8
// UserServiceImpl.java
public void insert(User user) {
  	log.info("开始新增……");
    if (user.getName() == null) {
      throw new BizException("-1", "用户姓名不能为空,新增失败!");
    }
    log.info("结束新增……");
 }

日志

1
2
3
4
com.yaxing.service.UserServiceImpl       : 开始新增……
c.yaxing.handler.GlobalExceptionHandler  : 业务异常

com.yaxing.exception.BizException: 用户姓名不能为空新增失败

返回结果

1
2
3
4
5
{
    "code": "B000",
    "msg": "业务异常",
    "data": null
}

删除

代码

1
2
3
4
5
6
7
public void delete(User user) {
    log.info("开始删除……");
    if (user.getName() == null) {
      throw new SysException("-1", "用户姓名不能为空,删除失败!");
    }
    log.info("结束删除……");
}

日志

1
2
3
4
5
com.yaxing.service.UserServiceImpl       : 开始删除……
c.yaxing.handler.GlobalExceptionHandler  : 系统异常

com.yaxing.exception.SysException: 用户姓名不能为空删除失败
	at com.yaxing.service.UserServiceImpl.delete(UserServiceImpl.java:29) ~[classes/:na]

返回结果

1
2
3
4
5
{
    "code": "C000",
    "msg": "系统异常",
    "data": null
}

修改

代码

1
2
3
4
5
6
public void update(User user) {
    log.info("开始更新……");
    String str = null;
    str.equals("111");
    log.info("结束更新……");
}

日志

1
2
3
4
5
com.yaxing.service.UserServiceImpl       : 开始更新……
c.yaxing.handler.GlobalExceptionHandler  : 其他异常

java.lang.NullPointerException: null
	at com.yaxing.service.UserServiceImpl.update(UserServiceImpl.java:38) ~[classes/:na]

返回结果

1
2
3
4
5
{
    "code": "D000",
    "msg": "其他异常",
    "data": null
}

查询

代码

1
2
3
4
5
public void select() {
    log.info("开始查询……");
    Integer.parseInt("abc123");
    log.info("结束查询……");
}

日志

1
2
3
4
com.yaxing.service.UserServiceImpl       : 开始查询……
c.yaxing.handler.GlobalExceptionHandler  : 其他异常

java.lang.NumberFormatException: For input string: "abc123"

返回结果

1
2
3
4
5
{
    "code": "D000",
    "msg": "其他异常",
    "data": null
}