Spring Boot异常处理方案选择

作者: 那年初二 | 来源:发表于2018-07-17 17:01 被阅读19次

    Spring Boot集成Security以及OAuth2后如何进行异常处理

    时间:2018-07-17 17:00

    开发者:那年初二

    全局异常处理

    如果对Spring Boot比较熟悉的话,基本上都会想到使用@ControllerAdvice@RestControllerAdvice@ExceptionHandler注解来进行全局异常处理。

    具体流程

    • 1、注解解析

      • @ControllerAdvice 捕获 Controller 层抛出的异常,如果添加 @ResponseBody 返回信息则为JSON 格式。
      • @RestControllerAdvice 相当于 @ControllerAdvice 与 @ResponseBody 的结合体。
      • @ExceptionHandler 统一处理一种类的异常,减少代码重复率,降低复杂度。
    • 2、创建异常处理类

    创建一个 GlobalExceptionHandler 类,并添加上 @RestControllerAdvice 注解就可以定义出异常通知类了,然后在定义的方法中添加上 @ExceptionHandler 即可实现异常的捕捉......

    /**
     * 全局异常处理
     *
     * @author chentai
     * @date 2018/7/17 0001
     */
    @RestControllerAdvice
    public class GlobalExceptionHandler extends ResponseEntityExceptionHandler {
    
    
        /**
         * 定义要捕获的异常 可以多个 @ExceptionHandler({})
         *
         * @param request  request
         * @param e        exception
         * @param response response
         * @return 响应结果
         */
        @ExceptionHandler(CustomException.class)
        public ErrorResponseEntity customExceptionHandler(HttpServletRequest request, final Exception e, HttpServletResponse response) {
            response.setStatus(HttpStatus.BAD_REQUEST.value());
            CustomException exception = (CustomException) e;
            return new ErrorResponseEntity(exception.getCode(), exception.getMessage());
        }
    
        /**
         * 捕获  RuntimeException 异常
         * TODO  如果你觉得在一个 exceptionHandler 通过  if (e instanceof xxxException) 太麻烦
         * TODO  那么你还可以自己写多个不同的 exceptionHandler 处理不同异常
         *
         * @param request  request
         * @param e        exception
         * @param response response
         * @return 响应结果
         */
        @ExceptionHandler(RuntimeException.class)
        public ErrorResponseEntity runtimeExceptionHandler(HttpServletRequest request, final Exception e, HttpServletResponse response) {
            response.setStatus(HttpStatus.BAD_REQUEST.value());
            RuntimeException exception = (RuntimeException) e;
            return new ErrorResponseEntity(400, exception.getMessage());
        }
    
        /**
         * 通用的接口映射异常处理方
         */
        @Override
        protected ResponseEntity<Object> handleExceptionInternal(Exception ex, Object body, HttpHeaders headers,
                                                                 HttpStatus status, WebRequest request) {
            if (ex instanceof MethodArgumentNotValidException) {
                MethodArgumentNotValidException exception = (MethodArgumentNotValidException) ex;
                return new ResponseEntity<>(new ErrorResponseEntity(status.value(), exception.getBindingResult().getAllErrors().get(0).getDefaultMessage()), status);
            }
            if (ex instanceof MethodArgumentTypeMismatchException) {
                MethodArgumentTypeMismatchException exception = (MethodArgumentTypeMismatchException) ex;
                logger.error("参数转换失败,方法:" + exception.getParameter().getMethod().getName() + ",参数:" + exception.getName()
                        + ",信息:" + exception.getLocalizedMessage());
                return new ResponseEntity<>(new ErrorResponseEntity(status.value(), "参数转换失败"), status);
            }
            return new ResponseEntity<>(new ErrorResponseEntity(status.value(), "参数转换失败"), status);
        }
    }
    
    • 3、运行项目,能够正常进行全局异常处理。到此为止,如果你的项目集成Security以及OAuth2只是单纯使用密码模式进行授权认证的话,这样的处理方式完美符合项目需求。但是,如果项目需要使用OAuth2的授权码模式,这样的方式在进行授权码获取的时候会抛出User must be authenticated with Spring Security before authorization can be completed异常,即在完成授权之前,用户必须通过Spring Security进行身份验证。那么,这时候,我们应该怎么去处理呢?其实,很简单,既然有全局异常处理,那么就有单一异常处理。下面介绍单一异常处理。

    单一异常处理

    只需要在项目Controller类里面使用@ExceptionHandler 注解增加对应的异常处理方法,即可捕获该类抛出的异常并进行处理。

    如,项目中对请求参数进行了校验处理,则可以在Controller类中增加如下方法:

        /**
         * @param exception
         * @return TODO: 2018/07/17 参数未通过验证异常
         */
        @ExceptionHandler(value = MethodArgumentNotValidException.class)
        public ErrorResponse MethodArgumentNotValidHandler(MethodArgumentNotValidException exception) {
            // 解析原错误信息,封装后返回,此处返回非法的字段名称,原始值,错误信息
            return new ErrorResponse(ResponseCode.PARAM_ERROR_CODE.getCode(),
                    exception.getBindingResult().getAllErrors().get(0).getDefaultMessage());
        }
    

    如此,当Http请求传入的参数出错时,此方法会进行相应的处理。

    相关文章

      网友评论

        本文标题:Spring Boot异常处理方案选择

        本文链接:https://www.haomeiwen.com/subject/wadgpftx.html