1. 程式人生 > >SpringBoot全域性異常處理與定製404頁面

SpringBoot全域性異常處理與定製404頁面

一、錯誤處理原理分析

使用SpringBoot建立的web專案中,當我們請求的頁面不存在(http狀態碼為404),或者器發生異常(http狀態碼一般為500)時,SpringBoot就會給我們返回錯誤資訊。

也就是說,在SpringBoot的web專案中,會自動建立一個/error的錯誤介面,來返回錯誤資訊。但是針對不同的訪問方式,會有以下兩種不同的返回資訊。這主要取決於你訪問時的http頭部資訊的Accept這個值來指定你可以接收的型別有哪些

  • 使用瀏覽器訪問時的頭資訊及其返回結果
Accept: text/html

  • 使用其他裝置,如手機客戶端等訪問時頭部資訊及其返回結果(一般是在前後端分離的架構中)
Accept: */*

二、進行錯誤處理

處理異常主要有兩種方式:

1. 使用SpringBoot的自動配置原理進行異常處理

SpringBoot自動配置了一個類ErrorMvcAutoConfiguration來處理處理異常,有興趣的可以去看一下,然後在這個類中定義一個錯誤的BasicErrorController類,主要程式碼有如下:

@Controller
@RequestMapping({"${server.error.path:${error.path:/error}}"})
public class BasicErrorController extends AbstractErrorController {

  	/**
  	 * 錯誤的頁面響應 
  	 */
    @RequestMapping(produces = {"text/html"})
    public ModelAndView errorHtml(HttpServletRequest request, HttpServletResponse response) {
        HttpStatus status = this.getStatus(request);
        Map<String, Object> model = Collections.unmodifiableMap(this.getErrorAttributes(request, this.isIncludeStackTrace(request, MediaType.TEXT_HTML)));
        response.setStatus(status.value());
      	// 得到一個modelAndView物件
        ModelAndView modelAndView = this.resolveErrorView(request, response, status, model);
        return modelAndView != null ? modelAndView : new ModelAndView("error", model);
    }
		
  /**
   * 錯誤的json響應
   */
    @RequestMapping
    public ResponseEntity<Map<String, Object>> error(HttpServletRequest request) {
        HttpStatus status = this.getStatus(request);
        if (status == HttpStatus.NO_CONTENT) {
            return new ResponseEntity(status);
        } else {
            Map<String, Object> body = this.getErrorAttributes(request, this.isIncludeStackTrace(request, MediaType.ALL));
            return new ResponseEntity(body, status);
        }
    }
}

多的程式碼就不深究了,感興趣的可以去看一下。上邊的程式碼也就是說,針對不同的請求方式,會返回不同的結果,其關鍵在於 @RequestMapping註解的produces = {"text/html"}屬性上

1)、返回一個錯誤頁面,如404、500等。

  • 有模板引擎的情況(可以用於渲染頁面)

專案中使用的了模板引擎,如:thymeleaf 、freemarker等做為頁面的渲染時。在templates建立/error資料夾並新增錯誤的狀態碼對應的.html檔案,如下圖:

這裡的404和500就是確定的錯誤狀態碼,而4xx表示其他的4開頭的錯誤,如400,401等。當然可以為每一個狀態碼都設定對應的錯誤頁面,但是這樣做,並沒有什麼好處,所以就直接使用4xx.html這樣的泛指代替了。

可以在我們錯誤頁面中獲取到如下資訊(就是ModelAndView物件中的內容):

欄位名 說明
timstamp 時間戳
status 錯誤狀態碼
error 錯誤提示
exception 異常物件
message 異常訊息
path 頁面路徑

細心的小夥伴會發現,這個其實就是當你用手機請求時返回的json內容

比如:在程式碼中加入上邊資訊,然後在在後端寫一個錯誤程式碼:

@RequestMapping("haserror")
@ResponseBody
public Object myError(){
  int i =10/0;
  return "something is error";
}
這是一個錯誤頁面:
<ul>
    <li>錯誤狀態碼:[[${status}]]</li>
    <li>錯誤訊息:[[${error}]]</li>
    <li>異常物件:[[${exception}]]</li>
    <li>異常訊息:[[${message}]]</li>
    <li>當前時間:[[${timestamp}]]</li>
</ul>

  • 沒有模板引擎的情況

當專案中沒有使用模板引擎的時候,就將整個error資料夾移到static資料夾下就可以了。

不過此時並不能獲取上邊的那些資訊了,因為這本就是靜態資源,沒有模板引擎進行渲染

2)、返回對應的json串

這個並沒有什麼好說的,返回的就是一個json字串。格式如下:

{
"timestamp": "2020-04-22T16:13:37.506+0000",
"status": 500,
"error": "Internal Server Error",
"message": "/ by zero",
"path": "/hello/haserror",
"reason": "完了,你寫的程式碼又產生了一次線上事故"
}

3)、自定義頁面返回資訊

這才是最重要的內容,因為這個資訊不僅是做為json返回的,也是可以在上邊的錯誤頁面中拿到,也可以直接返回一個json。其實也很簡單,就是在Spring容器中新增一個ErrorAttributes物件就可以了,這裡我選擇繼承它的一個子類。

@Component
public class MyErrorAttributes extends DefaultErrorAttributes {
    @Override
    public Map<String, Object> getErrorAttributes(WebRequest webRequest, boolean includeStackTrace) {
        //呼叫父類的方法,會自動獲取內建的那些屬性,如果你不想要,可以不呼叫這個
        Map<String, Object> errorAttributes = super.getErrorAttributes(webRequest, includeStackTrace);

        //新增自定義的屬性
        errorAttributes.put("reason","完了,你寫的程式碼又產生了一次線上事故");
        // 你可以看一下這個方法的引數webRequest這個物件,我相信你肯定能發現好東西

        return errorAttributes;
    }
}

這就可以了,用兩種請求方式分別測試一個我們的這個自定義屬性是否可用:

2. 使用AOP的異常通知進行處理(推薦)

它的原理就是獲取一個全域性的異常通知,然後進行處理。我們只需要在專案中寫下邊程式碼就可以了(其實上邊也只是寫了一個自定義異常資訊的類)

@ControllerAdvice
public class ErrroAcvice {

    /**
     * 全域性捕獲異常的切面類
     * @param request 請求物件,可不傳
     * @param response 響應物件,可不傳
     * @param e 異常類(這個要和你當前捕獲的異常類是同一個)
     */
    @ExceptionHandler(Exception.class) //也可以只對一個類進行捕獲
    public void errorHandler(HttpServletRequest request, HttpServletResponse response,Exception e){
      	/*
      	 * You can do everything you want to do
         * 這裡你拿到了request和response物件,你可以做任何你想做的事
         * 比如:
         *	1.用request從頭資訊中拿到Accept來判斷是請求方可接收的型別從而進行第一個方法的判斷
         *	2.如果你也想返回一個頁面,使用response物件進行重定向到自己的錯誤頁面就可以了
         *  3.你甚至還拿到了異常物件
      	 */
      
        String accept = request.getHeader("Accept");
				// 根據這個字串來判斷做出什麼響應	
      
        try {
            response.setStatus(500);
            response.getWriter().write("hello");
        } catch (IOException ex) {
            ex.printStackTrace();
        }
      
    }
}

3. 兩種方法對比:

  • 第一種方法,就是在當前專案中放置一些錯誤狀態碼的頁面讓SpringBoot去查詢。也支援自定義返回的錯誤資訊
  • 第二種方法,就是直接使用AOP的思想,進行異常通知處理,自由性很大。
  • 我個人建議使用第二種方法,因為自由度很高,可以根據自己的業務邏輯進行隨時改變,而且還有一個很大的用處。下一篇文章會有個很好的例子
  • 使用了第二種方式後,通過第一種方式放置的錯誤頁面和自定義錯誤資訊全部失效

三、程式碼地址:

關注微信公眾號:小魚與Java,後臺回覆"2000"獲取

相關推薦

SpringBoot全域性異常處理定製404頁面

一、錯誤處理原理分析 使用SpringBoot建立的web專案中,當我們請求的頁面不存在(http狀態碼為404),或者器發生異常(http狀態碼一般為500)時,SpringBoot就會給我們返回錯誤資訊。 也就是說,在SpringBoot的web專案中,會自動建立一個/error的錯誤介面,來返回錯誤資訊

springboot全域性異常處理(包含404錯誤處理) 一:解決spring boot中rest介面404,500等錯誤返回統一的json格式(備用地址) 二:SpringBoot入門——區域性全域性異常處理(備用地址)

個人整理參考文件: 一:解決spring boot中rest介面404,500等錯誤返回統一的json格式(備用地址) 二:SpringBoot入門——區域性與全域性的異常處理(備用地址) 三:SpringBoot全域性異常處理(備用地址) 四:sprin

springboot全域性異常處理ControllerAdvice示例區分方法返回型別json還是頁面

如果返回是json,收到異常則返回預設的異常包裝型別 如果返回是頁面,收到異常則返回預設的異常頁面 判斷返回型別的實現方法是,加一個攔截器,在preHandler中取得HandlerMethod,判斷其方法的返回型別,以及方法的註解和類的註解 import java.lang.refle

Spring Boot 全域性異常處理 Hibernate Validator校驗框架整合

Hibernate Validator校驗框架的使用 Spring boot已經集成了hibernate-validator,不需要引入maven,其他框架也可以自己引入: <dependency> <groupId>org.h

springboot全域性異常處理

在spring 3.2中,新增了@ControllerAdvice 註解,可以用於定義@ExceptionHandler、@InitBinder、@ModelAttribute,並應用到所有@RequestMapping中。參考:@ControllerAdvi

Springboot異常處理自定義異常

園友們好,元旦很快就到來了,提前祝各位園友們元旦快樂,今天給大家分享一個工作中必用一個知識點,就是使用列舉構建自定義異常並應用於springboot的異常處理器。開始之前我先把這個案例的結構大致說明一下: 1、使用idea建立一個springboot的Gradle/Maven專案,引入web模組即可(由於案

Java程式設計中Springboot異常處理自定義異常處理教程

元旦很快就到來了,提前祝各位元旦快樂,今天給大家分享一個工作中必用一個知識點,就是在Java開發中使用列舉構建自定義異常並應用於springboot的異常處理器。 開始之前我先把這個案例的結構大致說明一下: 1、使用idea建立一個springboot的Gradle/Maven專案,引入we

如何優雅的處理異常?SpringBoot全域性異常資料校驗

要思考的問題 在現在的前後端互動中,通常都規範了介面返回方式,如返回的介面狀態(成功|失敗)以及要返回的資料在那個欄位取,或者說失敗了以後提示資訊從介面哪裡返回,因此,如果想做全域性異常,並且異常發生後能準確的返回給前端解析,那麼需要異常發生時返回給前端的格式與正常失敗場景的格式一致。

SpringBoot基於@ControllerAdvice配置全域性異常處理

SpringBoot預設全域性異常處理 SpringBoot提供了一個預設的對映:/error,當處理中丟擲異常之後,會轉到請求中處理,並且該請求有一個全域性的錯誤頁面用來展示異常內容。 啟動訪問一個異常的url出現的呈現的頁面情況是這樣的: 但是這樣的頁面我們也覺得不太友好

springboot(3)——整合freemarker模板、AOP統一處理全域性異常處理

《三》、整合freemarker模板、AOP統一處理、全域性異常處理 一、整合freemarker模板引擎 1、引入freemarker依賴 <dependency> <groupId>org.springframe

SpringBoot全域性異常資料校驗

異常處理是每個專案中都繞不開的話題,那麼如何優雅的處理異常,是本文的話題。本文將結合SpringBoot框架一起和大家探討下。 要思考的問題 在現在的前後端互動中,通常都規範了介面返回方式,如返回的介面狀態(成功|失敗)以及要返回的資料在那個欄位取,或者說失敗了以後提示資訊從介面哪裡返回,因

springmvc、 springboot 專案全域性異常處理

異常在專案中那是不可避免的,通常情況下,我們需要對全域性異常進行處理,下面介紹兩種比較常用的情況。 準備工作: 在捕獲到異常的時候,我們通常需要返回給前端錯誤碼,錯誤資訊等,所以我們需要手動封裝一個jsonData物件,這裡為了方便,我直接通過返回布林型別來進行判斷成功或失敗,在實際的專案中

SpringBoot全域性異常捕獲及處理(包括自定義異常捕獲處理

在做專案的時候需要對自定義異常做捕獲和處理,現在將程式碼記錄下來便於以後查閱。 1、全域性異常捕捉處理 @ControllerAdvice( annotations = {RestController.class} ) public class ExceptionHandlerAdv

springboot區域性及全域性異常處理

區域性異常處理 對TestController類進行操作 (1)、創造異常點 如果設定一個變數=整數/0,則會發生ArithmeticException異常 在TestController中加入除0異常點 @RequestMapping("/hello1") public St

使用SpringBoot通過自定義註解+AOP+全域性異常處理實現引數統一非空校驗

一、前言         在我們寫後臺介面時,難免對引數進行非空校驗,如果一兩個還好,但如果需要寫大量的介面,及必填引數太多的時候,會給我們開發帶來大量的重複工作,及很多相似程式碼。而sping自帶的@RequestParam註解並不能完全滿足我們的需求,因為

springboot基礎篇——全域性異常處理

基於之前的demo:springboot基礎篇——基礎入門 專案結構   一、建立全域性異常處理類 程式碼: package com.springboot.controller; import java.util.HashMap; import java.uti

springboot全域性異常處理和自定義異常以及自定義返回值

1.介紹    全域性異常處理,是mvc的一個新特性,避免大量的重複程式碼    自定義異常 , 方便使用,丟擲自己定義好的異常,配合全域性異常處理使用,效果更佳    自定義返回值,類似異常,返回自己定義的返回值 2.全域性異常處理重點知識 1. 新建一

springboot對springmvc的全域性異常處理

1.application.properties配置中加入: ## global exception ## #出現錯誤時, 直接丟擲異常 spring.mvc.throw-exception-if-no-handler-found=true #不要為我們工程中的資原始檔建立

Spring MVC 全域性異常處理-RESTAPI介面返回統一JSON格式-自定義異常處理--404異常捕捉

寫之前大概兩週草草的將一些程式碼儲存在草稿箱,今天有空來看,結果都沒有了【怨念】—重新整理一下了 —–【轉載請標註出處】 第一部分:需求 第二部分:實現方式 第三部分:404異常捕捉不能實現分析 第四部分:原因和原始碼分析 第五部分:最終總結 需求

SpringBoot系列全域性異常處理

1、介紹 在日常開發中發生了異常,往往是需要通過一個統一的異常處理處理所有異常,來保證客戶端能夠收到友好的提示。SpringBoot在頁面 發生異常的時候會自動把請求轉到/error,SpringBoot內建了一個BasicErrorController對異常