Spring 4 異常處理


異常與HTTP狀態碼的映射(@ResponseStatus)

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狀態碼。

控制器中的異常處理方法(@ExceptionHandler)

異常處理方法能處理同一個controller中所有方法拋出的異常,如下示例:

我們在controller下添加了一個MyException異常的處理方法,直接返回到body。

    @ExceptionHandler(MyException.class)
    @ResponseBody
    public String handleException(){
        return "handle by ExceptionHandler.";
    }

打開瀏覽器,觀察結果:

控制器通知(@ControllerAdvice)

異常處理方法只能處理同一個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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM