服务端接口校验之三——校验异常捕获与处理

当参数校验通过后,可以执行后续的业务逻辑;
但如果校验未通过,应该如何处理?这就涉及到参数校验的异常捕获问题。

系统没有按照预期的执行,遇到了一些意料之中或者意料之外的问题,这就是系统运行异常。我们需要将问题捕获,记录下来当时的情况(入参、异常信息),然后抛出一个预先设计的友好的错误代码和描述,这就是异常处理。
针对异常处理,有最适合的方式就是切面编程。

我们首先定义一个切面类

@Slf4j
@Aspect
@Configuration
public class ControllerAspect {
	//定义切面范围
    private final String controller = "execution(public * com.xx.controller.*.*(..))";
    
    @Pointcut(controller)
    public void controller() {}
    
    @Around(controller)
    public ServiceResult doAround(ProceedingJoinPoint joinPoint) {
        LogUtil.setLogId();
        long startTime = System.currentTimeMillis();
        Object[] args = joinPoint.getArgs();
        ServiceResult result = null;
        BindingResult bindingResult = null;
        String methodName = joinPoint.getSignature().getName();
        String className = joinPoint.getTarget().getClass().getName();
        className = className.substring(className.lastIndexOf(".") + 1);
        log.info("<<" + className + "." + methodName + ">> --->request :{} ",args);

        try {
            for(int i=0;i<args.length;i++) {
                if(args[i] instanceof BindingResult) {
                    bindingResult = (BindingResult)args[i];
                }
            }
            if(bindingResult !=null) {
                if(bindingResult.hasErrors()) {
                    List<ObjectError> errors = bindingResult.getAllErrors();
                    if (errors.size() > 0) {
                        ObjectError error = errors.get(0);
                        String message = error.getDefaultMessage();
                        if (StringUtils.isNotBlank(message)) {
                            throw new ServiceException(ErrorCode.PARAM_ERROR,message);
                        } else {
                            throw new ValidationException();
                        }
                    }
                }
            }
            result = (ServiceResult)joinPoint.proceed();
        } catch (Throwable e) {
            return ExceptionHandler.exceptionHandler(e);
        }
        log.info("<<" + className + "." + methodName + ">> ==> exec time millis : {} ",
            System.currentTimeMillis() - startTime);
        log.info("<<" + className + "." + methodName + ">> --->response : {} ", JSON.toJSONString(result));
        LogUtil.clearLogId();
        return result;
    }
}

对于上述代码中的异常处理类,具体如下:

public class ExceptionHandler {
       
    public static ServiceResult exceptionHandler(Throwable th) {
        if(th instanceof ConstraintViolationException) {
            //参数异常
            String message = null;
            Set<ConstraintViolation<?>> set =  ((ConstraintViolationException)th).getConstraintViolations();
            for(ConstraintViolation cv:set) {
                message = cv.getMessage();
                break;
            }
            LOG.error("参数异常:{}",message);
            return ServiceResult.fail(ErrorCode.PARAM_ERROR.getCode(), message);
        }else if(th instanceof ServiceException) {
            // 业务异常
            ServiceException se = (ServiceException) th;
            LOG.error("业务异常:{}",se.getMessage());
            return ServiceResult.fail(se.getErrorCode(), se.getMessage());
        }else {
            // 其他异常
            LOG.error("其他系统异常:{}",th);
            return ServiceResult.fail(ErrorCode.SYSTEM_ERROR.getCode(), ErrorCode.SYSTEM_ERROR.getMessage());
        }
    }
}

如上所示,通过切面来捕获异常,使用ExceptionHandler 来处理异常,即可对参数校验问题,业务问题以及系统运行时异常进行统一处理。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值