JAVA项目为什么使用统一异常处理?应该怎么处理异常?

为什么使用统一异常处理?

1.软件开发过程中,不可避免的是需要处理各种异常,就我自己来说,至少有一半以上的时间都是在处理各种异常情况,所以代码中就会出现大量的try {…} catch {…} finally {…} 代码块,不仅有大量的冗余代码,而且还影响代码的可读性。

2.使用统一结果处理时,有些异常我们可以提前预知并处理,但是一个运行时异常,我们不一定能预知并处理,这时可以使用统一异常处理,当异常发生时,触发该处理操作,从而保证程序的健壮性。

比较下面两张图,看看您现在编写的代码属于哪一种风格?然后哪种编码风格您更喜欢?

目前系统所做的异常处理
JAVA项目为什么使用统一异常处理?应该怎么处理异常?_第1张图片

统一异常处理之后

JAVA项目为什么使用统一异常处理?应该怎么处理异常?_第2张图片

上面的示例,还只是在Controller层,如果是在Service层,可能会有更多的try catch代码块。这将会严重影响代码的可读性、“美观性”。

所以如果是我的话,我肯定偏向于第二种,我可以把更多的精力放在业务代码的开发,同时代码也会变得更加简洁。

既然业务代码不显式地对异常进行捕获、处理,而异常肯定还是处理的,不然系统岂不是动不动就崩溃了,所以必须得有其他地方捕获并处理这些异常。
那么问题来了,如何优雅的处理各种异常?


怎么做?如何处理?代码实现?

异常分类(三大类)

  1. 统一业务异常(BusinessExceptionHandler)

JAVA项目为什么使用统一异常处理?应该怎么处理异常?_第3张图片

2.未知异常(UnExpectedExceptionHandler)

JAVA项目为什么使用统一异常处理?应该怎么处理异常?_第4张图片

3.数据合法性检查异常(ValidationExceptionHandler)

JAVA项目为什么使用统一异常处理?应该怎么处理异常?_第5张图片

当出现异常时,异常处理的结果会包装到相应的Error对象中,包括错误代码code以及错误信息描述msg;

public static class Error {
    @ApiModelProperty(value = "错误代码", name = "code", example = "TOKEN_001")
    private String code = "";
    @ApiModelProperty(value = "错误信息描述", name = "msg")
    private String msg = "";
    ......
}

最佳实践

  • 不要随意处理异常,除非你不得不这么做
private boolean authenticate(String userId, String password) {
  try {
    service.login(userId, password);
  } catch (PasswordWrongException e) {   //按需处理,按需抛出
    return false;
  }
  return true;
}
  • 参数合法性检查

参数的格式校验由BeanValidation来处理,具体校验方式参见使用BeanValidation进行参数合法检查

@NotBlank(message = "{OFC_VALID_0008}")
@ApiModelProperty(value = "用户名", required = true)
private String userName;
  • 业务规则处理,用BusinessException的子类来完成处理,由Guava的Preconditions改写而成,目前框架定义的子类包含如下:BusinessIllegalArgumentExceptionBusinessIllegalStateExceptionBusinessNullPointerException

使用方式有以下两种:

第一种:使用BusinessPreconditions来完成

// 检查参数
BusinessPreconditions.checkArgument(checkResult, ErrorCode.LOGIN_FAILED.code(),
    ErrorCode.LOGIN_FAILED.msg());

// 检查状态
BusinessPreconditions.checkState(checkResult, ErrorCode.USER_IS_LOCKED.code(),
    ErrorCode.USER_IS_LOCKED.msg());

// 检查是否为空
BusinessPreconditions.checkNotNull(checkResult, ErrorCode.PASSWORD_IS_NULL.code(),
    ErrorCode.PASSWORD_IS_NULL.msg());

第二种:自定义异常,编程显式抛出

public class PasswordWrongException extends BusinessException {

  private static final long serialVersionUID = 1L;

  public PasswordWrongException() {
    super();
  }
  public PasswordWrongException(String message, Throwable cause) {
    super(message, cause);
  }
  public PasswordWrongException(String s) {
    super(s);
  }
  public PasswordWrongException(Throwable cause) {
    super(cause);
  }
}
//程序抛出
throw new PasswordWrongException(BusinessPreconditions.format(ErrorCode.PASS_ERROR.code(),
        ErrorCode.PASS_ERROR.msg()));

你可能感兴趣的:(java,开发语言)