• 如何使用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);
        }
    
    
    
    }
    
    
    
    • 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
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
  • 相关阅读:
    MySQL视图&导入导出&索引&执行计划
    redis的使用场景
    UOS QTextEdit设置换行和滚动条(bug自动换行时右侧个别字符被遮盖)
    冰冰学习笔记:反向迭代器的模拟
    GIT 首次提交
    机器学习模型2——决策树
    HTML5期末大作业:旅游网页设计与实现——旅游风景区网站HTML+CSS (1)
    Java流(Stream)式编程
    libigl 网格等值线
    【Linux学习笔记】基础命令2
  • 原文地址:https://blog.csdn.net/Kingsea442/article/details/134076763