繁体   English   中英

@ControllerAdvice 不处理异常

[英]@ControllerAdvice doesn't handle exceptions

我正在使用 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());
}

这是我的控制器建议,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);
    }

}

这是我的文件夹结构: 在此处输入图片说明

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

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

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

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

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

让您的控制器扩展ResponseEntityExceptionHandler并让您的异常处理方法将WebRequest作为参数

然后将您的返回值更改为此

return handleExceptionInternal(ex, errorInfo, new HttpHeaders(), HttpStatus.BAD_REQUEST, request);

HttpStatus.BAD_REQUEST可以更改为任何 40x 错误

Exception.class示例

@ExceptionHandler(value = { Exception.class })
protected ResponseEntity<Object> handleUncaughtException(Exception ex, WebRequest request) {

  String message = "Something bad happened";

  return handleExceptionInternal(ex, message, new HttpHeaders(), HttpStatus.BAD_REQUEST, request);
}

根据这个Make simple servlet filter work with @ControllerAdvice你可以创建一个自定义处理程序。

然后将您的新处理程序添加到您的WebSecurityConfigurerAdapter

@Override
public void addInterceptors(InterceptorRegistry registry) {
    registry.addInterceptor(new CustomHandler());
}

我也遇到过这个问题,其中 RestControllerAdivce 没有处理异常,事实是建议方法只能在其签名中包含异常抛出方法具有或可以提供的那些参数。 我的 AOP 方法无法访问 Headers,因此它无法向 RestControllerAdivce 方法提供 Headers。 一旦我在 RestController 中创建了一个没有 Headers 作为参数的新异常处理程序方法,RestControllerAdivce 就开始按预期工作。 详情在这里

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM