1. 程式人生 > >SpringBoot-定製錯誤頁面

SpringBoot-定製錯誤頁面

錯誤頁面

1. 檔案路徑

classpath:templates/error:模板存放地址

classpath:static/error:靜態頁面存放地址

  • 無需額外配置,Spring-Boot自動識別
  • 檔名error,沒有需要手動建立
  • spring.server.error.path配置可以替換error,看情況配置
  • 優先採用模板,沒有再找靜態資料夾

2. 檔案格式

  • 指定錯誤頁
# 404跳轉頁面
404.html
# 500跳轉頁面
500.html

檔名格式:code.html

  • 預設錯誤頁
# 4XX錯誤統一錯誤頁面
4xx.html
# 5xx錯誤統一頁面
5xx.html
  • 有詳細錯誤頁面404.html,優先採用詳細錯誤頁面,沒有則採用4xx.html
  • 40x.html之類的沒試過,可以看看行不行

3. 自動路由

存在錯誤頁面就行了,多餘的不需要再進行配置,能夠直接生效。

4. 模板渲染

  • 靜態頁面

    不論是classpath:static或者classpath:templates都能夠被系統對映並利用。

  • 模板渲染

    但是系統為模板注入了幾個錯誤的顯示資訊:

    • timestamp:時間戳
    • status:狀態碼
    • error:錯誤資訊
    • exception:異常物件
    • message:提示資訊
    • errors:JSR303

    當採用模板編寫錯誤頁面時,可以直接引入這些已經注入的錯誤資訊。

    但是如果錯誤頁面在classpath:static靜態資料夾下的話,是取不到這些資訊的。

5. 預設提示

​ 如果都沒有配置,那就是Spring-Boot自己的預設提示頁了。

錯誤資料

1. 自定義異常

public class MyException extends Exception{
    public MyException(){
        super("MyException");
    }
}

2. json輸出

@ControllerAdvice
public class MyHandlerException {
    @ResponseBody
    @ExceptionHandler(MyException.class)
    public
Map<String,Object> handlerException(Exception e){ Map<String ,Object> map = new HashMap<>(); map.put("myMessage","自定義資訊" ); return map; } }

@ControllerAdvice:錯誤跳轉控制器

@ResponseBody:返回內容

@ExceptionHandler:處理的異常類,針對指定異常進行處理

Map:返回資訊,自動放進域內

  • 直接返回的json資訊,只包含自動一內容myMessage
  • Spring-Boot預設資料未注入
  • 瀏覽器和介面訪問都只返回json

3. 適配輸出

@ControllerAdvice
public class MyHandlerException {
    @ExceptionHandler(MyException.class)
    public String handlerException(Exception e, HttpServletRequest request){
        Map<String, Object> map = new HashMap<>();
        map.put("msg","error");
        request.setAttribute("javax.servlet.error.status_code", 400);
        return "redirect:/error";
    }
}

redirect:/error:Spring-Boot自動維護一個BasicErrorController,redirect:/error會轉發到那讓它自動處理

request:BasicErrorcontroller從請求域中識別錯誤型別

javax.servlet.error.status_code:為了讓BasicErrorController能夠識別,需要傳入該屬性,設定錯誤碼

redirect:/error:為了流程完整,再說一遍,轉發BasicErrorController進行處理

  • 轉發BasicErrorController的話,就會自動識別瀏覽器和介面,自動跳轉頁面和返回json
  • 但是攜帶的只有Spring-Boot定製的基本資訊,我們可以修改,但是新增的資訊不回傳達到顯示

4. 資訊攜帶

@Component
public class MyErrorAttributes extends DefaultErrorAttributes {
    @Override
    public Map<String, Object> getErrorAttributes(WebRequest webRequest, boolean includeStackTrace) {
        Map<String, Object> map = super.getErrorAttributes(webRequest, includeStackTrace);
        map.put("add_msg","this is new add msg");
        map.put("company", "godme");
        Map<String, Object> myMessage = (Map<String, Object>) webRequest.getAttribute("myMsg", RequestAttributes.SCOPE_REQUEST);
        map.put("myMessage", myMessage);
        return map;
    }
}

DefaultErrorAttributes:BasicErrorController取的資訊都是從DefaultErrorAttributes中取得,所以需要我們進行注入

company:一般開發的話,總有公司想要注入公司名稱。

webReqeust:這個是從web中去獲取資料的請求物件

getAttribute:從域中獲取資料,需要指定key,和scope儲存的域,從指定域中獲取物件

return:返回的mapBasicErrorController會自動處理的啦,自動寫入json,也會自動注入模板

5. 錯誤糾正

​ 為了方便,一直說的是BasicErrorController,顧名思義,它只是Controller而已。真正的處理不是它,而是路由到的指定處理器。

​ 如果有想法,可以順著邏輯去翻一翻原始碼。

6. 總結梳理

1. 一般配置

  • 頁面位置
    • classpath:templates/error
    • claspath:static/error

模板位置可以配置: spring.server.error.path

  • 檔名稱

    • 錯誤頁面: code.html
    • 預設頁面:nxx.html
  • 模板資料

    • static;無資料注入
    • templates:自動注入資料

    BasicErrorController自動路由

2. 自定資料

  • 定義異常
public class MyException extends Exception{
    public MyException(){
        super("MyException");
    }
}
  • 資訊注入
@ControllerAdvice
public class MyHandlerException {
    @ExceptionHandler(MyException.class)
    public String handlerException(Exception e, HttpServletRequest request){
        Map<String, Object> map = new HashMap<>();
        request.setAttribute("myMessage",e.getMessage());
        request.setAttribute("javax.servlet.error.status_code", 400);
        return "redirect:/error";
    }
}

@ControllerAdvice:異常訪問

ExceptionHandler:異常捕捉

request.setAttribute("myMessage",e.getMessage()):資訊注入

request.setAttribute("javax.servlet.error.status_code", 400):路由標記

  • 資訊提取
@Component
public class MyErrorAttributes extends DefaultErrorAttributes {
    @Override
    public Map<String, Object> getErrorAttributes(WebRequest webRequest, boolean includeStackTrace) {
        Map<String, Object> map = super.getErrorAttributes(webRequest, includeStackTrace);
        map.put("add_msg","this is new add msg");
        map.put("company", "godme");
        Map<String, Object> myMessage = (Map<String, Object>) webRequest.getAttribute("myMsg", RequestAttributes.SCOPE_REQUEST);
        map.put("myMessage", myMessage);
        return map;
    }
}

DefaultErrorAttributes:預設採用資訊

map.put("company", "godme"):注入額外資訊

webRequest.getAttribute("myMsg", RequestAttributes.SCOPE_REQUEST):提取注入資訊

map.put("myMessage", myMessage):新增到處理引數

@Component:別忘記標記,交給Spring

3. 流程總結

  • 三重路由
  1. 頁面訪問
  2. 程式異常處理
  3. 錯誤轉發BasicErrorController
  • 資料注入
  1. 頁面資料不相關
  2. 異常處理時注入新資訊
  3. BasicErrorController提取新資訊並設定
  • 關鍵步驟

    • 入口

    @ControllerAdvice:控制錯誤跳轉

    • 注入

    @ExceptionHandler:處理異常,完成資訊注入錯誤轉發

    • 交由BasicErrorController處理,注意注入錯誤資訊,便於路由
    • 提取

    DefaultErrorAttributes重寫getErrorAttributes

    getErrorAttributes:提取上層注入資訊,注入

    @Component:Spring管理

三種程度

1. 簡單配置

​ 簡單新增頁面,無需配置,利用程度不高,具體資訊無法獲取。

2. 手動修改

​ 自定義資訊,不論訪問方式,都是json返回,無頁面路由,瀏覽器頁面不友好。

3. 嫁接方案

  • 異常攔截
  • 請求轉發

通過攔截異常,把請求轉發BasicErrorController。

利用Spring-Boot自己自動路由功能完成頁面和介面的差異化適配。

  • request.setAttribute
  • DefaultAttributes

通過scope設定域引數,再注入到BasicErrorController中,讓自定義引數得以處理。

本質上來說,三種處理方式如下

  1. 入口提供路由頁面,Spring-Boot自動路由
  2. 手動路由,新引數注入但未適配客戶端
  3. 修改Spring-Boot錯誤路由,提供頁面,手動路由,注入引數

第三種方式關鍵點在於手動路由引數注入

手動路由:讓Spring-Boot自動適配客戶端

引數注入:讓Spring-Boot能夠採用新引數