@ControllerAdvice 不处理异常

Den*_*nov 2 java spring spring-boot

我正在使用 Spring Boot 1.5.9 来开发我的应用程序。我需要实现 jwt 身份验证,并且我使用了 jjwt 库。以下代码来自我的自定义身份验证安全过滤器,它继承自OncePerRequestFilter. 在这里,我尝试从令牌解析用户名,当自动解析用户名时,会进行 jwt 验证,并检查令牌的过期时间。我调试它并且它有效,所以接下来我想向客户端应用程序发送正确的消息,说明身份验证失败的原因。我想抛出一个 ExpiredJwtException 并使用格式化输出的控制器建议来处理它。

这是异常抛出:

try {
    username = jwtTokenService.getUsername(authToken);
} catch (IllegalArgumentException e) {
    logger.error("an error occured during getting username from token", e);
} catch (ExpiredJwtException e) {
    logger.warn("the token is expired and not valid anymore", e);
    throw new ExpiredJwtException(e.getHeader(), e.getClaims(), e.getMessage());
}
Run Code Online (Sandbox Code Playgroud)

这是我的控制器建议,JwtException 是 ExpiredJwtException 的基类,我抛出它,所以它应该可以工作。我也尝试在ExceptionHandler中直接使用ExpiredJwtException,但效果不佳。接下来我想用同样的方式处理另一个异常。

@ControllerAdvice
public class GlobalControllerExceptionHandler {

    @ExceptionHandler(Exception.class)
    public @ResponseBody
    ResponseEntity<Map<String, Object>> handleException(Exception ex) {
        Map<String, Object> errorInfo = new HashMap<>();
        errorInfo.put("message", ex.getMessage());
        errorInfo.put("status", HttpStatus.BAD_REQUEST);
        errorInfo.put("status_code", HttpStatus.BAD_REQUEST.value());
        return new ResponseEntity<>(errorInfo, HttpStatus.BAD_REQUEST);
    }


    @ExceptionHandler(JwtException.class)
    //@ResponseStatus(HttpStatus.UNPROCESSABLE_ENTITY)
    public @ResponseBody
    ResponseEntity handleJwtException(JwtException ex) {
        Map<String, Object> errorInfo = new HashMap<>();
        errorInfo.put("message", ex.getLocalizedMessage());
        errorInfo.put("status", HttpStatus.UNPROCESSABLE_ENTITY);
        errorInfo.put("status_code", HttpStatus.UNPROCESSABLE_ENTITY.value());
        return new ResponseEntity<>(errorInfo, HttpStatus.UNPROCESSABLE_ENTITY);
    }

}
Run Code Online (Sandbox Code Playgroud)

这是我的文件夹结构: 在此输入图像描述

我只想返回 4xx 状态的响应,但当抛出异常时,我总是收到 5xx 内部错误。你能告诉我我的代码有什么问题吗?谢谢指教。

Bog*_*ros 5

如果在filter中抛出异常,则不涉及Springs异常处理( @ControllerAdvice, )。@ExceptionHandler您需要捕获过滤器内的所有异常并直接使用ServletResponse.

据我了解 -过滤器是低级逻辑(在 Spring 基础设施之前处理请求),但您可以有一个解决方法,例如包装链接并捕获所有RuntimeExceptions. (看起来像一个紧缩,但没有其他解决方案)。

如果您想使用特定的登录来创建异常对象 - 覆盖ErrorAttributesbean。它将允许您对所有应用程序异常有一个单一的视图。

直接指定http响应状态使用
httpServletResponse.setStatus(... your status code ...);