2014-02-27 36 views
6

我使用springmvc爲客戶端創建了restful api,我有一個用於檢查accesstoken的攔截器。如何在Spring Interceptor中使用@ExceptionHandler?

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

而在我的控制,我用@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; 
} 

但不幸的是在preHandle方法扔的異常沒有被定義的異常處理程序捕獲在控制器中。

任何一個可以給我一個處理異常的解決方案嗎? PS:我的控制器方法使用下面的代碼產生既JSON和XML

@RequestMapping(value = "login", method = RequestMethod.POST, produces = 
{ 
    "application/xml", "application/json" 
}) 
+1

你不能。 「@ ExceptionHandler」方法只適用於特定的控制器。攔截器在控制器之前執行,所以在那個時候無法知道應用哪個'@ ExceptionHandler'方法。不確定一個'@ ControllerAdvice' bean是否會在這裏起作用,註冊全局錯誤處理方法,否則實現你自己的'HandlerExceptionResolver'來以通用的方式而不是你的控制器來實現它。 –

+0

什麼類型的異常拋出preHandle方法? – Rembo

+0

與其他方法一樣,ValidateToken方法應該是小寫的。 我面臨同樣的問題,但它似乎確實從preHandle方法拋出一個異常時,從來沒有觸及過Controller方法,所以@ControllerAdvice不會趕上並處理這個異常。 – klausch

回答

0

您有無效的返回類型,這就是爲什麼沒有異常處理程序

下面的返回類型都支持抓處理器方法:

  • A ModelAndView object(Servlet MVC或Portlet MVC)。
  • A Model對象,其視圖名稱通過RequestToViewNameTranslator隱式確定。
  • A Map暴露模型的對象,其視圖名稱通過RequestToViewNameTranslator隱式確定。
  • A View對象。
  • A String值被解釋爲視圖名稱。
  • void如果該方法處理反應本身(通過直接寫入的響應內容,聲明類型ServletResponse/HttpServletResponse/RenderResponse的用於該目的的參數),或者如果視圖名稱應該被隱式地確定通過RequestToViewNameTranslator(未聲明處理程序方法簽名中的響應參數;僅適用於Servlet環境)。

試着改變你的返回類型,讓它工作。

REFFERENCE:spring source

3

使用其他方法,捕獲異常,並轉發到另一個控制器解決。

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; 
} 
+0

無需拋出異常。拋出異常會導致性能問題。根據條件返回一個值並設置response.setStatus()或根據需要修改響應對象。最後,'return false'將確保響應被髮送回客戶端。 – jaks

2

移動你@ExceptionHandler方法爲@ControllerAdvice註釋類可以幫助在這裏。請參閱:ControllerAdvice

Rembo已在評論中建議它(標記爲「不確定」),我確認這適用於我:在這種情況下,拋出的異常被正確捕獲。

相關問題