SpringBoot接口 - 统一异常处理

为什么要统一异常处理

如果不统一处理异常,程序开发时就需要在controller层写大量重复的Valid代码, 比如下面这个样子:

@Slf4j
@RestController
public class Controller {

    /**
     *
     * @param ListReq
     * @return
     * @throws Exception
     */
    @RequestMapping("/list")
    public ResponseMessage getList(@Valid @RequestBody ListReq listReq, BindingResult bindingResult) throws Exception {
        log.info("start /list,请求参数:{}", JSONObject.toJSONString(listReq));
        //参数校验
        if (bindingResult.hasErrors()) {
            bindingResult.getAllErrors().forEach(objectError -> log.warn("[{}]绑定校验错误[{}]", objectError.getCodes()[0], objectError.getDefaultMessage()));
            return ResponseUtil.setFailedResponse(ResponseStatus.PARAM_FAILED);
        }
 	// 参数预处理
        try {
            // do something
        } catch(Exception e) {
            return ResponseUtil.setFailedResponse(ResponseStatus.PARAM_FAILED);
        }
        return ResponseUtil.setSuccessResponse(ResponseStatus.SUCCESS);
    }

如上所示,每个接口都会进行重复的参数校验、预处理,最终项目中充斥大量的重复代码,臃肿;那么接下来我们学习使用java提供的@ControllerAdvice统一异常处理简化我们的代码。

@ControllerAdvice异常统一处理

先看代码实现:

异常处理

/**
 * 统一处理异常信息
 */
@Slf4j
@RestControllerAdvice
public class ExceptionAdvice {
     /**
     * 捕获接口请求参数校验异常
     */
    @ResponseBody
    @ExceptionHandler(value = {BindException.class, ValidationException.class,
            MethodArgumentNotValidException.class, MissingServletRequestParameterException.class})
    public ResponseMessage handleParameterVerificationException(@NonNull Exception e) {
        if (e instanceof MethodArgumentNotValidException) {
            //MethodArgumentNotValidException异常:@RequestBody上validate失败后抛出的异常,json格式有效
            BindingResult bindingResult = ((MethodArgumentNotValidException) e).getBindingResult();
            bindingResult.getAllErrors().forEach(
                    objectError -> log.warn("[{}]绑定校验错误[{}]", objectError.getCodes()[0], objectError.getDefaultMessage()));
        } else if (e instanceof BindException) {
            //BindException异常:@RequestBody上validate失败后抛出的异常,表单提交有效
            BindingResult bindingResult = ((BindException) e).getBindingResult();
            bindingResult.getAllErrors().forEach(
                    objectError -> log.warn("[{}]绑定校验错误[{}]", objectError.getCodes()[0], objectError.getDefaultMessage()));
        } else {
            //@RequestParam上validate失败后抛出的异常是javax.validation.ConstraintViolationException异常
            //@RequestParam上参数缺失抛出MissingServletRequestParameterException异常
            log.warn("绑定校验错误[{}] ", e.getMessage());
        }
        return ResponseUtil.setFailedResponse(ResponseStatus.PARAM_FAILED);
    }
	
    /**
     * 捕获其他Exception
     */
    @ResponseBody
    @ExceptionHandler({Exception.class})
    public ResponseMessage customExceptionHandler(Exception e) {
        log.error(e.getMessage());
        return ResponseUtil.setFailedResponse(ResponseStatus.FAILED);
    }
}

接口层(无需特殊处理)

@Slf4j
@Validated
@RestController
public class Controller {

    /**
     * @param listReq
     * @return
     * @throws Exception
     */
    @RequestMapping("/list")
    public ResponseMessage getList(@Valid @RequestBody ListReq listReq) throws Exception {
        log.info("start /list,请求参数:{}", JSONObject.toJSONString(listReq));
        return confMgmtService.getConfList(confListReq);
    }

以上就是统一处理的简单实现~ 快GET起来吧

posted @ 2022-06-10 10:35  super_龙  阅读(192)  评论(0编辑  收藏  举报