Springboot プロジェクトは、フィルターで例外ソリューションをキャプチャできません

Spring Security を使用してフィルターで jwt 検証を実行すると、グローバル例外はフィルターでキャッチされない例外を返します。これにより記録

理由:Spring Bootグローバル例外処理はすべてのレイヤーによってスローされた例外@RestControllerAdviceのみをキャッチするためController、フィルターでスローされた例外クラスは認識されません。
解決策: 例外をフィルターのコントローラーに転送します

フィルターに挿入しHandlerExceptionResolver resolver.resolveException()例外をコントローラーに渡します。

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

完全なフィルター コードは次のとおりです。

@Component
@Slf4j
public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {
    
    
  @Resource
  private RedisUtil redisUtil;

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

  @Override
  protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
    
    
    // 获取token
    String token = request.getHeader("token");
    // 如果请求头中不包含token直接放行
    if (StringUtils.isBlank(token)) {
    
    
      filterChain.doFilter(request, response);
      return;
    }
    // 解析token
    String userId = null;
    try {
    
    
      Claims claims = JwtUtil.parseJWT(token);
      userId = claims.getSubject();
    } catch (BaseException e) {
    
    
      log.error("非法的token:{}", token);
      //throw new BaseException(ResultCode.TOKEN_VALIDATE_LOSE);
      resolver.resolveException(request, response, null, new BaseException(ResultCode.TOKEN_VALIDATE_LOSE));
      return;
    }
    // 从redis中获取用户信息
    String redisKey = "login:" + userId;
    LoginUser loginUser = (LoginUser) redisUtil.get(redisKey);
    if (Objects.isNull(loginUser)) {
    
    
      //throw new BaseException(10007, "用户未登录");
      // 交给全局异常处理类处理
      resolver.resolveException(request, response, null, new BaseException(10007, "用户未登录"));
      return;
    }
    // 存入SecurityContextHolder
    // loginUser.getAuthorities()获取权限信息封装到Authentication
    UsernamePasswordAuthenticationToken authenticationToken =
        new UsernamePasswordAuthenticationToken(loginUser, null, loginUser.getAuthorities());
    SecurityContextHolder.getContext().setAuthentication(authenticationToken);
    // 放行
    filterChain.doFilter(request, response);
  }
}

カスタム例外クラス:

@EqualsAndHashCode(callSuper = true)
@Data
public class BaseException extends RuntimeException {
    
    
  private static final long serialVersionUID = 7939259259170410861L;
  //错误代码
  private Integer code;

  // 错误信息
  private String message;

  public BaseException() {
    
    
    super();
  }

  public BaseException(ResultCode resultCode) {
    
    
    super(resultCode.getMessage());
    this.code = resultCode.getCode();
    this.message = resultCode.getMessage();
  }

  public BaseException(Integer code, String message) {
    
    
    super(message);
    this.code = code;
    this.message = message;
  }

  @Override
  public synchronized Throwable fillInStackTrace() {
    
    
    return this;
  }
}

グローバル キャッチ例外クラス:


@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {
    
    
  @ExceptionHandler(value = BaseException.class)
  public ResponseResult<String> baseExceptionHandler(BaseException e) {
    
    
    String s = CommonUtils.exceptionInfo(e);
    log.error("发生业务异常!异常处在:[{}] , 原因是:[{}]", s, e.getMessage());
    return new ResponseResult<>(e.getCode(), e.getMessage());
  }

  @ExceptionHandler(value = NullPointerException.class)
  public ResponseResult<String> exceptionHandler(NullPointerException e) {
    
    
    String s = CommonUtils.exceptionInfo(e);
    log.error("发生空指针异常!异常处在:[{}] , 原因是:[{}]", s, e.getMessage());
    return new ResponseResult<>(ResultCode.BODY_NOT_MATCH);
  }

  @ExceptionHandler(value = Exception.class)
  public ResponseResult<String> exceptionHandler(Exception e) {
    
    
    String s = CommonUtils.exceptionInfo(e);
    log.error("未知异常!异常处在:[{}] , 原因是:[{}]", s, e.getMessage());
    return new ResponseResult<>(ResultCode.INTERNAL_SERVER_ERROR.getCode(), e.getMessage());
  }

おすすめ

転載: blog.csdn.net/qq_60361946/article/details/128405169