如何使用SpringBoot处理全局异常

如何使用SpringBoot处理全局异常

使用@ControllerAdvice 和 @ExceptionHandler处理全局异常

参考:

@ControllerAdvice
@ResponseBody
@Slf4j
public class ExceptionHandler {


    @ResponseStatus(HttpStatus.OK)
    @org.springframework.web.bind.annotation.ExceptionHandler(value = {MissingServletRequestParameterException.class})
    public ViewResult<Object> missingServletRequestParameterException(MissingServletRequestParameterException e) {
        return ViewResult.state(RpcCode.OPERATION_NOT_PERMITTED_CODE, e.getMessage(), null);
    }

    @ResponseStatus(HttpStatus.OK)
    @org.springframework.web.bind.annotation.ExceptionHandler(value = {Exception.class})
    public ViewResult<Object> allException(Exception e) {
        ViewResult<Object> result = buildCustomException(e);
        if (result == null && e.getCause() != null) {
            result = buildCustomException(e.getCause() );
        }
        if (result != null) {
            return result;
        }
        // 请求传参等spring抛出的异常消息显示出来用于调试
        if (e instanceof ServletException || e instanceof NestedRuntimeException) {
            log.warn("", e);
            return ViewResult.state(RpcCode.SYSTEM_DEFAULT_ERROR_CODE, "请求错误:" + e.getMessage(), null);
        }
        log.error("system error:", e);
        return ViewResult.state(RpcCode.SYSTEM_DEFAULT_ERROR, null);
    }

    /**
     * 自定义异常的统一处理,各异常的message需要是汉字形式的提示文本。
     * @param e
     * @return
     */
    private ViewResult<Object> buildCustomException(Throwable e) {
        int code = RpcCode.SYSTEM_DEFAULT_ERROR_CODE;
        if (e instanceof NoAuthException) {
            code = RpcCode.OPERATION_NOT_PERMITTED_CODE;
        } else if (e instanceof com.chj.thor.auth.v2.exception.NoAuthException) {
            code = RpcCode.OPERATION_NOT_PERMITTED_CODE;
        } else if (e instanceof DuplicatedException) {
            code = RpcCode.RESOURCE_DUPLICATED_CODE;
        } else if (e instanceof NotFoundException) {
            code = RpcCode.RESOURCE_NOTFOUND_CODE;
        } else if (e instanceof OperationNotPermittedException) {
            code = RpcCode.OPERATION_NOT_PERMITTED_CODE;
        } else if (e instanceof ParamInvalidException) {
            code = ApiRpcCode.PARAM_INVALIDATED_CODE;
        } else if (e instanceof UrlUnreachableException) {
            code = ApiRpcCode.URL_UNREACHABLE_CODE;
        } else if (e instanceof ThirdServiceException) {
            code = ApiRpcCode.THIRD_SERVICE_CODE;
        } else if (e instanceof ThorException) {
            code = 500001;
        }
        if (code != RpcCode.SYSTEM_DEFAULT_ERROR_CODE) {
            return ViewResult.state(code, e.getMessage(), null);
        }
        return null;
    }

    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @org.springframework.web.bind.annotation.ExceptionHandler({
            MethodArgumentNotValidException.class,//requestBody校验
    })
    public ViewResult<Object> methodArgumentNotValidException(MethodArgumentNotValidException e) throws MethodArgumentNotValidException {
        log.info("[前置条件校验失败]", e);
        Class<?> clazz = e.getParameter().getExecutable().getDeclaringClass();
        //只有Controller层的参数出现问题才进行封装处理,否则直接上抛
        if (clazz.getSimpleName().endsWith("Controller")) {
            FieldError fieldError = e.getBindingResult().getFieldError();
            String message = "INVALID PARAMS";
            if (null != fieldError) {
                message += ":" + fieldError.getField();
                message += ":" + fieldError.getDefaultMessage();
            }
            return ViewResult.state(IRpcCode.ILLEGAL_ARGUMENT_CODE, message, null);
        } else {
            throw e;
        }
    }

    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @org.springframework.web.bind.annotation.ExceptionHandler({
            ConstraintViolationException.class //requestParam校验
    })
    public ViewResult<Object> constraintViolationException(ConstraintViolationException e) {
        log.info("[前置条件校验失败]", e);

        Set<ConstraintViolation<?>> validations = e.getConstraintViolations();
        StringBuilder message = new StringBuilder("INVALID PARAMS");
        //当配置的是failFast模式时,循环只会执行一遍
        for (ConstraintViolation<?> v : validations) {
            //只有Controller service层的参数出现问题才进行封装处理,否则直接上抛
            if (v.getRootBeanClass().getSimpleName().endsWith("Controller") ||
                    v.getRootBeanClass().getSimpleName().endsWith("ServiceImpl")) {
                message.append(":");
                message.append(v.getPropertyPath());
                message.append(":");
                message.append(v.getMessage());
            } else {
                throw e;
            }
        }
        return ViewResult.state(IRpcCode.ILLEGAL_ARGUMENT_CODE, message.toString(), null);
    }
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @org.springframework.web.bind.annotation.ExceptionHandler({
            HttpMessageNotReadableException.class, //requestParam校验
            HttpRequestMethodNotSupportedException.class,//method不支持
            HttpMediaTypeException.class,//ContentType问题
            ServletRequestBindingException.class//数据绑定问题
    })
    public ViewResult<Object> constraintViolationException(Exception e) {
        log.info("[客户端数据格式错误]", e);
        return ViewResult.state(IRpcCode.ILLEGAL_ARGUMENT_CODE, e.getMessage(), null);
    }



}


你可能感兴趣的:(spring,boot,java,后端,异常处理)