Spring Boot集成Security以及OAuth2后如何進(jìn)行異常處理
時間:2018-07-17 17:00
開發(fā)者:那年初二
全局異常處理
如果對Spring Boot比較熟悉的話逮栅,基本上都會想到使用@ControllerAdvice
、@RestControllerAdvice
富玷、@ExceptionHandler
注解來進(jìn)行全局異常處理排惨。
具體流程
-
1八千、注解解析
- @ControllerAdvice 捕獲 Controller 層拋出的異常,如果添加 @ResponseBody 返回信息則為JSON 格式锡宋。
- @RestControllerAdvice 相當(dāng)于 @ControllerAdvice 與 @ResponseBody 的結(jié)合體瘫证。
- @ExceptionHandler 統(tǒng)一處理一種類的異常,減少代碼重復(fù)率舆逃,降低復(fù)雜度蚂维。
2、創(chuàng)建異常處理類
創(chuàng)建一個 GlobalExceptionHandler 類路狮,并添加上 @RestControllerAdvice
注解就可以定義出異常通知類了鸟雏,然后在定義的方法中添加上 @ExceptionHandler
即可實(shí)現(xiàn)異常的捕捉......
/**
* 全局異常處理
*
* @author chentai
* @date 2018/7/17 0001
*/
@RestControllerAdvice
public class GlobalExceptionHandler extends ResponseEntityExceptionHandler {
/**
* 定義要捕獲的異常 可以多個 @ExceptionHandler({})
*
* @param request request
* @param e exception
* @param response response
* @return 響應(yīng)結(jié)果
*/
@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 響應(yīng)結(jié)果
*/
@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("參數(shù)轉(zhuǎn)換失敗,方法:" + exception.getParameter().getMethod().getName() + "览祖,參數(shù):" + exception.getName()
+ ",信息:" + exception.getLocalizedMessage());
return new ResponseEntity<>(new ErrorResponseEntity(status.value(), "參數(shù)轉(zhuǎn)換失敗"), status);
}
return new ResponseEntity<>(new ErrorResponseEntity(status.value(), "參數(shù)轉(zhuǎn)換失敗"), status);
}
}
- 3孝鹊、運(yùn)行項(xiàng)目,能夠正常進(jìn)行全局異常處理展蒂。到此為止又活,如果你的項(xiàng)目集成Security以及OAuth2只是單純使用密碼模式進(jìn)行授權(quán)認(rèn)證的話,這樣的處理方式完美符合項(xiàng)目需求锰悼。但是柳骄,如果項(xiàng)目需要使用OAuth2的授權(quán)碼模式,這樣的方式在進(jìn)行授權(quán)碼獲取的時候會拋出
User must be authenticated with Spring Security before authorization can be completed
異常箕般,即在完成授權(quán)之前耐薯,用戶必須通過Spring Security進(jìn)行身份驗(yàn)證
。那么丝里,這時候曲初,我們應(yīng)該怎么去處理呢?其實(shí)杯聚,很簡單臼婆,既然有全局異常處理,那么就有單一異常處理幌绍。下面介紹單一異常處理颁褂。
單一異常處理
只需要在項(xiàng)目Controller類里面使用@ExceptionHandler
注解增加對應(yīng)的異常處理方法,即可捕獲該類拋出的異常并進(jìn)行處理傀广。
如颁独,項(xiàng)目中對請求參數(shù)進(jìn)行了校驗(yàn)處理,則可以在Controller類中增加如下方法:
/**
* @param exception
* @return TODO: 2018/07/17 參數(shù)未通過驗(yàn)證異常
*/
@ExceptionHandler(value = MethodArgumentNotValidException.class)
public ErrorResponse MethodArgumentNotValidHandler(MethodArgumentNotValidException exception) {
// 解析原錯誤信息伪冰,封裝后返回誓酒,此處返回非法的字段名稱,原始值糜值,錯誤信息
return new ErrorResponse(ResponseCode.PARAM_ERROR_CODE.getCode(),
exception.getBindingResult().getAllErrors().get(0).getDefaultMessage());
}
如此丰捷,當(dāng)Http請求傳入的參數(shù)出錯時坯墨,此方法會進(jìn)行相應(yīng)的處理寂汇。