如何在Spring Interceptor中使用@ExceptionHandler?

Wp7*_*ner 6 java spring exception-handling interceptor

我正在使用springmvc为客户端创建restful api,我有一个用于检查accesstoken的拦截器.

public class AccessTokenInterceptor extends HandlerInterceptorAdapter
{    
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception
{
    if (handler instanceof HandlerMethod)
    {
        HandlerMethod handlerMethod = (HandlerMethod) handler;
        Authorize authorizeRequired = handlerMethod.getMethodAnnotation(Authorize.class);
        if (authorizeRequired != null)
        {
            String token = request.getHeader("accesstoken");
            ValidateToken(token);
        }
    }
    return true;
}

protected long ValidateToken(String token)
{
    AccessToken accessToken = TokenImpl.GetAccessToken(token);

    if (accessToken != null)
    {
        if (accessToken.getExpirationDate().compareTo(new Date()) > 0)
        {
            throw new TokenExpiredException();
        }
        return accessToken.getUserId();
    }
    else
    {
        throw new InvalidTokenException();
    }
}
Run Code Online (Sandbox Code Playgroud)

在我的控制器中,我使用@ExceptionHandler来处理异常,处理InvalidTokenException的代码看起来像

@ExceptionHandler(InvalidTokenException.class)
public @ResponseBody
Response handleInvalidTokenException(InvalidTokenException e)
{
    Log.p.debug(e.getMessage());
    Response rs = new Response();
    rs.setErrorCode(ErrorCode.INVALID_TOKEN);
    return rs;
}
Run Code Online (Sandbox Code Playgroud)

但不幸的是,preHandle方法抛出的异常并未被控制器中定义的异常处理程序捕获.

任何人都可以给我一个处理异常的解决方案吗? PS:我的控制器方法使用以下代码生成json和xml:

@RequestMapping(value = "login", method = RequestMethod.POST, produces =
{
    "application/xml", "application/json"
})
Run Code Online (Sandbox Code Playgroud)

Wp7*_*ner 6

使用其他方法解决,捕获异常并转发到另一个控制器。

try
{
    ValidateToken(token);
} catch (InvalidTokenException ex)
{
    request.getRequestDispatcher("/api/error/invalidtoken").forward(request, response);
    return false;
} catch (TokenExpiredException ex)
{
    request.getRequestDispatcher("/api/error/tokenexpired").forward(request, response);
    return false;
}
Run Code Online (Sandbox Code Playgroud)


ist*_*esi 5

@ExceptionHandler方法移到带@ControllerAdvice注释的类中可以在这里有所帮助。请参阅:ControllerAdvice

Rembo已经在评论中建议了它(标记为“不确定”),我确认对我有用:在这种情况下,可以正确捕获引发的异常。

  • 我正在使用 ControllerAdvice 类,但它对我不起作用。当“preHandle”方法抛出异常时,我的“@ExceptionHandler”“handle”代码没有被执行。Springboot 2.0.2 (2认同)

Abh*_*yak 0

您的返回类型无效,这就是异常处理程序未捕获的原因

处理程序方法支持以下返回类型:

  • 对象ModelAndView(Servlet MVC 或 Portlet MVC)。
  • 一个Model对象,其视图名称通过 隐式确定RequestToViewNameTranslator
  • 用于公开模型的对象Map,其视图名称通过RequestToViewNameTranslator.
  • 一个View物体。
  • String被解释为视图名称的值。
  • void如果方法本身处理响应(通过直接写入响应内容,为此目的声明ServletResponse//HttpServletResponse类型的参数RenderResponse),或者如果视图名称应该通过 a 隐式确定RequestToViewNameTranslator(不在处理程序方法签名中声明响应参数) ;仅适用于 Servlet 环境)。

尝试改变你的返回类型,让它工作。

参考:spring源码