Spring默認會將自身拋出的異常自動映射到合適的狀態碼,如下是一些示例:
舉個例子,當後端拋出如下異常(TypeMismatchException異常,往方法傳參時,類型不匹配):
org.springframework.beans.TypeMismatchException: Failed to convert value of type 'java.lang.String' to required type 'long'; nested exception is java.lang.NumberFormatException: For input string: "2l" at org.springframework.beans.TypeConverterSupport.doConvert(TypeConverterSupport.java:77) at org.springframework.beans.TypeConverterSupport.convertIfNecessary(TypeConverterSupport.java:47) at org.springframework.validation.DataBinder.convertIfNecessary(DataBinder.java:603) ...
前台返回400狀態碼:
除了以上異常,對於其它異常以及我們業務自己拋出的異常,如果沒有明確綁定Http狀態碼,響應默認都會帶有500狀態碼。
當然,除了這些默認機制,我們也可以將自定義異常綁定特點的Http狀態碼,通過@ResponseStatus注解可實現,如下示例:
定義一個異常,通過@ResponseStatus注解綁定400狀態碼:
@ResponseStatus(value = HttpStatus.NOT_FOUND) public class MyException extends RuntimeException { }
然後再controller拋出自定義異常throw new MyException();
訪問controller,發現響應確實返回了400狀態碼。
異常處理方法能處理同一個controller中所有方法拋出的異常,如下示例:
我們在controller下添加了一個MyException異常的處理方法,直接返回到body。
@ExceptionHandler(MyException.class) @ResponseBody public String handleException(){ return "handle by ExceptionHandler."; }
打開浏覽器,觀察結果:
異常處理方法只能處理同一個controller中拋出的異常,然而一個系統,肯定不止一個controller,總不可能在每個controller中都添加重復性的異常處理方法吧~~
那麼對於多個controller,如何處理異常呢?使用@ControllerAdvice注解即可。
帶有@ControllerAdvice注解的類,可以收到系統中所有Controller拋出的異常,如下示例:
@ControllerAdvice public class DSSExceptionHandler extends BaseController { /** * 處理controller拋出的異常 * * @return */ @ExceptionHandler(Exception.class) @ResponseBody public String handleException(HttpServletRequest request, Exception e) { logger.error("Request FAILD, URL = {} ", request.getRequestURI()); logger.error(e.toString(), e); return gson.toJson(BaseController.FAILD); } /** * 處理controller拋出的異常 * * @return */ @ExceptionHandler(NumberFormatException.class) @ResponseBody public String handleNumberFormatException(HttpServletRequest request, NumberFormatException e) { logger.error("Request FAILD, URL = {} ", request.getRequestURI()); logger.error(e.toString(), e); return gson.toJson(BaseController.FAILD); } }
有一個點注意下,就是spring 掃描配置的時候,要包括該bean,我的配置如下,可參考:
spring-mvc.xml:
<context:component-scan base-package="com.cetiti.epdc.dss" > <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/> <context:include-filter type="annotation" expression="org.springframework.web.bind.annotation.ControllerAdvice"/> </context:component-scan>
spring.xml
<context:component-scan base-package="com.cetiti.epdc.dss"> <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller" /> <context:exclude-filter type="annotation" expression="org.springframework.web.bind.annotation.ControllerAdvice" /> </context:component-scan>
另外,在上面的示例中,范圍更小的異常,優先級更大,所以會調用handleNumberFormatException方法。
spring in action 4