导语
上一篇文章由于各种原因吧,并没有太多的说明和代码,再次跟各位读者说声抱歉。今天在补发一篇详细的说明,让大家久等了。下面我将从顶层接口一步步带大家体验一下完整的流程。
整体设计
4种异常实现
BaseException
基础异常,可通过构造函数进行扩展满足不同的需求
public class BaseException extends RuntimeException {/** * 错误编号 */ private final String code; /** * 错误编号 英文 */ private final String codeEn; /** * 关键业务单编号 */ private final String bussinessId; /** * 附加错误信息 */ private String addtionalMessage; /** * 业务异常 */ public & ErrorEnumInterface> BaseException(T errorEnum) { this(errorEnum, ""); } public & ErrorEnumInterface> BaseException(T errorEnum, String bussinessId) { this(errorEnum, bussinessId, ""); } public & ErrorEnumInterface> BaseException(T errorEnum, String bussinessId, String message) { this(errorEnum, bussinessId, message, null); } /** * 业务异常 * * @param errorEnum 业务异常枚举值 * @param bussinessId 关键业务单号 * @param cause 底层错误 * @param */ public & ErrorEnumInterface> BaseException(T errorEnum, String bussinessId, Throwable cause) { super(errorEnum.getErrorInfo().getMessage(), cause); ErrorInfo errorInfo = errorEnum.getErrorInfo(); this.code = errorInfo.getCode(); this.bussinessId = bussinessId; this.codeEn = CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, errorEnum.name()); } public & ErrorEnumInterface> BaseException(T errorEnum, String bussinessId, String message, Throwable cause) { super(String.format("%s %n %s ", errorEnum.getErrorInfo().getMessage(), message), cause); ErrorInfo errorInfo = errorEnum.getErrorInfo(); this.code = errorInfo.getCode(); this.bussinessId = bussinessId; this.codeEn = CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, errorEnum.name()); } /** * 自定义业务异常 * * @param message * @param errorCode * @param codeEn * @param bussinessId * @param cuase */ public BaseException(String message, String errorCode, String codeEn, String bussinessId, Throwable cuase) { super(message, cuase); this.code = errorCode; this.bussinessId = bussinessId; this.codeEn = codeEn; } @Override public String toString() { return MoreObjects.toStringHelper(this).add("message", this.getMessage()).add("code", this.code) .add("codeEn", this.codeEn).add("bussinessId", this.bussinessId) .add("addtionalMessage", this.addtionalMessage).toString(); }
}
ArgumentError
参数异常枚举类
public enum ArgumentError implements ErrorEnumInterface {/** * 10000 ,"参数异常" */ COMMON_ERROR(new ErrorInfo("01000", "参数异常")), NOT_NULL(new ErrorInfo("10100", "参数不能为空")), NOT_NULL_EPMTY(new ErrorInfo("10101", "参数不能为null和空值")); private ErrorInfo errorInfo; ArgumentError(ErrorInfo errorInfo) { this.errorInfo = errorInfo; } @Override public ErrorInfo getErrorInfo() { return null; }}
ArgumentException
参数错误异常类,其他异常的实现基本大同小异,可参照ArgumentException进行扩展
/*** 参数错误异常类 */public class ArgumentException extends BaseException { public & ErrorEnumInterface> ArgumentException(T errorEnum) { this(errorEnum, ""); } public & ErrorEnumInterface> ArgumentException(T errorEnum, String bussinessId) { this(errorEnum, bussinessId, null); } public & ErrorEnumInterface> ArgumentException(T errorEnum, String bussinessId, Throwable cause) { super(errorEnum, bussinessId, cause); } public ArgumentException(String message, String errorCode, String codeEn, String bussinessId, Throwable cuase) { super(message, errorCode, codeEn, bussinessId, cuase); }}
全局异常处理
异常处理
@ControllerAdvice 是Spring3.2提供的新注解,不了解的可以去网上查一下,这里就不做过多的解释了,直接上代码
/*** 通常异常处理 */@ControllerAdvice@Slf4jpublic class ControllerExceptionhandler { private static Logger logger = LoggerFactory.getLogger(ControllerExceptionhandler.class); /** * 处理参数异常 * * @param exception * @param request * @return 标准错误400 */ @ExceptionHandler(value = ArgumentException.class) public ResponseEntity handleArgumentException(ArgumentException exception, HttpServletRequest request) { return new ResponseEntity<>(new BaseExceptionBody(exception), HttpStatus.BAD_REQUEST); } /** * 处理业务异常 * * @param exception * @param request * @return标准返回值500 */ @ExceptionHandler(value = BusinessException.class) public ResponseEntity handleBusinessException(BusinessException exception, HttpServletRequest request) { return new ResponseEntity<>(new BaseExceptionBody(exception), HttpStatus.INTERNAL_SERVER_ERROR); } /** * 处理权限异常 * * @param exception * @param request * @return 标准错误401 未授权登录, 403 没有权限 */ @ExceptionHandler(value = PermissionException.class) public ResponseEntity handlePermissionException(PermissionException exception, HttpServletRequest request) { HttpStatus status = HttpStatus.SERVICE_UNAVAILABLE; String notLogin = PermissionError.NOT_LOG_IN.getErrorInfo().getCode(); String noPermission = PermissionError.NO_Permission.getErrorInfo().getCode(); if (notLogin.equals(exception.getCode())) { status = HttpStatus.UNAUTHORIZED; } else if (noPermission.equals(exception.getCode())) { status = HttpStatus.FORBIDDEN; } return new ResponseEntity<>(new BaseExceptionBody(exception), status); } /** * 处理其他异常 * * @param exception * @param request * @return标准返回值500 */ @ExceptionHandler(value = Exception.class) @ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR) public ResponseEntity handleException(Exception exception, HttpServletRequest request) { logger.error(" [com.bmsoft.framework.core] Unkown Exception", exception); CommonException e = new CommonException(CommonErrors.UNKNOW_ERROR, "", exception); return new ResponseEntity<>(new BaseExceptionBody(e), HttpStatus.INTERNAL_SERVER_ERROR); } /** * 处理其他异常 * * @param t * @param request * @return标准返回值500 */ @ExceptionHandler(value = Throwable.class) @ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR) public ResponseEntity handleException(Throwable t, HttpServletRequest request) { logger.error(" [com.bmsoft.framework.core] Unkown Exception", t); CommonException e = new CommonException(CommonErrors.UNKNOW_ERROR, "", t); return new ResponseEntity<>(new BaseExceptionBody(e), HttpStatus.INTERNAL_SERVER_ERROR); } /** * 处理fegin 以及子类异常 * * @param exception * @param request * @return 500 */ @ExceptionHandler(value = FeignException.class) public ResponseEntity handleFiegnException(FeignException exception, HttpServletRequest request) { ObjectMapper mapper = new ObjectMapper(); String content = exception.getMessage().substring(exception.getMessage().indexOf("; content:\n") + 11); BaseExceptionBody body = null; try { body = mapper.readValue(content, BaseExceptionBody.class); } catch (IOException e) { body = new BaseExceptionBody(new CommonException(CommonErrors.UNKNOW_ERROR, "", exception)); } return new ResponseEntity<>(body, HttpStatus.INTERNAL_SERVER_ERROR); }}
测试案例
总结
代码整体来说比较通俗易懂,没有什么难点,主要都集中在统一异常处理那块。中间在各类异常的处理中构造了多种情况的处理,还引入了枚举进行统一规范。
路过朋友都看到这了就给点个赞评论一下吧,谢谢啦!