2013-04-30 50 views
2

我正在使用SpringMVC,並且我想處理其他控制器上的異常。 我的控制器通常在響應輸出中寫入一個json,但是當發生異常時,我無法捕獲它並返回tomcat html頁面。SpringMVC處理其他控制器中的錯誤

如何根據請求中的「accept」參數捕獲全局異常並返回適當的響應?

+0

查看['@ ExceptionHandler'](http://static.springsource.org/spring/docs/3.1.x/javadoc-api/org/springframework/web/bind/annotation/ExceptionHandler.html)註釋。 – 2013-04-30 15:15:01

回答

14

@ControllerAdvice註解是在Spring 3.2發行版中添加的新註釋。從reference docs

中的類@ControllerAdvice註釋可以包含@ExceptionHandler,@InitBinder和@ModelAttribute方法和那些將適用於整個@RequestMapping控制器層次的方法,而不是內聲明它們控制器層次。 @ControllerAdvice是一個組件註釋,允許通過類路徑掃描來自動檢測實現類。

例子:

@ControllerAdvice 
class GlobalControllerExceptionHandler { 

    // Basic example 
    @ExceptionHandler 
    @ResponseStatus(HttpStatus.BAD_REQUEST) 
    @ResponseBody 
    ErrorMessage handleException(FirstException ex) { 
     ErrorMessage errorMessage = createErrorMessage(ex); 
     return errorMessage; 
    } 

    // Multiple exceptions can be handled 
    @ExceptionHandler({SecondException.class, ThirdException.class}) 
    @ResponseStatus(HttpStatus.BAD_REQUEST) 
    @ResponseBody 
    ErrorMessage handleException() { 
     ErrorMessage errorMessage = createErrorMessage(...); 
     return errorMessage; 
    } 

    // Returning a custom response entity 
    @ExceptionHandler 
    ResponseEntity<ErrorMessage> handleException(OtherException ex) { 
     ErrorMessage errorMessage = createErrorMessage(...); 
     ResponseEntity<ErrorMessage> responseEntity = new ResponseEntity<ErrorMessage>(errorMessage, HttpStatus.BAD_REQUEST); 
     return responseEntity; 
    } 
} 

基本上,它可以讓你捕捉指定的異常,創建一個自定義的ErrorMessage(這是根據Accept頭自定義錯誤類,Spring將序列化到響應正文),在本例中將響應狀態設置爲400 - Bad Request。請注意,最後一個示例返回ResponseEntity(並且不是註釋@ResponseBody),它允許您以編程方式指定響應狀態和其他響應標頭。有關@ExceptionHandler的更多信息可以在reference docs或我之前寫的blog post中找到。

更新:根據評論添加更多示例。

+0

很好的答案! @ControllerAdvice是Spring 3.2中最好的事情之一!你也可以把多個映射放到'@ExceptionHandler({Exception1.class,Exception2.class})'。更新帖子信息可能很有趣,當然我認爲。 – 2013-04-30 17:14:08

+0

用這個解決方案可以以編程方式設置響應狀態嗎?我需要這些用於我的用例,並且可以在我的解決方案中看到它可能在那裏。但是,感謝分享這種新方法,將派上用場。 – Matsemann 2013-04-30 17:22:15

+0

@DeividiCavarzan完成! – matsev 2013-05-01 08:47:26

1

另一種方法(我使用的是)創建一個全局異常處理程序,並告訴Spring它應該被使用。那麼當用@ExceptionHandler註釋控制器方法時,您不必重複邏輯或擴展相同的基礎控制器。這是一個簡單的例子。

public class ExceptionHandler implements HandlerExceptionResolver { 

    @Override 
    public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse response, Object o, Exception e) { 
     response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); // Or some other error code 
     ModelAndView mav = new ModelAndView(new MappingJackson2JsonView()); 
     mav.addObject("error", "Something went wrong: \"" + e.getMessage() + "\""); 
     return mav; 
    } 
} 

而在<something>-servlet.xml你將它設爲您想要的exceptionResolver:

<!-- Define our exceptionHandler as the resolver for our program --> 
<bean id="exceptionResolver" class="tld.something.ExceptionHandler" /> 

然後所有的異常將被髮送到您的ExceptionHandler,在那裏你可以看看的請求,並決定如何應該回復給用戶。在我的情況下,我正在使用傑克遜。