SpringBoot解决方案之 统一异常处理
SpringBoot接口如何对异常进行统一封装,并统一返回呢?
实现案例 @ControllerAdvice异常统一处理 结合 统一接口封装 的思想,在异常处理中也将统一
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 @Slf4j @Component @RestControllerAdvice public class UnifiedExceptionHandler { @ExceptionHandler(Exception.class) public R exception (Exception e) { log.error(e.getMessage(),e); return R.error(); } @ExceptionHandler(BadSqlGrammarException.class) public R badSqlGrammarException (BadSqlGrammarException e) { log.error(e.getMessage(),e); return R.setResult(ResponseEnum.BAD_SQL_GRAMMAR_ERROR); } @ExceptionHandler(BusinessException.class) public R businessException (BusinessException e) { log.error(e.getMessage(),e); return R.error().message(e.getMessage()).code(e.getCode()); } @ExceptionHandler({ NoHandlerFoundException.class, HttpRequestMethodNotSupportedException.class, HttpMediaTypeNotSupportedException.class, MissingPathVariableException.class, MissingServletRequestParameterException.class, TypeMismatchException.class, HttpMessageNotReadableException.class, HttpMessageNotWritableException.class, MethodArgumentNotValidException.class, HttpMediaTypeNotAcceptableException.class, ServletRequestBindingException.class, ConversionNotSupportedException.class, MissingServletRequestPartException.class, AsyncRequestTimeoutException.class }) public R handleServletException (Exception e) { log.error(e.getMessage(), e); return R.error().message(ResponseEnum.SERVLET_ERROR.getMessage()).code(ResponseEnum.SERVLET_ERROR.getCode()); } }
@BusinessException BusinessException 异常是我们自定义的运行时异常
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 @Data @NoArgsConstructor public class BusinessException extends RuntimeException { private Integer code; private String message; public BusinessException (String message) { this .message = message; } public BusinessException (String message, Integer code) { this .message = message; this .code = code; } public BusinessException (String message, Integer code, Throwable cause) { super (cause); this .message = message; this .code = code; } public BusinessException (ResponseEnum resultCodeEnum) { this .message = resultCodeEnum.getMessage(); this .code = resultCodeEnum.getCode(); } public BusinessException (ResponseEnum resultCodeEnum, Throwable cause) { super (cause); this .message = resultCodeEnum.getMessage(); this .code = resultCodeEnum.getCode(); } }
这里也与 前文的 统一接口封装 灵活运用,可以传入 ResponseEnum 枚举 快捷定义异常消息
除此之外,还可以仿照 spring 的 Assert 类,让我们更方便的 抛出自定义异常,并且还可以使代码看起来更整洁
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 @Slf4j public abstract class Assert { public static void notNull (Object obj, ResponseEnum responseEnum) { if (obj == null ) { log.info("obj is null..............." ); throw new BusinessException (responseEnum); } } public static void isNull (Object object, ResponseEnum responseEnum) { if (object != null ) { log.info("obj is not null......" ); throw new BusinessException (responseEnum); } } public static void isTrue (boolean expression, ResponseEnum responseEnum) { if (!expression) { log.info("fail..............." ); throw new BusinessException (responseEnum); } } public static void notEquals (Object m1, Object m2, ResponseEnum responseEnum) { if (m1.equals(m2)) { log.info("equals..............." ); throw new BusinessException (responseEnum); } } public static void equals (Object m1, Object m2, ResponseEnum responseEnum) { if (!m1.equals(m2)) { log.info("not equals..............." ); throw new BusinessException (responseEnum); } } public static void notEmpty (String s, ResponseEnum responseEnum) { if (StringUtils.isEmpty(s)) { log.info("is empty..............." ); throw new BusinessException (responseEnum); } } }
示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 @ApiOperation("会员注册") @PostMapping("/register") public R register (@RequestBody RegisterVO registerVO) { String mobile = registerVO.getMobile(); String password = registerVO.getPassword(); String code = registerVO.getCode(); Assert.notEmpty(mobile, ResponseEnum.MOBILE_NULL_ERROR); Assert.isTrue(RegexValidateUtils.checkCellphone(mobile),ResponseEnum.MOBILE_ERROR); Assert.notEmpty(password, ResponseEnum.PASSWORD_NULL_ERROR); Assert.notEmpty(code, ResponseEnum.CODE_NULL_ERROR); String codeGen = (String) redisTemplate.opsForValue().get("jkr:sms:code:" + mobile); Assert.equals(code,codeGen,ResponseEnum.CODE_ERROR); userInfoService.register(registerVO); return R.ok().message("注册成功" ); }