Springboot 錯誤處理機制

来源:https://www.cnblogs.com/thelovelybugfly/archive/2019/08/19/11380446.html
-Advertisement-
Play Games

SpringBoot預設的錯誤處理機制 即我們常見的白色的ErrorPage頁面 瀏覽器發送的請求頭: 如果是其他的請求方式,比如客戶端,則相應一個json數據: 原理;是通過 ErrorMvcAutoConfiguration,錯誤處理的自動配置; 給容器中添加了以下組件 1、DefaultErr ...


SpringBoot預設的錯誤處理機制

即我們常見的白色的ErrorPage頁面

瀏覽器發送的請求頭:

如果是其他的請求方式,比如客戶端,則相應一個json數據:

 原理;是通過 ErrorMvcAutoConfiguration,錯誤處理的自動配置;

給容器中添加了以下組件

1、DefaultErrorAttributes:

幫我們在頁面共用信息;
@Override
    public Map<String, Object> getErrorAttributes(RequestAttributes requestAttributes,
            boolean includeStackTrace) {
        Map<String, Object> errorAttributes = new LinkedHashMap<String, Object>();
        errorAttributes.put("timestamp", new Date());
        addStatus(errorAttributes, requestAttributes);
        addErrorDetails(errorAttributes, requestAttributes, includeStackTrace);
        addPath(errorAttributes, requestAttributes);
        return errorAttributes;
    }

 2、BasicErrorController:處理預設/error請求 

@Controller
@RequestMapping("${server.error.path:${error.path:/error}}")
public class BasicErrorController extends AbstractErrorController {
    
    @RequestMapping(produces = "text/html")//產生html類型的數據;瀏覽器發送的請求來到這個方法處理
    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 ? new ModelAndView("error", model) : modelAndView);
    }

    @RequestMapping
    @ResponseBody    //產生json數據,其他客戶端來到這個方法處理;
    public ResponseEntity<Map<String, Object>> error(HttpServletRequest request) {
        Map<String, Object> body = getErrorAttributes(request,
                isIncludeStackTrace(request, MediaType.ALL));
        HttpStatus status = getStatus(request);
        return new ResponseEntity<Map<String, Object>>(body, status);
    }

 3、ErrorPageCustomizer:

@Value("${error.path:/error}")
    private String path = "/error";  系統出現錯誤以後來到error請求進行處理;(web.xml註冊的錯誤頁面規則)

 4、DefaultErrorViewResolver:

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

    private ModelAndView resolve(String viewName, Map<String, Object> model) {
        //預設SpringBoot可以去找到一個頁面?  error/404
        String errorViewName = "error/" + viewName;
        
        //模板引擎可以解析這個頁面地址就用模板引擎解析
        TemplateAvailabilityProvider provider = this.templateAvailabilityProviders
                .getProvider(errorViewName, this.applicationContext);
        if (provider != null) {
            //模板引擎可用的情況下返回到errorViewName指定的視圖地址
            return new ModelAndView(errorViewName, model);
        }
        //模板引擎不可用,就在靜態資源文件夾下找errorViewName對應的頁面   error/404.html
        return resolveResource(errorViewName, model);
    }

​ 一但系統出現4xx或者5xx之類的錯誤;ErrorPageCustomizer就會生效(定製錯誤的響應規則);就會來到/error請求;就會被BasicErrorController處理;

 1)響應頁面;去哪個頁面是由DefaultErrorViewResolver解析得到的;

protected ModelAndView resolveErrorView(HttpServletRequest request,
      HttpServletResponse response, HttpStatus status, Map<String, Object> model) {
    //所有的ErrorViewResolver得到ModelAndView
   for (ErrorViewResolver resolver : this.errorViewResolvers) {
      ModelAndView modelAndView = resolver.resolveErrorView(request, status, model);
      if (modelAndView != null) {
         return modelAndView;
      }
   }
   return null;
}

2)、如何定製錯誤響應:

  如何定製錯誤的頁面

1)、有模板引擎的情況下;error/狀態碼; 【將錯誤頁面命名為 錯誤狀態碼.html 放在模板引擎文件夾裡面的 error文件夾下】,發生此狀態碼的錯誤就會來到 對應的頁面;

​ 我們可以使用4xx和5xx作為錯誤頁面的文件名來匹配這種類型的所有錯誤,精確優先(優先尋找精確的狀態碼.html);

​ 頁面能獲取的信息;

​ timestamp:時間戳

​ status:狀態碼

​ error:錯誤提示

​ exception:異常對象

​ message:異常消息

​ errors:JSR303數據校驗的錯誤都在這裡

​ 2)、沒有模板引擎(模板引擎找不到這個錯誤頁面),靜態資源文件夾下找;

​ 3)、以上都沒有錯誤頁面,就是預設來到SpringBoot預設的錯誤提示頁面;

如何定製錯誤的json數據;

Controller.MyExceptionHandler

package com.project.javasystem.Controller;

import com.project.javasystem.exception.UserNotExistException;
import org.springframework.http.HttpRequest;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;

@ControllerAdvice
public class MyExceptionHandler {

  //方法一:
    //瀏覽器,客戶端都返回的是Json數據
   /* @ResponseBody//響應json數據
    @ExceptionHandler(UserNotExistException.class)
    public Map<String,Object> handleException(Exception e){
        Map<String,Object>map = new HashMap<>();
        map.put("code:","User.notExit");
        map.put("message:",e.getMessage());
        return map;
    }*/

  //方法二:自適應效果
    @ExceptionHandler(UserNotExistException.class)
    public String handleException(Exception e,HttpServletRequest request){
        Map<String,Object>map = new HashMap<>();
        //傳入自定義的狀態碼
        /*Integer statusCode = (Integer)request.getAttribute("javax.servlet.error.status_code");*/
        request.setAttribute("javax.servlet.error.status_code",500);
        map.put("code:","User.NotExit");
        map.put("message:","用戶出錯啦");
        //轉發到error進行自適應處理
        request.setAttribute("MyError",map);
        //轉發到error
        return "forward:/error";
    }
}

 

3)、將我們的定製數據攜帶出去;

出現錯誤以後,會來到/error請求,會被BasicErrorController處理,響應出去可以獲取的數據是由getErrorAttributes得到的(是AbstractErrorController(ErrorController)規定的方法);

​ 1、完全來編寫一個ErrorController的實現類【或者是編寫AbstractErrorController的子類】,放在容器中;

​ 2、頁面上能用的數據,或者是json返回能用的數據都是通過errorAttributes.getErrorAttributes得到;

​ 容器中DefaultErrorAttributes.getErrorAttributes();預設進行數據處理的;

自定義ErrorAttributes

Component.MyErrorAttributes

package com.project.javasystem.Component;

import org.springframework.boot.web.servlet.error.DefaultErrorAttributes;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.WebRequest;
import java.util.Map;


@Component
public class MyErrorAttributes  extends DefaultErrorAttributes {

    //返回值 map中就是頁面和json能獲取的所有欄位
    @Override
    public Map<String, Object> getErrorAttributes(WebRequest webRequest, boolean includeStackTrace) {
        Map<String, Object> map = super.getErrorAttributes(webRequest,includeStackTrace);
        map.put("CompanyName","517NA");
        // 異常處理器攜帶的數據
        Map<String,Object>MyError = (Map<String, Object>) webRequest.getAttribute("MyError", 0);
        map.put("MyError",MyError);
        return map;
    }
}

 

最終的效果:響應是自適應的,可以通過定製ErrorAttributes改變需要返回的內容,

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • SpringMVC 原理 設計原理、啟動過程、請求處理詳細解讀 目錄 "一、 設計原理" "二、 啟動過程" "三、 請求處理" 一、 設計原理 Servlet 規範 SpringMVC 是基於 Servlet 的。 Servlet 是運行在 web 伺服器上的程式,它接收並響應來自 web 客戶端 ...
  • Django自定義分頁並保存搜索條件 1、自定義分頁組件pagination.py 2、view視圖 3、templates模板 4、頁面展示 ...
  • 什麼是內置函數? 就是Python中已經寫好了的函數,可以直接使用 內置函數圖表: 以3.6.2為例 ...
  • Spring boot 應用可以添加依賴 來構建響應式 Web 應用程式。 內置響應式伺服器 Spring Boot WebFlux 內置 Reactor Netty、Tomcat、Jetty 和 Undertow。預設埠是 8080。 WebFlux 的 CRUD 示例 Springboot W ...
  • 從迴圈說起 順序 , 分支 , 迴圈 是編程語言的三大邏輯結構,在Python中都得到了支持,而Python更是為迴圈結構提供了非常便利的語法: 剛從C語言轉入Python的同學可能傾向於寫索引下標式的迴圈,例如下麵的代碼像遍歷C中的數組一樣遍歷了一個Python中的列表: 但如果將列表(list) ...
  • 一、引用類型 1.String是sun在JAVASE中提供的字元串類型 2.String.class字碼 3.String是引用數據類型,s是變數名,“abc”是字面值; 二、三元運算符 1.語法規則:布爾表達式 ? 表達式1:表達式2 2.三元運算符執行原理 當布爾表達式的結果為true時,選擇表 ...
  • Spring是以Ioc和Aop為內核,提供了表現層spring MVC 和持久層Spring JDBC等眾多應用技術,還能整合開源世界眾多著名的第三方框架和類庫,成為使用最多的JavaEE企業應用開源框架。 Spring的優勢: Spring的體繫結構:全部基於核心容器Core Container ...
  • 參數明細 查看大圖 ThreadPoolExecutor執行順序: 線程池按以下行為執行任務 當線程數小於核心線程數時,創建線程。 當線程數大於等於核心線程數,且任務隊列未滿時,將任務放入任務隊列。 當線程數大於等於核心線程數,且任務隊列已滿 若線程數小於最大線程數,創建線程 若線程數等於最大線程數 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...