Spring Boot异常处理方案选择

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 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异常处理方案选择)