溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Spring Boot 中自定義異常怎么處理

發(fā)布時間:2021-12-24 17:08:28 來源:億速云 閱讀:192 作者:小新 欄目:大數(shù)據(jù)

這篇文章將為大家詳細(xì)講解有關(guān)Spring Boot 中自定義異常怎么處理,小編覺得挺實用的,因此分享給大家做個參考,希望大家閱讀完這篇文章后可以有所收獲。

在 Spring Boot 項目中 ,異常統(tǒng)一處理,可以使用 Spring 中 @ControllerAdvice 來統(tǒng)一處理,也可以自己來定義異常處理方案。Spring Boot 中,對異常的處理有一些默認(rèn)的策略,我們分別來看。

默認(rèn)情況下,Spring Boot 中的異常頁面 是這樣的:

Spring Boot 中自定義異常怎么處理

我們從這個異常提示中,也能看出來,之所以用戶看到這個頁面,是因為開發(fā)者沒有明確提供一個 /error 路徑,如果開發(fā)者提供了 /error 路徑 ,這個頁面就不會展示出來,不過在 Spring Boot 中,提供 /error 路徑實際上是下下策,Spring Boot 本身在處理異常時,也是當(dāng)所有條件都不滿足時,才會去找 /error 路徑。那么我們就先來看看,在 Spring Boot 中,如何自定義 error 頁面,整體上來說,可以分為兩種,一種是靜態(tài)頁面,另一種是動態(tài)頁面。

靜態(tài)異常頁面

自定義靜態(tài)異常頁面,又分為兩種,第一種 是使用 HTTP 響應(yīng)碼來命名頁面,例如 404.html、405.html、500.html ....,另一種就是直接定義一個 4xx.html,表示400-499 的狀態(tài)都顯示這個異常頁面,5xx.html 表示 500-599 的狀態(tài)顯示這個異常頁面。

默認(rèn)是在 classpath:/static/error/ 路徑下定義相關(guān)頁面:

Spring Boot 中自定義異常怎么處理

此時,啟動項目,如果項目拋出 500 請求錯誤,就會自動展示 500.html 這個頁面,發(fā)生 404 就會展示 404.html 頁面。如果異常展示頁面既存在 5xx.html,也存在 500.html ,此時,發(fā)生500異常時,優(yōu)先展示 500.html 頁面。

動態(tài)異常頁面

動態(tài)的異常頁面定義方式和靜態(tài)的基本 一致,可以采用的頁面模板有 jsp、freemarker、thymeleaf。動態(tài)異常頁面,也支持 404.html 或者 4xx.html ,但是一般來說,由于動態(tài)異常頁面可以直接展示異常詳細(xì)信息,所以就沒有必要挨個枚舉錯誤了 ,直接定義 4xx.html(這里使用thymeleaf模板)或者 5xx.html 即可。

注意,動態(tài)頁面模板,不需要開發(fā)者自己去定義控制器,直接定義異常頁面即可 ,Spring Boot 中自帶的異常處理器會自動查找到異常頁面。

頁面定義如下:

Spring Boot 中自定義異常怎么處理

頁面內(nèi)容如下:

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h2>5xx</h2>
<table border="1">
    <tr>
        <td>path</td>
        <td th:text="${path}"></td>
    </tr>
    <tr>
        <td>error</td>
        <td th:text="${error}"></td>
    </tr>
    <tr>
        <td>message</td>
        <td th:text="${message}"></td>
    </tr>
    <tr>
        <td>timestamp</td>
        <td th:text="${timestamp}"></td>
    </tr>
    <tr>
        <td>status</td>
        <td th:text="${status}"></td>
    </tr>
</table>
</body>
</html>

默認(rèn)情況下,完整的異常信息就是這5條,展示 效果如下 :

Spring Boot 中自定義異常怎么處理

如果動態(tài)頁面和靜態(tài)頁面同時定義了異常處理頁面,例如 classpath:/static/error/404.htmlclasspath:/templates/error/404.html 同時存在時,默認(rèn)使用動態(tài)頁面。即完整的錯誤頁面查找方式應(yīng)該是這樣:

發(fā)生了500錯誤-->查找動態(tài) 500.html 頁面-->查找靜態(tài) 500.html --> 查找動態(tài) 5xx.html-->查找靜態(tài) 5xx.html。

自定義異常數(shù)據(jù)

默認(rèn)情況下,在Spring Boot 中,所有的異常數(shù)據(jù)其實就是上文所展示出來的5條數(shù)據(jù),這5條數(shù)據(jù)定義在 org.springframework.boot.web.reactive.error.DefaultErrorAttributes 類中,具體定義在 getErrorAttributes 方法中 :

@Override
public Map<String, Object> getErrorAttributes(ServerRequest request,
                boolean includeStackTrace) {
        Map<String, Object> errorAttributes = new LinkedHashMap<>();
        errorAttributes.put("timestamp", new Date());
        errorAttributes.put("path", request.path());
        Throwable error = getError(request);
        HttpStatus errorStatus = determineHttpStatus(error);
        errorAttributes.put("status", errorStatus.value());
        errorAttributes.put("error", errorStatus.getReasonPhrase());
        errorAttributes.put("message", determineMessage(error));
        handleException(errorAttributes, determineException(error), includeStackTrace);
        return errorAttributes;
}

DefaultErrorAttributes 類本身則是在org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration 異常自動配置類中定義的,如果開發(fā)者沒有自己提供一個 ErrorAttributes 的實例的話,那么 Spring Boot 將自動提供一個ErrorAttributes 的實例,也就是 DefaultErrorAttributes 。

基于此 ,開發(fā)者自定義 ErrorAttributes 有兩種方式 :

  1. 直接實現(xiàn) ErrorAttributes 接口

  2. 繼承 DefaultErrorAttributes(推薦),因為 DefaultErrorAttributes 中對異常數(shù)據(jù)的處理已經(jīng)完成,開發(fā)者可以直接使用。

具體定義如下:

@Component
public class MyErrorAttributes  extends DefaultErrorAttributes {
    @Override
    public Map<String, Object> getErrorAttributes(WebRequest webRequest, boolean includeStackTrace) {
        Map<String, Object> map = super.getErrorAttributes(webRequest, includeStackTrace);
        if ((Integer)map.get("status") == 500) {
            map.put("message", "服務(wù)器內(nèi)部錯誤!");
        }
        return map;
    }
}

定義好的 ErrorAttributes 一定要注冊成一個 Bean ,這樣,Spring Boot 就不會使用默認(rèn)的 DefaultErrorAttributes 了,運行效果如下圖:

Spring Boot 中自定義異常怎么處理

自定義異常視圖

異常視圖默認(rèn)就是前面所說的靜態(tài)或者動態(tài)頁面,這個也是可以自定義的,首先 ,默認(rèn)的異常視圖加載邏輯在 org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController 類的 errorHtml 方法中,這個方法用來返回異常頁面+數(shù)據(jù),還有另外一個 error 方法,這個方法用來返回異常數(shù)據(jù)(如果是 ajax 請求,則該方法會被觸發(fā))。

@RequestMapping(produces = MediaType.TEXT_HTML_VALUE)
public ModelAndView errorHtml(HttpServletRequest request,
                HttpServletResponse response) {
        HttpStatus status = getStatus(request);
        Map<String, Object> model = Collections.unmodifiableMap(getErrorAttributes(
                        request, isIncludeStackTrace(request, MediaType.TEXT_HTML)));
        response.setStatus(status.value());
        ModelAndView modelAndView = resolveErrorView(request, response, status, model);
        return (modelAndView != null) ? modelAndView : new ModelAndView("error", model);
}

在該方法中 ,首先會通過 getErrorAttributes 方法去獲取異常數(shù)據(jù)(實際上會調(diào)用到 ErrorAttributes 的實例 的 getErrorAttributes 方法),然后調(diào)用 resolveErrorView 去創(chuàng)建一個 ModelAndView ,如果這里創(chuàng)建失敗,那么用戶將會看到默認(rèn)的錯誤提示頁面。

正常情況下, resolveErrorView 方法會來到 DefaultErrorViewResolver 類的 resolveErrorView 方法中:

@Override
public ModelAndView resolveErrorView(HttpServletRequest request, HttpStatus status,
                Map<String, Object> model) {
        ModelAndView modelAndView = resolve(String.valueOf(status.value()), model);
        if (modelAndView == null && SERIES_VIEWS.containsKey(status.series())) {
                modelAndView = resolve(SERIES_VIEWS.get(status.series()), model);
        }
        return modelAndView;
}

在這里,首先以異常響應(yīng)碼作為視圖名分別去查找動態(tài)頁面和靜態(tài)頁面,如果沒有查找到,則再以 4xx 或者 5xx 作為視圖名再去分別查找動態(tài)或者靜態(tài)頁面。

要自定義異常視圖解析,也很容易 ,由于 DefaultErrorViewResolver 是在 ErrorMvcAutoConfiguration 類中提供的實例,即開發(fā)者沒有提供相關(guān)實例時,會使用默認(rèn)的 DefaultErrorViewResolver ,開發(fā)者提供了自己的 ErrorViewResolver 實例后,默認(rèn)的配置就會失效,因此,自定義異常視圖,只需要提供 一個 ErrorViewResolver 的實例即可:

@Component
public class MyErrorViewResolver extends DefaultErrorViewResolver {
    public MyErrorViewResolver(ApplicationContext applicationContext, ResourceProperties resourceProperties) {
        super(applicationContext, resourceProperties);
    }
    @Override
    public ModelAndView resolveErrorView(HttpServletRequest request, HttpStatus status, Map<String, Object> model) {
        return new ModelAndView("/aaa/123", model);
    }
}

實際上,開發(fā)者也可以在這里定義異常數(shù)據(jù)(直接在 resolveErrorView 方法重新定義一個 model ,將參數(shù)中的model 數(shù)據(jù)拷貝過去并修改,注意參數(shù)中的 model 類型為 UnmodifiableMap,即不可以直接修改),而不需要自定義MyErrorAttributes。定義完成后,提供一個名為123的視圖,如下圖:

Spring Boot 中自定義異常怎么處理

如此之后,錯誤試圖就算定義成功了。

關(guān)于“Spring Boot 中自定義異常怎么處理”這篇文章就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,使各位可以學(xué)到更多知識,如果覺得文章不錯,請把它分享出去讓更多的人看到。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI