SpringBoot統(tǒng)一異常處理的示例分析

這篇文章主要為大家展示了“SpringBoot統(tǒng)一異常處理的示例分析”,內(nèi)容簡而易懂,條理清晰,希望能夠幫助大家解決疑惑,下面讓小編帶領(lǐng)大家一起研究并學(xué)習(xí)一下“SpringBoot統(tǒng)一異常處理的示例分析”這篇文章吧。

站在用戶的角度思考問題,與客戶深入溝通,找到長清網(wǎng)站設(shè)計(jì)與長清網(wǎng)站推廣的解決方案,憑借多年的經(jīng)驗(yàn),讓設(shè)計(jì)與互聯(lián)網(wǎng)技術(shù)結(jié)合,創(chuàng)造個(gè)性化、用戶體驗(yàn)好的作品,建站類型包括:成都網(wǎng)站設(shè)計(jì)、成都網(wǎng)站制作、外貿(mào)網(wǎng)站建設(shè)、企業(yè)官網(wǎng)、英文網(wǎng)站、手機(jī)端網(wǎng)站、網(wǎng)站推廣、域名注冊、網(wǎng)頁空間、企業(yè)郵箱。業(yè)務(wù)覆蓋長清地區(qū)。

區(qū)分請求方式

其實(shí) Spring Boot 本身是內(nèi)置了一個(gè)異常處理機(jī)制的, 會(huì)判斷請求頭的參數(shù)來區(qū)分要返回 JSON 數(shù)據(jù)還是錯(cuò)誤頁面. 源碼為: org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController, 他會(huì)處理 /error 請求. 核心處理代碼如下:

@RequestMapping(
 produces = {"text/html"}
)
// 如果請求頭是 text/html, 則找到錯(cuò)誤頁面, 并返回
public ModelAndView errorHtml(HttpServletRequest request, HttpServletResponse response) {
 // 1. 獲取 HTTP 錯(cuò)誤狀態(tài)碼
 HttpStatus status = this.getStatus(request);
 // 2. 調(diào)用 getErrorAttributes 獲取響應(yīng)的 map 結(jié)果集.
 Map<String, Object> model = Collections.unmodifiableMap(this.getErrorAttributes(request, this.isIncludeStackTrace(request, MediaType.TEXT_HTML)));
 // 3. 設(shè)置響應(yīng)頭的狀態(tài)碼
 response.setStatus(status.value());
 // 4. 獲取錯(cuò)誤頁面的路徑
 ModelAndView modelAndView = this.resolveErrorView(request, response, status, model);
 return modelAndView != null ? modelAndView : new ModelAndView("error", model);
}

@RequestMapping
@ResponseBody
public ResponseEntity<Map<String, Object>> error(HttpServletRequest request) {
 // 調(diào)用 getErrorAttributes 獲取響應(yīng)的 map 結(jié)果集.
 Map<String, Object> body = this.getErrorAttributes(request, this.isIncludeStackTrace(request, MediaType.ALL));
 // 獲取 HTTP 錯(cuò)誤狀態(tài)碼
 HttpStatus status = this.getStatus(request);
 // 返回給頁面 JSON 信息.
 return new ResponseEntity(body, status);
}

這兩個(gè)方法的共同點(diǎn)是: 他們都調(diào)用了 this.getErrorAttributes(…) 方法來獲取響應(yīng)信息.

然后來看看他默認(rèn)情況下對于 AJAX 請求和 HTML 請求, 分別的返回結(jié)果是怎樣的:

SpringBoot統(tǒng)一異常處理的示例分析

SpringBoot統(tǒng)一異常處理的示例分析 

對于返回錯(cuò)誤頁面, 其中還調(diào)用了一個(gè)非常重要的方法: this.resolveErrorView(...) 方法, 源碼我就不帶大家看了, 他的作用就是根據(jù) HTTP 狀態(tài)碼來去找錯(cuò)誤頁面, 如 500 錯(cuò)誤會(huì)去找 /error/500.html, 403 錯(cuò)誤回去找 /error/403.html, 如果找不到則再找 /error/4xx.html 或 /error/5xx.html 頁面. 還找不到的話, 則會(huì)去找 /error.html 頁面, 如果都沒有配置, 則會(huì)使用 Spring Boot 默認(rèn)的頁面. 即:

SpringBoot統(tǒng)一異常處理的示例分析

看到這里, 應(yīng)該就清楚了, 我們主要需要做四件事:

  • 發(fā)送異常后, 重定向到 BasicErrorController 來處理 (既然Spring Boot 都已經(jīng)寫好了區(qū)分請求的功能, 我們就不必要再寫這些判斷代碼了)

  • 自定義 HTTP 錯(cuò)誤狀態(tài)碼

  • 他返回的信息格式可能不是我們想要的, 所以必須要改造 getErrorAttributes(...) 方法, 以自定義我們向頁面返回的數(shù)據(jù). (自定義錯(cuò)誤信息)

  • 創(chuàng)建我們自己的 /error/4xx.html 或 /error/5xx.html 等頁面, (自定義錯(cuò)誤頁面)

BasicErrorController

第一點(diǎn)很簡單, BasicErrorController 他處理 /error 請求, 我們只需要將頁面重定向到 /error 即可, 在 ControllerAdvice 中是這樣的:

@ControllerAdvice
public class WebExceptionHandler {

 @ExceptionHandler
 public String methodArgumentNotValid(BindException e) {
 // do something
 return "/error";
 }
}

自定義 HTTP 錯(cuò)誤狀態(tài)碼

我們來看下 this.getStatus(request); 的源碼, 看他原來時(shí)如何獲取錯(cuò)誤狀態(tài)碼的:

protected HttpStatus getStatus(HttpServletRequest request) {
 Integer statusCode = (Integer)request.getAttribute("javax.servlet.error.status_code");
 if (statusCode == null) {
 return HttpStatus.INTERNAL_SERVER_ERROR;
 } else {
 try {
  return HttpStatus.valueOf(statusCode);
 } catch (Exception var4) {
  return HttpStatus.INTERNAL_SERVER_ERROR;
 }
 }
}

簡單來說就是從 request 域中獲取 javax.servlet.error.status_code 的值, 如果為 null 或不合理的值, 都返回 500. 既然如何在第一步, 重定向到 /error 之前將其配置到 request 域中即可, 如:

@ControllerAdvice
public class WebExceptionHandler {

 @ExceptionHandler
 public String methodArgumentNotValid(BindException e, HttpServletRequest request) {
 request.setAttribute("javax.servlet.error.status_code", 400);
 // do something
 return "forward:/error";
 }
}

自定義錯(cuò)誤信息

也就是 getErrorAttributes 方法, 默認(rèn)的代碼是這樣的:

public Map<String, Object> getErrorAttributes(WebRequest webRequest, boolean includeStackTrace) {
 Map<String, Object> errorAttributes = new LinkedHashMap();
 errorAttributes.put("timestamp", new Date());
 this.addStatus(errorAttributes, webRequest);
 this.addErrorDetails(errorAttributes, webRequest, includeStackTrace);
 this.addPath(errorAttributes, webRequest);
 return errorAttributes;
}

他獲取了時(shí)間戳, 錯(cuò)誤狀態(tài)碼, 錯(cuò)誤信息, 錯(cuò)誤路徑等信息, 和我們之前看到默認(rèn)的返回內(nèi)容是一致的:

{
 "timestamp": "2019-01-27T07:08:30.011+0000",
 "status": 500,
 "error": "Internal Server Error",
 "message": "/ by zero",
 "path": "/user/index"
}

同樣的思路, 我們將錯(cuò)誤信息也放到 request 域中, 然后在 getErrorAttributes 中從 request 域中獲取:

@ControllerAdvice
public class WebExceptionHandler {

 @ExceptionHandler
 public String methodArgumentNotValid(BindException e, HttpServletRequest request) {
 request.setAttribute("javax.servlet.error.status_code", 400);
 request.setAttribute("code", 1);
 request.setAttribute("message", "參數(shù)校驗(yàn)失敗, xxx");
 // do something
 return "forward:/error";
 }
}

再繼承 DefaultErrorAttributes 類, 重寫 getErrorAttributes 方法:

//@Component
public class MyDefaultErrorAttributes extends DefaultErrorAttributes {

 @Override
 //重寫 getErrorAttributes方法-添加自己的項(xiàng)目數(shù)據(jù)
 public Map<String, Object> getErrorAttributes(WebRequest webRequest,
       boolean includeStackTrace) {
 Map<String, Object> map = new HashMap<>();
 // 從 request 域中獲取 code
 Object code = webRequest.getAttribute("code", RequestAttributes.SCOPE_REQUEST);
 // 從 request 域中獲取 message
 Object message = webRequest.getAttribute("message", RequestAttributes.SCOPE_REQUEST);
 map.put("code", code);
 map.put("message", message);
 return map;
 }
}

自定義錯(cuò)誤頁面

我們遵循 SpringBoot 的規(guī)則, 在 /error/ 下建立 400.html, 500.html 等頁面細(xì)粒度的錯(cuò)誤, 并配置一個(gè) /error.html 用來處理細(xì)粒度未處理到的其他錯(cuò)誤.

/error/400.html

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
 <meta charset="UTF-8">
 <title>400</title>
</head>
<body>
 <h2>400</h2>
 <h2 th:text="$[code]"></h2>
 <h2 th:text="${message}"></h2>
</body>
</html>

/error/500.html

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
 <meta charset="UTF-8">
 <title>500</title>
</head>
<body>
 <h2>500</h2>
 <h2 th:text="$[code]"></h2>
 <h2 th:text="${message}"></h2>
</body>
</html>

/error.html

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
 <meta charset="UTF-8">
 <title>系統(tǒng)出現(xiàn)了錯(cuò)誤</title>
</head>
<body>
 <h2>ERROR PAGE</h2>
 <h2 th:text="$[code]"></h2>
 <h2 th:text="${message}"></h2>
</body>
</html>

測試效果

到此位置, 大功告成, 然后來創(chuàng)造一個(gè)異常來測試一下效果:

SpringBoot統(tǒng)一異常處理的示例分析

SpringBoot統(tǒng)一異常處理的示例分析

SpringBoot統(tǒng)一異常處理的示例分析

SpringBoot統(tǒng)一異常處理的示例分析

前端 error 處理

現(xiàn)在使用了 HTTP 狀態(tài)碼, 所以 Ajax 請求出現(xiàn)錯(cuò)誤后, 需要在每個(gè) Ajax 請求方法中都寫 error: function() {} 方法, 甚至麻煩. 好在 jQuery 為我們提供了全局處理 Ajax 的 error 結(jié)果的方法 ajaxError() :

$(document).ajaxError(function(event, response){
 console.log("錯(cuò)誤響應(yīng)狀態(tài)碼: ",response.status);
 console.log("錯(cuò)誤響應(yīng)結(jié)果: ",response.responseJSON);
 alert("An error occurred!");
});

以上是“SpringBoot統(tǒng)一異常處理的示例分析”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對大家有所幫助,如果還想學(xué)習(xí)更多知識(shí),歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道!

分享文章:SpringBoot統(tǒng)一異常處理的示例分析
轉(zhuǎn)載源于:http://muchs.cn/article24/gjscje.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站排名、網(wǎng)站收錄、域名注冊、Google、定制開發(fā)、小程序開發(fā)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)

成都網(wǎng)站建設(shè)