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请求传入的参数出错时,此方法会进行相应的处理。