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