实现思路
- 使用@RestControllerAdvice注解,定义系统全局异常捕捉类,捕捉系统全局异常
- 继承RuntimeException类,定义业务异常类,用于业务打断
异常捕捉演示
- 下载源代码,github源码链接
- 项目启动,调用/test/exception接口
- 自定义异常
- 全局异常捕捉
关键业务代码
- 系统全局异常捕捉
/** * 系统全局异常捕捉 */ @Slf4j @RestControllerAdvice public class GlobalControllerExceptionHandler { @ExceptionHandler(ErrorCodeException.class) @ResponseBody public ResultBean handleErrorCodeException(ErrorCodeException e) { Integer code = e.getErrorCode(); String msg = e.getMessage(); // 外部传入了消息描述,这个地方就不再覆盖了 if (!StringUtils.hasLength(msg)) { msg = "服务器正忙,请稍后重试。"; } if (e instanceof BusinessException) { log.info("Business exception : msg {} : code {}", msg, code); } else { log.error("ErrorCodeException exception : msg {}", msg, e); } return ResultBean.error(code, msg); } /** * 空指针 */ @ExceptionHandler(value = NullPointerException.class) @ResponseBody public ResultBean nullPointerException(NullPointerException e) { log.error("发生空指针异常!原因是:", e); return ResultBean.error(HttpStatus.INTERNAL_SERVER_ERROR.value(), e.toString()); } /** * 类型强制转换异常 */ @ExceptionHandler(value = ClassCastException.class) @ResponseBody public ResultBean classCastException(ClassCastException e) { log.error("类型强制转换异常!原因是:", e); return ResultBean.error(HttpStatus.INTERNAL_SERVER_ERROR.value(), e.toString()); } /** * 数组下标越界异常 */ @ExceptionHandler(value = ArrayIndexOutOfBoundsException.class) @ResponseBody public ResultBean arrayIndexOutOfBoundsException(ArrayIndexOutOfBoundsException e) { log.error("数组下标越界异常!原因是:", e); return ResultBean.error(HttpStatus.INTERNAL_SERVER_ERROR.value(), e.toString()); } /** * 字符串转换为数字异常 */ @ExceptionHandler(value = NumberFormatException.class) @ResponseBody public ResultBean numberFormatException(NumberFormatException e) { log.error("字符串转换为数字异常!原因是:", e); return ResultBean.error(HttpStatus.INTERNAL_SERVER_ERROR.value(), e.toString()); } /** * 输入输出异常 */ @ExceptionHandler(value = IOException.class) @ResponseBody public ResultBean IOException(IOException e) { log.error("输入输出异常!原因是:", e); return ResultBean.error(HttpStatus.INTERNAL_SERVER_ERROR.value(), e.toString()); } /** * 方法未找到异常 */ @ExceptionHandler(value = NoSuchMethodException.class) @ResponseBody public ResultBean noSuchMethodException(NoSuchMethodException e) { log.error("方法未找到异常!原因是:", e); return ResultBean.error(HttpStatus.INTERNAL_SERVER_ERROR.value(), e.toString()); } /** * 系统异常 */ @ExceptionHandler(value = SystemException.class) @ResponseBody public ResultBean systemException(SystemException e) { log.error("系统异常!原因是:", e); return ResultBean.error(HttpStatus.INTERNAL_SERVER_ERROR.value(), e.toString()); } /** * 非法参数异常 */ @ExceptionHandler(value = IllegalArgumentException.class) @ResponseBody public ResultBean IllegalArgumentException(IllegalArgumentException e) { log.error("非法参数异常!原因是:", e); return ResultBean.error(HttpStatus.BAD_REQUEST.value(), e.toString()); } /** * 不支持的操作异常 */ @ExceptionHandler(value = UnsupportedOperationException.class) @ResponseBody public ResultBean unsupportedOperationException(UnsupportedOperationException e) { log.error("不支持的操作异常!原因是:", e); return ResultBean.error(HttpStatus.BAD_REQUEST.value(), e.toString()); } /** * 操作数据库异常 */ @ExceptionHandler(value = SQLException.class) @ResponseBody public ResultBean sqlException(SQLException e) { log.error("操作数据库异常!原因是:", e); return ResultBean.error(HttpStatus.INTERNAL_SERVER_ERROR.value(), e.toString()); } /** * 参数校验失败 */ @ExceptionHandler(BindException.class) @ResponseBody public ResultBean handlerConstraintViolationException(BindException e) { log.warn(e.getMessage(), e); if (!e.getAllErrors().isEmpty()) { String msg = e.getAllErrors().get(0).getDefaultMessage(); return ResultBean.error(HttpStatus.BAD_REQUEST.value(), msg); } else { return ResultBean.error(HttpStatus.BAD_REQUEST.value(), e.toString()); } } /** * 方法参数无效异常 */ @ExceptionHandler(MethodArgumentNotValidException.class) @ResponseBody public ResultBean handlerArgumentNotValidException(MethodArgumentNotValidException e) { log.warn(e.getMessage(), e); if (!e.getBindingResult().getAllErrors().isEmpty()) { String msg = e.getBindingResult().getAllErrors().get(0).getDefaultMessage(); return ResultBean.error(HttpStatus.BAD_REQUEST.value(), msg); } else { return ResultBean.error(HttpStatus.BAD_REQUEST.value(), e.toString()); } } /** * Internal Server Error 500 */ @ExceptionHandler(Exception.class) @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) @ResponseBody public ResultBean handlerException(Exception e) { log.error(e.getMessage(), e); return ResultBean.error(HttpStatus.INTERNAL_SERVER_ERROR.value(), e.toString()); } /** * 404异常 */ @ExceptionHandler(NoHandlerFoundException.class) @ResponseStatus(HttpStatus.NOT_FOUND) @ResponseBody public ResultBean noHandlerFoundException(NoHandlerFoundException e) { return ResultBean.error(HttpStatus.NOT_FOUND.value(), e.toString()); } }
本文定义了常见的全局异常,有兴趣的小伙伴,可以根据业务增加其他的异常。
- 业务异常类,用于业务打断
/** * 业务异常类,只用于业务打断 */ public class BusinessException extends ErrorCodeException { private static final long serialVersionUID = -45155154531465551L; public BusinessException(Integer businessErrorCode) { super(businessErrorCode); } public BusinessException(Integer businessErrorCode, String message, Throwable cause) { super(businessErrorCode, message, cause); } public BusinessException(Integer businessErrorCode, String message) { super(businessErrorCode, message); } public BusinessException(Integer businessErrorCode, Throwable cause) { super(businessErrorCode, cause); } public BusinessException(Integer businessErrorCode, String message, Object result) { super(businessErrorCode, message, result); } public BusinessException(ResultCode resultCode) { this(resultCode.getCode(), resultCode.getMsg()); } public BusinessException(ResultCode resultCode, Throwable cause) { this(resultCode.getCode(), resultCode.getMsg(), cause); } public static void throwException(ResultCode resultCode) { throw new BusinessException(resultCode); } public static void throwException(ResultCode resultCode,Throwable cause) { throw new BusinessException(resultCode, cause); } @Override public String getMessage() { return super.getMessage(); } } /** * 含错误码的异常类 */ public class ErrorCodeException extends RuntimeException { private static final long serialVersionUID = -21116129021561225L; // 错误码 private Integer errorCode; // 异常结果返回 private Object result; public ErrorCodeException(Integer errorCode) { this(errorCode, null, null); } public ErrorCodeException(Integer errorCode, String message) { this(errorCode, message, null); } public ErrorCodeException(Integer errorCode, Throwable cause) { this(errorCode, null, cause); } public ErrorCodeException(Integer errorCode, String message, Throwable cause) { super(message, cause); this.errorCode = errorCode; } public ErrorCodeException(Integer errorCode, String message,Object result) { super(message); this.errorCode = errorCode; this.result = result; } public Integer getErrorCode() { return errorCode; } @Override public String getMessage() { return super.getMessage(); } public Object getResult(){ return this.result; } }
- 异常捕捉测试类
@Service public class TestServiceImpl implements TestService { @Override public ResultBean test(int type) { if (1 == type) { throw new BusinessException(ResultCode.INTERNAL_SERVER_ERROR); } else if (2 == type) { int a = 1 / 0; } else if (3 == type) { Integer[] arr = {1, 2}; int a = arr[2]; } else if (4 == type) { List<Integer> list = new ArrayList<>(); list.add(1); int a = list.get(2); } else if (5 == type) { String a = "12.5662"; Integer b = Integer.parseInt(a); } else if (6 == type) { Map<String, Object> map = null; map.size(); } else if (7 == type) { String a = "hello world"; Map map = JSON.parseObject(a, Map.class); } else if (8 == type) { List<String> list = null; list.contains("a"); } else if (9 == type) { Integer[] arr = new Integer[1]; arr[0] = 1; arr[1] = 2; } else { int a = 1 + 1; } return ResultBean.success(); } }