如何在SpringBoot中進(jìn)行異常處理

這篇文章將為大家詳細(xì)講解有關(guān)如何在Spring Boot中進(jìn)行異常處理,文章內(nèi)容質(zhì)量較高,因此小編分享給大家做個(gè)參考,希望大家閱讀完這篇文章后對相關(guān)知識有一定的了解。

站在用戶的角度思考問題,與客戶深入溝通,找到環(huán)縣網(wǎng)站設(shè)計(jì)與環(huán)縣網(wǎng)站推廣的解決方案,憑借多年的經(jīng)驗(yàn),讓設(shè)計(jì)與互聯(lián)網(wǎng)技術(shù)結(jié)合,創(chuàng)造個(gè)性化、用戶體驗(yàn)好的作品,建站類型包括:成都網(wǎng)站設(shè)計(jì)、網(wǎng)站建設(shè)、企業(yè)官網(wǎng)、英文網(wǎng)站、手機(jī)端網(wǎng)站、網(wǎng)站推廣、主機(jī)域名、網(wǎng)絡(luò)空間、企業(yè)郵箱。業(yè)務(wù)覆蓋環(huán)縣地區(qū)。

通過這篇文章,可以搞懂如何在 Spring Boot  中進(jìn)行異常處理。但是,光是會用了還不行,我們還要思考如何把異常處理這部分的代碼寫的稍微優(yōu)雅一點(diǎn)。下面我會以我在工作中學(xué)到的一點(diǎn)實(shí)際項(xiàng)目中異常處理的方式,來說說我覺得稍微優(yōu)雅點(diǎn)的異常處理解決方案。

下面僅僅是我作為一個(gè)我個(gè)人的角度來看的,如果各位讀者有更好的解決方案或者覺得本文提出的方案還有優(yōu)化的余地的話,歡迎在評論區(qū)評論。

最終效果展示

下面先來展示一下完成后的效果,當(dāng)我們定義的異常被系統(tǒng)捕捉后返回給客戶端的信息是這樣的:

如何在Spring Boot中進(jìn)行異常處理

效果展示

返回的信息包含了異常下面 5 部分內(nèi)容:

  1. 鴻蒙官方戰(zhàn)略合作共建——HarmonyOS技術(shù)社區(qū)

  2. 唯一標(biāo)示異常的 code

  3. HTTP 狀態(tài)碼

  4. 錯(cuò)誤路徑

  5. 發(fā)生錯(cuò)誤的時(shí)間戳

  6. 錯(cuò)誤的具體信息

這樣返回異常信息,更利于我們前端根據(jù)異常信息做出相應(yīng)的表現(xiàn)。

異常處理核心代碼

ErrorCode.java (此枚舉類中包含了異常的唯一標(biāo)識、HTTP 狀態(tài)碼以及錯(cuò)誤信息)

這個(gè)類的主要作用就是統(tǒng)一管理系統(tǒng)中可能出現(xiàn)的異常,比較清晰明了。但是,可能出現(xiàn)的問題是當(dāng)系統(tǒng)過于復(fù)雜,出現(xiàn)的異常過多之后,這個(gè)類會比較龐大。有一種解決辦法:將多種相似的異常統(tǒng)一為一個(gè),比如將用戶找不到異常和訂單信息未找到的異常都統(tǒng)一為“未找到該資源”這一種異常,然后前端再對相應(yīng)的情況做詳細(xì)處理(我個(gè)人的一種處理方法,不敢保證是比較好的一種做法)。

import org.springframework.http.HttpStatus;   public enum ErrorCode {      RESOURCE_NOT_FOUND(1001, HttpStatus.NOT_FOUND, "未找到該資源"),     REQUEST_VALIDATION_FAILED(1002, HttpStatus.BAD_REQUEST, "請求數(shù)據(jù)格式驗(yàn)證失敗");     private final int code;      private final HttpStatus status;      private final String message;      ErrorCode(int code, HttpStatus status, String message) {         this.code = code;         this.status = status;         this.message = message;     }      public int getCode() {         return code;     }      public HttpStatus getStatus() {         return status;     }      public String getMessage() {         return message;     }      @Override     public String toString() {         return "ErrorCode{" +                 "code=" + code +                 ", status=" + status +                 ", message='" + message + '\'' +                 '}';     } }

ErrorReponse.java(返回給客戶端具體的異常對象)

這個(gè)類作為異常信息返回給客戶端,里面包括了當(dāng)出現(xiàn)異常時(shí)我們想要返回給客戶端的所有信息。

import org.springframework.util.ObjectUtils;  import java.time.Instant; import java.util.HashMap; import java.util.Map;  public class ErrorReponse {     private int code;     private int status;     private String message;     private String path;     private Instant timestamp;     private HashMap<String, Object> data = new HashMap<String, Object>();      public ErrorReponse() {     }      public ErrorReponse(BaseException ex, String path) {         this(ex.getError().getCode(), ex.getError().getStatus().value(), ex.getError().getMessage(), path, ex.getData());     }      public ErrorReponse(int code, int status, String message, String path, Map<String, Object> data) {         this.code = code;         this.status = status;         this.message = message;         this.path = path;         this.timestamp = Instant.now();         if (!ObjectUtils.isEmpty(data)) {             this.data.putAll(data);         }     }  // 省略 getter/setter 方法      @Override     public String toString() {         return "ErrorReponse{" +                 "code=" + code +                 ", status=" + status +                 ", message='" + message + '\'' +                 ", path='" + path + '\'' +                 ", timestamp=" + timestamp +                 ", data=" + data +                 '}';     } }

BaseException.java(繼承自 RuntimeException 的抽象類,可以看做系統(tǒng)中其他異常類的父類)

系統(tǒng)中的異常類都要繼承自這個(gè)類。

public abstract class BaseException extends RuntimeException {     private final ErrorCode error;     private final HashMap<String, Object> data = new HashMap<>();      public BaseException(ErrorCode error, Map<String, Object> data) {         super(error.getMessage());         this.error = error;         if (!ObjectUtils.isEmpty(data)) {             this.data.putAll(data);         }     }      protected BaseException(ErrorCode error, Map<String, Object> data, Throwable cause) {         super(error.getMessage(), cause);         this.error = error;         if (!ObjectUtils.isEmpty(data)) {             this.data.putAll(data);         }     }      public ErrorCode getError() {         return error;     }      public Map<String, Object> getData() {         return data;     }  }

ResourceNotFoundException.java (自定義異常)

可以看出通過繼承 BaseException 類我們自定義異常會變的非常簡單!

import java.util.Map;  public class ResourceNotFoundException extends BaseException {      public ResourceNotFoundException(Map<String, Object> data) {         super(ErrorCode.RESOURCE_NOT_FOUND, data);     } }

GlobalExceptionHandler.java(全局異常捕獲)

我們定義了兩個(gè)異常捕獲方法。

這里再說明一下,實(shí)際上這個(gè)類只需要 handleAppException() 這一個(gè)方法就夠了,因?yàn)樗潜鞠到y(tǒng)所有異常的父類。只要是拋出了繼承  BaseException 類的異常后都會在這里被處理。

import com.twuc.webApp.web.ExceptionController; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; 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;  @ControllerAdvice(assignableTypes = {ExceptionController.class}) @ResponseBody public class GlobalExceptionHandler {      // 也可以將 BaseException 換為 RuntimeException     // 因?yàn)?nbsp;RuntimeException 是 BaseException 的父類     @ExceptionHandler(BaseException.class)     public ResponseEntity<?> handleAppException(BaseException ex, HttpServletRequest request) {         ErrorReponse representation = new ErrorReponse(ex, request.getRequestURI());         return new ResponseEntity<>(representation, new HttpHeaders(), ex.getError().getStatus());     }      @ExceptionHandler(value = ResourceNotFoundException.class)     public ResponseEntity<ErrorReponse> handleResourceNotFoundException(ResourceNotFoundException ex, HttpServletRequest request) {         ErrorReponse errorReponse = new ErrorReponse(ex, request.getRequestURI());         return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(errorReponse);     } }

(重要)一點(diǎn)擴(kuò)展:

哈哈!實(shí)際上我多加了一個(gè)算是多余的異常捕獲方法handleResourceNotFoundException() 主要是為了考考大家當(dāng)我們拋出了  ResourceNotFoundException異常會被下面哪一個(gè)方法捕獲呢?

答案:

會被handleResourceNotFoundException()方法捕獲。因?yàn)?@ExceptionHandler  捕獲異常的過程中,會優(yōu)先找到最匹配的。

下面通過源碼簡單分析一下:

ExceptionHandlerMethodResolver.java中g(shù)etMappedMethod決定了具體被哪個(gè)方法處理。

@Nullable     private Method getMappedMethod(Class<? extends Throwable> exceptionType) {         List<Class<? extends Throwable>> matches = new ArrayList<>();     //找到可以處理的所有異常信息。mappedMethods 中存放了異常和處理異常的方法的對應(yīng)關(guān)系         for (Class<? extends Throwable> mappedException : this.mappedMethods.keySet()) {             if (mappedException.isAssignableFrom(exceptionType)) {                 matches.add(mappedException);             }         }     // 不為空說明有方法處理異常         if (!matches.isEmpty()) {       // 按照匹配程度從小到大排序             matches.sort(new ExceptionDepthComparator(exceptionType));       // 返回處理異常的方法             return this.mappedMethods.get(matches.get(0));         }         else {             return null;         }     }

從源代碼看出:getMappedMethod()會首先找到可以匹配處理異常的所有方法信息,然后對其進(jìn)行從小到大的排序,最后取最小的那一個(gè)匹配的方法(即匹配度最高的那個(gè))。

寫一個(gè)拋出異常的類測試

Person.java

public class Person {     private Long id;     private String name;      // 省略 getter/setter 方法 }

ExceptionController.java(拋出一場的類)

@RestController @RequestMapping("/api") public class ExceptionController {      @GetMapping("/resourceNotFound")     public void throwException() {         Person p=new Person(1L,"SnailClimb");         throw new ResourceNotFoundException(ImmutableMap.of("person id:", p.getId()));     }  }

關(guān)于如何在Spring Boot中進(jìn)行異常處理就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,可以學(xué)到更多知識。如果覺得文章不錯(cuò),可以把它分享出去讓更多的人看到。

本文名稱:如何在SpringBoot中進(jìn)行異常處理
本文URL:http://www.muchs.cn/article8/ghjhip.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供關(guān)鍵詞優(yōu)化、做網(wǎng)站、品牌網(wǎng)站設(shè)計(jì)、Google、網(wǎng)站內(nèi)鏈定制網(wǎng)站

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)

成都定制網(wǎng)站建設(shè)