添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

异常处理

Java中的异常处理是开发过程中很重要的一个环节,如果异常处理不好可能会出现无法很快找到 BUG、系统中明明有问题却没有任何异常日志等问题。本文中列出一些异常处理规范,供大家参考。

异常分类

在Java中异常分为 Exception 以及 Error 两种类型,而 Exception 又可分为 Checked Exception Unchecked Exception

Error 无需处理。发生 Error 一般都是比较严重的问题,代码层次也处理不了。

Unchecked Exception

对于 Unchecked Exception 也是不处理的,即不用捕获,直接让其抛到顶层,最终交给 Spring 的 ControllerAdvice 中的 ExceptionHandler 来处理。

这类异常通常不捕获代码也是不会报错。而这类异常通常继承自 RuntimeException 。或者说只要是继承自 RuntimeException 都是 Unchecked Exception

Checked Exception

Checked Exception 是在 Java 中的一种异常类型,它是一种编译时异常(checked exception)。在 Java 中,编译时异常是指在编译阶段必须进行处理的异常,即在代码中必须显式地处理这些异常,否则编译器会报错。

Checked Exception 通常是由外部因素导致的异常,例如文件不存在、网络连接中断等,这些异常是程序无法控制的,但是程序需要在编译时就做出相应的处理以避免程序在运行时出错。

如果调用的方法中抛出了异常(Checked Exception),一般情况下需要先捕获,然后包装成自定义的业务异常(如: ServiceException )并抛出。如下:

try {
File file = new File("122");
file.createNewFile();
} catch (IOException e) {
throw new ServiceException("XXX_0001", "无法创建文件", e);
}
java
注意

在新抛出的异常中一定要包含原异常栈。而在后续的异常拦截中也需要将异常栈打印输出,否则会出现具体异常无法找到的问题。

throw new ServiceException("XXX_0001", "无法创建文件"); 这样写是不允许的。

在后续处理异常时,要打印完整的异常栈信息。

@ExceptionHandler(value = ServiceException.class)
public ResponseBean<String> serviceException(ServiceException serviceException) {
ResponseBean<String> result = new ResponseBean<>();
result.setErrorCode(serviceException.getErrorCode());
result.setMessage(serviceException.getMessage());
result.setStatus(serviceException.getStatus());
log.error(serviceException.getErrorCode() + "-" + serviceException.getMessage(), serviceException);
return result;
}
java

业务异常

在系统中一般需要定义一个通用的业务异常,通用业务异常应当定义为 Unchecked Exception,即需要继承自 RuntimeException 。一般通用业务异常中需要包含错误代码,如下:

通用业务异常定义
public class ServiceException extends RuntimeException {
/**
* 错误编码
*/
@Getter
private final String errorCode;

public ServiceException(String message) {
super(message);
this.errorCode = CommonError.SERVICE_ERROR.getErrorCode();
}

public ServiceException(String errorCode, String message) {
super(message);
this.errorCode = errorCode;
}

public ServiceException(String errorCode, String message, Throwable cause) {
super(message, cause);
this.errorCode = errorCode;
}

public ServiceException(ErrorInfo errorInfo) {
super(errorInfo.getErrorMessage());
this.errorCode = errorInfo.getErrorCode();
}

public ServiceException(ErrorInfo errorInfo, Throwable cause) {
super(errorInfo.getErrorMessage(), cause);
this.errorCode = errorInfo.getErrorCode();
}
}
java

对于系统中的业务逻辑校验,如必填字段校验不通过、数据重复提交等。则应当已抛出异常的方式来处理。如:添加权限时,首先判断权限编码是否已存在,如果存在抛出异常。

private void checkPermissionCode(String permissionCode, String excludeId) {
Integer count = this.sysPermissionMapper.countByPermissionCode(permissionCode, excludeId);
if (count != null && count > 0) {
throw new ServiceException(PermissionError.PERMISSION_CODE_EXIST);
}
}
java

除使用通用的业务异常外,也可以自定义业务异常,自定义的业务异常需要继承自 ServiceException

一些需要单独处理的 Checked Exception

下面总结了一些需要在 Spring 的 ControllerAdvice 中单独处理的 Checked Exception。

  • org.springframework.web.HttpRequestMethodNotSupportedException :请求接口的方法与接口暴露的方法不一致时,Spring 会抛出此异常。
  • org.springframework.web.bind.MethodArgumentNotValidException :参数校验不通过时抛出此异常,当使用 @NotNull @Valid 等方式进行请求参数验证时,如若验证不通过会抛出此异常,可以从此异常信息中获取具体的错误信息。
  • org.springframework.web.bind.MissingServletRequestParameterException :必填参数缺失时会抛出此异常,当 GET 请求中的参数被标记为 @RequestParam(require = true) 时,如果前端调用接口时未传此参数,会抛出此异常。
  • org.springframework.web.multipart.MaxUploadSizeExceededException :当上传的文件超过限制时抛出此异常。文件大小的限制通过 spring.servlet.multipart.max-file-size spring.servlet.multipart.max-request-size 配置。
  • 以下是 ExceptionHandler 的配置参考。