1. 程式人生 > >Springboot學習05-自定義錯誤頁面完整分析

Springboot學習05-自定義錯誤頁面完整分析

 Springboot學習06-自定義錯誤頁面完整分析

前言

   接著上一篇部落格,繼續分析Springboot錯誤頁面問題

正文

 

1-自定義瀏覽器錯誤頁面(只要將自己的錯誤頁面放在指定的路徑下即可)

 1-1-Springboot錯誤頁面匹配機制(以404錯誤為例):

  • 1-在模板引擎下:找templates/error/404.html;如果沒有,則繼續匹配
  • 2-在模板引擎下:找templates/error/4XX.html;如果沒有,則繼續匹配
  • 3-在靜態資源下:找static/error/404.html;如果沒有,則繼續匹配
  • 4-匹配最後的“圍牆”:WhiteLevel Erro Page頁面

  1-2-補充說明

 1-3-demo示例

 

 

 

 

 

 

  1-4-簡單自定義頁面的缺陷

  • 1-只能展示Springboot預設的返回資訊:timestamp時間戳;status狀態;error錯誤提示;exception異常物件;message異常訊息等簡單返回資訊;無法返回自定義業務資料

 

2-自定義錯誤的json

 2-1-原始碼分析

//1-自定義Exception
public class DataException extends RuntimeException {

    
public DataException() { super("資料不存在!"); } } //2-自定義handleException方法 @ControllerAdvice public class MyExceptionHandler { @ResponseBody @ExceptionHandler(DataException.class) public Map<String,Object> handleException(Exception e){ Map<String,Object> map = new HashMap<String,Object>(); map.put("code","data error"); map.put("msg",e.getMessage()); return map; } } //3-測試介面 @Controller public class DemoController { @GetMapping(value="test") public String toExceptionPage( ){ throw new DataException(); } }

 

2-2-頁面效果

 2-3-缺點:瀏覽器請求也返回了json資料;不符合期望

 

3-自定義錯誤頁面,自適應瀏覽器請求和客戶端請求

 3-1-原始碼示例

//1-自定義Exception
public class DataException extends RuntimeException {

    public DataException() {
            super("資料不存在!");
    }
}

//2-自定義handleException方法
@ControllerAdvice
public class MyExceptionHandler {

    @ExceptionHandler(DataException.class)
    public String handleException(Exception e, HttpServletRequest request){
        //傳入我們自己的錯誤狀態碼 4xx 5xx,否則就不會進入定製錯誤頁面的解析流程
        request.setAttribute("javax.servlet.error.status_code",500);
        Map<String,Object> map = new HashMap<String,Object>();
        map.put("code","data error");
        map.put("msg",e.getMessage());

        return "forward:/error";

    }
}

 //3-測試介面
@Controller
public class DemoController {
    
@GetMapping(value="test")
    public String toExceptionPage( ){
        throw  new DataException();
    }
}

  3-2-demo示例

  3-3-缺點:雖然已經相容了瀏覽器請求和客戶端請求;但是無法展示業務資料

 

4-自定義頁面終版:自適應瀏覽器請求和客戶端請求,並且允許返回業務資料

 4-1-原始碼解析

//1-自定義ErrorAttributes
@Component
public class MyErrorAttributes extends DefaultErrorAttributes {

  //重寫getErrorAttributes方法-新增自己的專案資料
    public Map<String, Object> getErrorAttributes(WebRequest webRequest, boolean includeStackTrace) {
        Map<String, Object> errorAttributes = super.getErrorAttributes(webRequest,includeStackTrace);

        errorAttributes.put("myName","我不吃番茄");//自定義資料
        errorAttributes.put("myAge","不告訴你");//自定義資料

        return errorAttributes;
    }
}


//2-自定義Exception
public class DataException extends RuntimeException {

    public DataException() {
            super("資料不存在!");
    }
}

//3-自定義handleException方法
@ControllerAdvice
public class MyExceptionHandler {

    @ExceptionHandler(DataException.class)
    public String handleException(Exception e, HttpServletRequest request){
        //傳入我們自己的錯誤狀態碼 4xx 5xx,否則就不會進入定製錯誤頁面的解析流程
        request.setAttribute("javax.servlet.error.status_code",500);//這裡只接受500狀態錯誤
        Map<String,Object> map = new HashMap<String,Object>();
        map.put("code","data error");
        map.put("msg",e.getMessage());
        request.setAttribute("extra", map);//放在request中的資料,在前端頁面中都可以取出來
        return "forward:/error";//並不直接返回檢視名稱或json資料,請求轉發到"/error",讓Springboo按流程處理處理,從而達到自適應瀏覽器請求和客戶端請求;

    }
}

//4-測試介面
@Controller
public class DemoController {
    
@GetMapping(value="test")
    public String toExceptionPage( ){
        throw  new DataException();//主動丟擲一個500錯誤,用於測試
    }
}
//templates/error/5XX.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>自定義頁面 --路徑:templates/error/5XX.html頁面 --優先級別:2</h1>
    <h1>status:[[${status}]]</h1>
    <h2>timestamp:[[${timestamp}]]</h2>
    <h2>exception:[[${exception}]]</h2>
    <h2>myName:[[${myName}]]</h2>
    <h2>myAge:[[${myAge}]]</h2>
    <h2>extra-code:[[${extra.code}]]</h2>
    <h2>extra-msg:[[${extra.msg}]]</h2>
</body>
</html>

 4-2-demo示例