@ControllerAdvice不处理异常

时间:2018-02-02 13:54:17

标签: 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());
}

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

}

这是我的文件夹结构: enter image description here

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

3 个答案:

答案 0 :(得分:1)

让您的控制器扩展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());
}

答案 1 :(得分:1)

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

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

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

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

答案 2 :(得分:0)

我还遇到了RestControllerAdivce不处理异常的问题,问题是,advice方法只能在签名中包含异常抛出方法具有或可以提供的参数。我的AOP方法无法访问Headers,因此无法将Headers提供给RestControllerAdivce方法。在没有标题作为参数的RestController中创建新的异常处理程序方法后,RestControllerAdivce就开始按预期工作。 Detials here