Springboot项目捕获不到Filter中的异常解决方案

在使用Spring Security时用过滤器进行jwt校验时,全局的异常返回没有捕获到Filter中的异常。特此记录一下

原因:在Spring Boot由于全局异常处理@RestControllerAdvice只会去捕获所有Controller层抛出的异常,所以在filter当中抛出的异常异常类是没有感知的。
解决办法 :在过滤器中将异常转移到Controller中

在过滤器中注入HandlerExceptionResolver 然后通过resolver.resolveException()将异常转移到Controller即可:

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

完整Filter代码如下:

@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());
  }
  • 6
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 9
    评论
在Spring Boot,全局异常处理器可以用于捕获和处理应用程序抛出的异常。然而,默认情况下,Spring Boot无法捕获和处理HttpMessageNotReadableException异常。这是因为HttpMessageNotReadableException异常是由HttpMessageConverter引起的,它在尝试将请求正文转换为控制器方法参数时发生错误。 要解决这个问题,你可以实现自己的全局异常处理器,并在其捕获和处理HttpMessageNotReadableException异常。以下是一个示例: ```java @ControllerAdvice public class GlobalExceptionHandler { @ExceptionHandler(HttpMessageNotReadableException.class) public ResponseEntity<Object> handleHttpMessageNotReadableException( HttpMessageNotReadableException ex, WebRequest request) { // 处理HttpMessageNotReadableException异常 // 返回自定义错误信息或其他逻辑 return new ResponseEntity<>("Error: Invalid request body", HttpStatus.BAD_REQUEST); } // 添加其他异常处理方法... } ``` 在上面的示例,我们使用@ControllerAdvice注释来标记全局异常处理器类,并使用@ExceptionHandler注释来指定处理HttpMessageNotReadableException异常的方法。在方法,我们可以根据需要自定义处理逻辑,并返回自定义错误信息或适当的HTTP状态码。 注意,为了使全局异常处理器生效,还需要确保在应用程序启用了异常处理机制。你可以通过在应用程序的启动类上添加@EnableWebMvc或@EnableWebFlux注释来实现这一点。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值