javascript
Spring 3.2的REST异常处理
1.概述
本文將重點(diǎn)介紹如何使用REST API的Spring實(shí)現(xiàn)異常處理 。 我們將介紹在Spring 3.2之前可用的較舊的解決方案,然后是對(duì)Spring 3.2的新支持。
本文的主要目的是展示如何最好地將應(yīng)用程序中的異常映射到HTTP狀態(tài)代碼。 哪種狀態(tài)代碼不適合本文中的哪種情況,REST錯(cuò)誤表示的語(yǔ)法也不屬于本文的范圍。
在Spring 3.2之前,在Spring MVC應(yīng)用程序中處理異常的兩種主要方法是: HandlerExceptionResolver和@ExceptionHandler批注。 Spring 3.2引入了新的@ControllerAdvice注釋,以解決前兩種解決方案的局限性。
所有這些確實(shí)有一個(gè)共同點(diǎn)–它們很好地處理了關(guān)注點(diǎn)分離 :標(biāo)準(zhǔn)應(yīng)用程序代碼可以正常拋出異常以指示某種類型的失敗–然后可以通過(guò)以下任意方式處理異常。
2.通過(guò)控制器級(jí)別
定義帶有@ExceptionHandler注釋的Controller級(jí)別方法非常容易:
public class FooController{...@ExceptionHandler({ CustomException1.class, CustomException2.class })public void handleException() {//} }一切都很好,但是這種方法確實(shí)有一個(gè)主要缺點(diǎn)–帶@ExceptionHandler注釋的方法僅對(duì)特定Controller有效 ,而不對(duì)整個(gè)應(yīng)用程序全局有效。 當(dāng)然,這使其不適用于通用異常處理機(jī)制。
一個(gè)常見(jiàn)的解決方案是讓?xiě)?yīng)用程序中的所有Controller都擴(kuò)展Base Controller類 -但是,對(duì)于由于某種原因無(wú)法使Controllers擴(kuò)展為此類的應(yīng)用程序來(lái)說(shuō),這可能是個(gè)問(wèn)題。 例如,控制器可能已經(jīng)從另一個(gè)基類擴(kuò)展了,該基類可能在另一個(gè)jar中,或者不能直接修改,或者它們本身也不能直接修改。
接下來(lái),我們將討論另一種解決異常處理問(wèn)題的方法-一種全局的方法,不包括對(duì)現(xiàn)有工件(如Controllers)的任何更改。
3.通過(guò)
為了在REST API中實(shí)現(xiàn)統(tǒng)一的異常處理機(jī)制 ,我們需要使用HandlerExceptionResolver-這將解決應(yīng)用程序在運(yùn)行時(shí)拋出的所有異常。 在尋求自定義解析器之前,讓我們看一下現(xiàn)有的實(shí)現(xiàn)。
3.1。 ExceptionHandlerExceptionResolver
該解析器是在Spring 3.1中引入的,默認(rèn)情況下已在DispatcherServlet中啟用。 這實(shí)際上是前面介紹的@ ExceptionHandler機(jī)制如何工作的核心組件。
3.2。 DefaultHandlerExceptionResolver
該解析器是在Spring 3.0中引入的,默認(rèn)情況下已在DispatcherServlet中啟用。 它用于將標(biāo)準(zhǔn)Spring異常解析為其對(duì)應(yīng)的HTTP狀態(tài)代碼,即客戶端錯(cuò)誤– 4xx和服務(wù)器錯(cuò)誤– 5xx狀態(tài)代碼。 這是它處理的Spring Exception 的完整列表 ,以及如何將它們映射到狀態(tài)代碼。
盡管它確實(shí)正確設(shè)置了響應(yīng)的狀態(tài)碼,但此解析器的一個(gè)局限性在于它沒(méi)有對(duì)響應(yīng)的主體設(shè)置任何內(nèi)容。 但是,在REST API的上下文中,狀態(tài)代碼確實(shí)不足以向客戶端提供信息-響應(yīng)也必須具有正文,以允許應(yīng)用程序提供有關(guān)失敗原因的其他信息。
這可以通過(guò)配置View分辨率和通過(guò)ModelAndView渲染錯(cuò)誤內(nèi)容來(lái)解決,但是解決方案顯然不是最優(yōu)的-這就是為什么Spring 3.2提供了更好的選擇的原因-我們將在本文的后半部分討論。
3.3。 ResponseStatusExceptionResolver
該解析器也在Spring 3.0中引入,默認(rèn)情況下在DispatcherServlet中啟用。 它的主要職責(zé)是使用自定義異常上可用的@ResponseStatus批注,并將這些異常映射到HTTP狀態(tài)代碼。
這樣的自定義異常可能看起來(lái)像:
@ResponseStatus(value = HttpStatus.NOT_FOUND) public final class ResourceNotFoundException extends RuntimeException {public ResourceNotFoundException() {super();}public ResourceNotFoundException(String message, Throwable cause) {super(message, cause);}public ResourceNotFoundException(String message) {super(message);}public ResourceNotFoundException(Throwable cause) {super(cause);} }與DefaultHandlerExceptionResolver一樣 ,此解析器在處理響應(yīng)主體方面也受到限制 -它確實(shí)將狀態(tài)代碼映射到響應(yīng)上,但主體仍為null。
3.4。 SimpleMappingExceptionResolver和AnnotationMethodHandlerExceptionResolver
SimpleMappingExceptionResolver已經(jīng)存在了很長(zhǎng)時(shí)間–它來(lái)自較早的Spring MVC模型,并且與REST Service無(wú)關(guān) 。 它用于將異常類名稱映射到視圖名稱。
Spring 3.0中引入了AnnotationMethodHandlerExceptionResolver來(lái)通過(guò)@ExceptionHandler批注處理異常,但是從Spring 3.2開(kāi)始, ExceptionHandlerExceptionResolver已棄用該方法。
3.5。 自定義HandlerExceptionResolver
DefaultHandlerExceptionResolver和ResponseStatusExceptionResolver的組合在為Spring RESTful Service提供良好的錯(cuò)誤處理機(jī)制方面有很長(zhǎng)的路要走-但主要的限制-無(wú)法控制響應(yīng)的主體-證明創(chuàng)建新的異常解析器是合理的。
因此,新解析器的一個(gè)目標(biāo)是啟用一個(gè)信息量更大的響應(yīng)主體,該主體也應(yīng)符合客戶端請(qǐng)求的表示類型(由Accept標(biāo)頭指定):
@Component public class RestResponseStatusExceptionResolver extends AbstractHandlerExceptionResolver {@Overrideprotected ModelAndView doResolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {try {if (ex instanceof IllegalArgumentException) {return handleIllegalArgument((IllegalArgumentException) ex, response, handler);}...} catch (Exception handlerException) {logger.warn("Handling of [" + ex.getClass().getName() + "] resulted in Exception", handlerException);}return null;}private ModelAndView handleIllegalArgument(IllegalArgumentException ex, HttpServletResponse response) throws IOException {response.sendError(HttpServletResponse.SC_CONFLICT);String accept = request.getHeader(HttpHeaders.ACCEPT);...return new ModelAndView();} }這里需要注意的一個(gè)細(xì)節(jié)是請(qǐng)求本身是可用的,因此應(yīng)用程序可以考慮客戶端發(fā)送的Accept標(biāo)頭的值。 例如,如果客戶端要求輸入application / json,則在出現(xiàn)錯(cuò)誤情況時(shí),應(yīng)用程序仍應(yīng)返回以application / json編碼的響應(yīng)正文。
另一個(gè)重要的實(shí)現(xiàn)細(xì)節(jié)是返回ModelAndView -這是響應(yīng)的主體,它將允許應(yīng)用程序?qū)ζ溥M(jìn)行必要的設(shè)置。
這種方法是用于Spring REST服務(wù)的錯(cuò)誤處理的一致且易于配置的機(jī)制。 但是它確實(shí)有局限性 :它與低級(jí)HtttpServletResponse交互,并且適合使用ModelAndView的舊MVC模型-因此仍有改進(jìn)的空間。
4.通過(guò)新的
Spring 3.2通過(guò)新的@ControllerAdvice批注支持全局@ExceptionHandler 。 這將啟用一種機(jī)制,該機(jī)制有別于舊的MVC模型,并利用ResponseEntity以及@ExceptionHandler的類型安全性和靈活性:
@ControllerAdvice public class RestResponseEntityExceptionHandler extends ResponseEntityExceptionHandler {@ExceptionHandler(value = { IllegalArgumentException.class, IllegalStateException.class })protected ResponseEntity<Object> handleConflict(RuntimeException ex, WebRequest request) {String bodyOfResponse = "This should be application specific";return handleExceptionInternal(ex, bodyOfResponse, new HttpHeaders(), HttpStatus.CONFLICT, request);} }新的批注允許將之前分散的多個(gè)@ExceptionHandler合并到單個(gè)全局錯(cuò)誤處理組件中 。
實(shí)際的機(jī)制非常簡(jiǎn)單,但也非常靈活:
- 它允許完全控制響應(yīng)的主體以及狀態(tài)代碼
- 它允許將多個(gè)異常映射到同一方法,以便一起處理
- 它充分利用了更新的RESTful ResposeEntity響應(yīng)
5.結(jié)論
本教程討論了幾種在Spring中為REST API實(shí)現(xiàn)異常處理機(jī)制的方法,從較舊的機(jī)制開(kāi)始,一直到對(duì)Spring 3.2的新支持。 要在現(xiàn)實(shí)世界的REST服務(wù)中完整實(shí)現(xiàn)這些異常處理機(jī)制,請(qǐng)查看github項(xiàng)目 。
翻譯自: https://www.javacodegeeks.com/2013/02/exception-handling-for-rest-with-spring-3-2.html
總結(jié)
以上是生活随笔為你收集整理的Spring 3.2的REST异常处理的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 怎样申请微信账号注册
- 下一篇: 黄腔是指什么 黄腔是指什么意思