全局統一異常處理無法攔截filter中catch的異常

一、背景

系統定義了全局統一異常處理,使用了@RestControllerAdvice註解的方式。

@Slf4j
@RestControllerAdvice
@SuppressWarnings("unchecked")
public class GlobalExceptionHandlerAdvice {

    @ExceptionHandler({MethodArgumentNotValidException.class, BindException.class})
    public BaseResponse handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {
        log.error("MethodArgumentNotValidException:" + e.getMessage());
        FieldError fe = (FieldError) e.getBindingResult().getAllErrors().get(0);
        String message = String.format("%s %s", fe.getField(), StringUtils.isNotBlank(fe.getDefaultMessage()) ? fe.getDefaultMessage() : e.getMessage());
        return BaseResponse.with(Code.PARAM_ERROR.getCode(), message);
    }
 @ExceptionHandler(JwtException.class)
    public BaseResponse handleJwtException(JwtException e) {
        log.error(e.getMessage(), e);
        return BaseResponse.with(Code.UN_AUTHORIZATION);
    }

    @ExceptionHandler(Exception.class)
    public ResponseEntity handleException(Exception e) {
        log.error(e.getMessage(), e);
        return new ResponseEntity(BaseResponse.with(Code.SYSTEM_ERROR.getCode(), Code.SYSTEM_ERROR.getMsg()
                + " " + e.getClass().getName() + ":" + e.getMessage(), null), HttpStatus.INTERNAL_SERVER_ERROR);
    }
}

鑑權使用的是JWT,使用filter對token進行解析和驗證。然後突然發現一個問題,就是當token過期時,拋出的異常無法通過全局統一異常處理對外返回,而是返回500。

 

二、原因

全局統一異常處理只能處理控制器中發生的異常。要在Spring Security過濾器鏈中重用此功能,需要定義過濾器並將其掛鉤到安全配置中。過濾器需要將異常重定向到統一異常處理中。

 

三、代碼

在filter中注入HandlerExceptionResolver

 @Autowired
    @Qualifier("handlerExceptionResolver")
    private HandlerExceptionResolver resolver;

然後在catch中拋出

catch (Exception e) {
            e.printStackTrace();
            resolver.resolveException(request, response, null, e);
        }

之後在GlobalExceptionHandlerAdvice中定義需要處理的異常類型,本文中用的是JwtException

@ExceptionHandler(JwtException.class)
    public BaseResponse handleJwtException(JwtException e) {
        log.error(e.getMessage(), e);
        return BaseResponse.with(Code.UN_AUTHORIZATION);
    }

這時便可以跟在業務代碼裏面拋出的業務異常一樣處理了。

 

四、備註

參考了https://stackoverflow.com/questions/34595605/how-to-manage-exceptions-thrown-in-filters-in-spring 中的回答

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章