SpringMVC異常處理句柄這些細(xì)節(jié),你知道嗎?
回顧
@Controller和@ControllerAdvice類(lèi)可以使用@ExceptionHandler注解標(biāo)注方法來(lái)處理控制器方法的異常,如下例所示:
局部異常處理
全局異常處理
指定能處理的異常類(lèi)型
在@ExceptionHandler中指明能夠處理的異常類(lèi)。
以上是回顧了SpringMVC異常處理的基本使用,通過(guò)@ExceptionHandler注解標(biāo)注方法,在上面的方法中都接受的是異常類(lèi),那這方法可以接收什么樣的參數(shù)及返回值呢?
異常句柄參數(shù)
@ExceptionHandler方法支持以下參數(shù):
方法參數(shù) | 描述 |
Exception type | 用于訪問(wèn)引發(fā)的異常。 |
HandlerMethod | 用于訪問(wèn)引發(fā)異常的控制器方法。 |
WebRequest, NativeWebRequest | 對(duì)請(qǐng)求參數(shù)、請(qǐng)求和會(huì)話屬性的通用訪問(wèn),而不直接使用 Servlet API。 |
javax.servlet.ServletRequest, javax.servlet.ServletResponse | 選擇任何特定的請(qǐng)求或響應(yīng)類(lèi)型(例如,ServletRequest或HttpServletRequest或Spring的MultipartRequest或MultipartHttpServletRequest)。 |
javax.servlet.http.HttpSession | 強(qiáng)制會(huì)話的存在。因此,這樣的參數(shù)永遠(yuǎn)不會(huì)為空。注意,會(huì)話訪問(wèn)不是線程安全的。如果允許多個(gè)請(qǐng)求并發(fā)訪問(wèn)一個(gè)會(huì)話,可以考慮將RequestMappingHandlerAdapter實(shí)例的synchronizeOnSession標(biāo)志設(shè)置為true。 |
java.security.Principal | 當(dāng)前已驗(yàn)證的用戶-如果已知,可能是特定的Principal實(shí)現(xiàn)類(lèi)。 |
HttpMethod | 請(qǐng)求的HTTP方法。 |
java.util.Locale | 當(dāng)前請(qǐng)求區(qū)域設(shè)置,由可用的最特定的LocaleResolver確定——實(shí)際上是配置的LocaleResolver或LocaleContextResolver。 |
java.util.TimeZone, java.time.ZoneId | 與當(dāng)前請(qǐng)求關(guān)聯(lián)的時(shí)區(qū),由LocaleContextResolver確定。 |
java.io.OutputStream, java.io.Writer | 用于訪問(wèn)由Servlet API公開(kāi)的原始響應(yīng)體。 |
java.util.Map, org.springframework.ui.Model, org.springframework.ui.ModelMap | 用于訪問(wèn)錯(cuò)誤響應(yīng)的模型。總是空的。 |
RedirectAttributes | 指定在重定向情況下使用的屬性-(將被追加到查詢字符串中)和臨時(shí)存儲(chǔ)的flash屬性,直到重定向后的請(qǐng)求。請(qǐng)參見(jiàn)重定向?qū)傩院虵lash屬性。 |
@SessionAttribute | 對(duì)于任何會(huì)話屬性的訪問(wèn),與作為類(lèi)級(jí)@SessionAttributes聲明的結(jié)果存儲(chǔ)在會(huì)話中的模型屬性相反。更多細(xì)節(jié)請(qǐng)參見(jiàn)@SessionAttribute。 |
@RequestAttribute | 用于訪問(wèn)請(qǐng)求屬性。詳見(jiàn)@RequestAttribute。 |
異常句柄返回值
@ExceptionHandler方法支持以下返回值:
返回值 | 描述 |
@ResponseBody | 返回值通過(guò)HttpMessageConverter實(shí)例轉(zhuǎn)換并寫(xiě)入響應(yīng)。看到@ResponseBody。 |
HttpEntity<B>, ResponseEntity<B> | 返回值指定通過(guò)HttpMessageConverter實(shí)例轉(zhuǎn)換完整響應(yīng)(包括HTTP報(bào)頭和正文)并將其寫(xiě)入響應(yīng)。看到ResponseEntity。 |
String | 要用ViewResolver實(shí)現(xiàn)解析的視圖名稱(chēng),并與隱式模型一起使用——通過(guò)命令對(duì)象和@ModelAttribute方法確定。處理程序方法還可以通過(guò)聲明model參數(shù)(前面描述過(guò))以編程方式豐富模型。 |
View | 一個(gè)用于呈現(xiàn)隱式模型的View實(shí)例——通過(guò)命令對(duì)象和@ModelAttribute方法確定。處理程序方法還可以通過(guò)聲明model參數(shù)(前面描述過(guò))以編程方式豐富模型。 |
java.util.Map, org.springframework.ui.Model | 屬性被添加到隱式模型中,視圖名通過(guò)RequestToViewNameTranslator隱式確定。 |
@ModelAttribute | 添加到模型中的屬性,通過(guò)RequestToViewNameTranslator隱式確定視圖名。 注意@ModelAttribute是可選的。請(qǐng)參閱該表末尾的“任何其他返回值”。 |
ModelAndView object | 要使用的視圖和模型屬性以及(可選的)響應(yīng)狀態(tài)。 |
void | 具有void返回類(lèi)型(或空返回值)的方法,如果它還具有ServletResponse、OutputStream參數(shù)或@ResponseStatus注釋?zhuān)瑒t認(rèn)為它已經(jīng)完全處理了響應(yīng)。如果控制器已經(jīng)做了一個(gè)正的ETag或lastModified時(shí)間戳檢查(詳情請(qǐng)參閱Controllers),同樣也是正確的。 如果以上都不為真,void返回類(lèi)型也可以表示REST控制器的“無(wú)響應(yīng)體”或HTML控制器的默認(rèn)視圖名稱(chēng)選擇。 |
Any other return value | 如果返回值與上述任何一個(gè)都不匹配,并且不是簡(jiǎn)單類(lèi)型(由BeanUtils#isSimpleProperty決定),默認(rèn)情況下,它將被視為要添加到模型中的模型屬性。如果是簡(jiǎn)單類(lèi)型,則仍未解決。 |
REST API異常
REST服務(wù)的一個(gè)常見(jiàn)需求是在響應(yīng)體中包含錯(cuò)誤詳細(xì)信息。Spring框架不會(huì)自動(dòng)執(zhí)行此操作,因?yàn)轫憫?yīng)體中的錯(cuò)誤細(xì)節(jié)表示是特定于應(yīng)用程序的。但是,@RestController可以使用帶有ResponseEntity返回值的@ExceptionHandler方法來(lái)設(shè)置響應(yīng)的狀態(tài)和主體。這樣的方法也可以在@ControllerAdvice類(lèi)中聲明,以便全局應(yīng)用它們。
在響應(yīng)體中使用錯(cuò)誤細(xì)節(jié)實(shí)現(xiàn)全局異常處理的應(yīng)用程序應(yīng)該考慮擴(kuò)展ResponseEntityExceptionHandler,它為Spring MVC引發(fā)的異常提供處理,并提供自定義響應(yīng)體的鉤子。要使用它,可以創(chuàng)建ResponseEntityExceptionHandler的子類(lèi),用@ControllerAdvice注釋它,重寫(xiě)必要的方法,并將其聲明為Spring bean,如下:
ResponseEntityExceptionHandler類(lèi)中內(nèi)置了很多類(lèi)型的異常處理