1. 程式人生 > 實用技巧 >springboot 的異常處理

springboot 的異常處理

背景分析

在專案的開發中,不管是對底層的資料邏輯操作過程,還是業務邏輯的處理過程,還是控制邏輯的處理過程,都不可避免會遇到各種可預知的、不可預知的異常。處理好異常對系統有很好的保護作用,同時會大大提高使用者的體驗。

異常處理分析

概述

Java專案中處理異常方式無非兩種,要麼執行trycatch操作,要麼執行throw操作(拋給其它物件處理),無論採用哪種方式,其目的是讓我們的系統對異常要有反饋。但現在的問題是我們如何讓這種反饋程式碼的編寫即簡單又直觀、友好。

處理規範

我們在處理異常的過程中通常要遵循一定的設計規範,例如:

  • 捕獲異常時與丟擲的異常必須完全匹配,或者捕獲異常是丟擲異常的父類型別。
  • 避免直接丟擲RuntimeException,更不允許丟擲Exception或者Throwable,應使用有業務含義的自定義異常(例如ServiceException)。
  • 捕獲異常後必須進行處理(例如記錄日誌)。如果不想處理它,需要將異常拋給它的呼叫者。
  • 最外層的邏輯必須處理異常,將其轉化成使用者可以理解的內容。
  • 避免出現重複的程式碼(Don’t Repeat Yourself),即DAY原則。

SpringBoot 工程下的異常處理

準備工作

第一步:建立專案或module,並新增web依賴,程式碼如下:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

第二步:修改專案訪問埠為80,例如

server.port=80

第三步:定義Controller類,程式碼如下:

package com.cy.pj.arithmetic.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
public class ArithmeticController {

  @RequestMapping("doCompute/{n1}/{n2}")
  @ResponseBody
  public String doCompute(@PathVariable  Integer n1, 
  @PathVariable Integer n2){
          Integer result=n1/n2;
          return "Result is "+result;
  }
}

第四步啟動專案進行訪問測試

在瀏覽器位址列輸入http://localhost/doCompute/10/2,檢測輸出結果。

Resultis5

預設異常處理

在瀏覽器位址列輸入http://localhost/doCompute/10/0,檢測輸出結果。

對於這樣的預設異常處理(spring boot提供),使用者體驗不太友好,為了呈現更加友好的異常資訊,我們通常要對異常進行自定義處理。

自己try異常處理

在控制層方法中,我們可以進行try catch處理,例如:

  @RequestMapping("doCompute/{n1}/{n2}")
  @ResponseBody
  public String doCompute(@PathVariable  Integer n1, 
  @PathVariable Integer n2){
          try{
          Integer result=n1/n2;
          return "Result is "+result;
          }catch(ArithmeticException e){
          return "exception is "+e.getMessage();
          }
  }
  

一個Controller類中通常會有多個方法,這樣多個方法中都寫try語句進行異常處理會帶來大量重複程式碼的編寫,不易維護。

Controller內部定義異常處理方法

在Controller類中新增異常處理方法,程式碼如下:

@ExceptionHandler(ArithmeticException.class)
@ResponseBody
public String doHandleArithmeticException(ArithmeticException e){
    e.printStackTrace();
    return "計算過程中出現了異常,異常資訊為"+e.getMessage();
}

@ExceptionHandler註解描述的方法為異常處理方法(註解中的異常型別為可處理的異常型別),假如Controller類中的邏輯方法中出現異常後沒有處理異常,則會查詢Controller類中有沒有定義異常處理方法,假如定義了,且可以處理丟擲的異常型別,則由異常處理方法處理異常。

控制層中的全域性異常處理類及方法定義

當專案由多個控制層類中有多個共性異常的處理方法定義時,我們可以將這些方法提取到公共的父類物件中,但是這種方式是一種強耦合的實現,不利於程式碼的維護。我們還可以藉助spring框架中web模組定義的全域性異常處理規範進行實現,例如定義全域性異常處理類,程式碼如下:

package com.cy.pj.common.web;

@RestControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(ArithmeticException.class)
    public String doHandleArithmeticException(ArithmeticException e){
        e.printStackTrace();
        return  "計算過程中出現了異常,異常資訊為"+e.getMessage();
    }
}

其中,@RestControllerAdvice 註解描述的類為全域性異常處理類,當控制層方法中的異常沒有自己捕獲,也沒有定義其內部的異常處理方法,底層預設會查詢全域性異常處理類,呼叫對應的異常處理方法進行異常處理。如圖所示:

總結(Summary)

本小節主要是對springboot中的異常處理機制進行了簡單分析和講解。目的是掌握springboot工程下的異常處理方式,並基於業務的不同進行響應的異常處理。從而有效提高其使用者體驗,加強系統的容錯能力。