Spring Boot統一異常處理方案示例

来源:https://www.cnblogs.com/gdwkong/archive/2018/04/29/8969963.html
-Advertisement-
Play Games

本示例以“前後端分離模式”進行演示,調試用的異常信息通過日誌的形式列印出來,代碼並不完整,僅從異常處理進行部分代碼示例。 ...


一、異常處理的原則

1、調用方法的時候返回布爾值來代替返回null,這樣可以 NullPointerException。由於空指針是java異常里最噁心的異常。

2、 catch塊里別不寫代碼。空catch塊是異常處理里的錯誤事件,因為它只是捕獲了異常,卻沒有任何處理或者提示。通常你起碼要列印出異常信息,當然你最好根據需求對異常信息進行處理。

3、能拋受控異常(checked Exception)就儘量不拋受非控異常(unchecked Exception[Error或者RuntimeException的異常])。通過去掉重覆的異常處理代碼,可以提高代碼的可讀性。

4、 絕對不要讓你的資料庫相關異常顯示到客戶端。由於絕大多數資料庫和SQLException異常都是受控異常,在Java中,你應該在DAO層把異常信息處理,然後返回處理過的能讓用戶看懂並根據異常提示信息改正操作的異常信息。

5、 在Java中,一定要在資料庫連接,資料庫查詢,流處理後,在finally塊中調用close()方法。

二、示例說明

本示例以“前後端分離模式”進行演示,調試用的異常信息通過日誌的形式列印出來,代碼並不完整,僅從異常處理進行部分代碼示例。

1、創建異常類

 1 @Getter //通過lombok插件實現省寫setter或者getter方法
 2 public class SellException extends RuntimeException {
 3 
 4     private Integer code;
 5     private String message;
 6 
 7     public SellException(ResultEnum resultEnum) {
 8         super(resultEnum.getMessage());
 9         this.code = resultEnum.getCode();
10     }
11 
12     public SellException(Integer code,String message) {
13         this.code = code;
14         this.message = message;
15     }
16 }

2、使用Handler類捕獲異常,統一格式返回給前端

 1 @ControllerAdvice
 2 public class SellExceptionHandler {
 3 
 4     @ExceptionHandler(value = SellException.class)
 5     @ResponseBody
 6     public ResultVO handlerSellerException(SellException e){
 7         return ResultVOUtil.error(e.getCode(),e.getMessage());
 8     }
 9 
10 }

  統一格式類:

 1 public class ResultVOUtil {
 2 
 3     public static ResultVO success(Object object) {
 4         ResultVO resultVO = new ResultVO();
 5         resultVO.setData(object);
 6         resultVO.setCode(0);
 7         resultVO.setMsg("成功");
 8         return resultVO;
 9     }
10 
11     public static ResultVO success() {
12         return success(null);
13     }
14 
15     public static ResultVO error(Integer code,String msg) {
16         ResultVO resultVO = new ResultVO();
17         resultVO.setCode(code);
18         resultVO.setMsg(msg);
19         return resultVO;
20     }
21 
22 }
 1 @Data
 2 public class ResultVO<T> implements Serializable{
 3 
 4     private static final long serialVersionUID = 8960474786737581150L;
 5 
 6     /**
 7      * 錯誤碼
 8      */
 9     private Integer code;
10     /**
11      *提示信息
12      */
13     private String msg;
14     /**
15      * 具體內容
16      */
17     private T data;
18 
19 }

3、異常的信息通過枚舉統一定義,方便定義管理

 1 @Getter
 2 public enum ResultEnum {
 3 
 4     SUCCESS(0,"成功"),
 5 
 6     PARAM_ERROR(1,"參數不正確"),
 7 
 8     PRODUCT_NOT_EXIST(10,"商品不存在"),
 9 
10     PRODUCT_STOCK_ERROR(11,"商品庫存不正確"),
11 
12     ORDER_NOT_EXIST(12,"訂單不存在"),
13 
14     ORDERDETAIL_NOT_EXIST(13,"訂單詳情不存在"),
15 
16     ORDER_STATUS_ERROR(14,"訂單狀態不正確"),
17 
18     ORDER_UPDATE_FAIL(15,"訂單更新失敗"),
19 
20     ORDER_DETAIL_EMPTY(16,"訂單詳情為空"),
21 
22     CART_EMPTY(18,"購物車為空"),
23 
24     ORDER_OWNER_ERROR(19,"該訂單不屬於當前用戶"),
25     ;
26 
27     private Integer code;
28     private String message;
29 
30     ResultEnum(Integer code, String message) {
31         this.code = code;
32         this.message = message;
33     }
34 
35 }

4、使用異常類

① controller層處理頁面傳來參數的校驗,如參數不正確,拋出自定義異常,由handler捕獲返回給頁面。

 1 @RestController
 2 @RequestMapping("/buyer/order")
 3 @Slf4j
 4 public class BuyerOrderController {
 5 
 6     @Autowired
 7     private OrderService orderService;
 8 
 9     @Autowired
10     private BuyerService buyerService;
11 
12     //創建訂單
13     @PostMapping("/create")
14     public ResultVO<Map<String,String>> create(@Valid OrderForm orderForm,
15                                                BindingResult bindingResult){
16         if (bindingResult.hasErrors()){
17             log.error("[創建訂單] 參數不正確,orderForm={}",orderForm);
18             throw new SellException(ResultEnum.PARAM_ERROR.getCode(),
19                     bindingResult.getFieldError().getDefaultMessage());
20         }
21         OrderDTO orderDTO = OrderForm2OrderDTOConverter.convert(orderForm);
22         if (CollectionUtils.isEmpty(orderDTO.getOrderDetailList())){
23             log.error("[創建訂單] 購物不能為空");
24             throw new SellException(ResultEnum.CART_EMPTY);
25         }
26 
27         OrderDTO createResult = orderService.create(orderDTO);
28         Map<String,String> map = new HashMap<>();
29         map.put("orderId",createResult.getOrderId());
30 
31         return ResultVOUtil.success(map);
32 
33     }
34     //訂單列表
35     @GetMapping("/list")
36     public ResultVO<List<OrderDTO>> list(@RequestParam("openid") String openid,
37                                          @RequestParam(value = "page",defaultValue = "0") Integer page,
38                                          @RequestParam(value = "size",defaultValue = "10") Integer size){
39         if (StringUtils.isEmpty(openid)){
40             log.error("[查詢訂單列表] openid為空");
41             throw new SellException(ResultEnum.PARAM_ERROR);
42         }
43         PageRequest request = new PageRequest(page, size);
44         Page<OrderDTO> orderDTOPage = orderService.findList(openid, request);
45 
46         return ResultVOUtil.success(orderDTOPage.getContent());
47     }
48 
49     //訂單詳情
50     @GetMapping("/detail")
51     public ResultVO<OrderDTO> detail(@RequestParam("openid") String openid,
52                                      @RequestParam("orderId") String orderId){
53 
54         OrderDTO orderDTO = buyerService.findOrderOne(openid, orderId);
55         return ResultVOUtil.success(orderDTO);
56     }
57 
58     //取消訂單
59     @PostMapping("/cancel")
60     public ResultVO<OrderDTO> cancel(@RequestParam("openid") String openid,
61                                      @RequestParam("orderId") String orderId) {
62 
63         buyerService.cancelOrderOne(openid, orderId);
64         return ResultVOUtil.success();
65     }
66 }

② service處理返回的結果的異常,拋出自定義異常,由handler捕獲返回給頁面。

 1 @Service
 2 @Slf4j
 3 public class BuyerServiceImpl implements BuyerService {
 4 
 5     @Autowired
 6     private OrderService orderService;
 7 
 8     @Override
 9     public OrderDTO findOrderOne(String openid, String orderId) {
10        return checkOrderOwner(openid, orderId);
11     }
12 
13     @Override
14     public OrderDTO cancelOrderOne(String openid, String orderId) {
15         OrderDTO orderDTO = checkOrderOwner(openid, orderId);
16         if (orderDTO == null){
17             log.error("[取消訂單] 查不到該訂單,orderDTO={}",orderId);
18             throw new SellException(ResultEnum.ORDER_NOT_EXIST);
19         }
20         return orderService.cancel(orderDTO);
21     }
22 
23     private OrderDTO checkOrderOwner(String openid, String orderId) {
24         OrderDTO orderDTO = orderService.findOne(orderId);
25         if (orderDTO == null){
26             return null;
27         }
28         if (!orderDTO.getBuyerOpenid().equalsIgnoreCase(openid)){
29             log.error("[查詢訂單] 訂單的openid不一致,openid={},orderDTO={}",openid,orderDTO);
30             throw new SellException(ResultEnum.ORDER_OWNER_ERROR);
31         }
32         return orderDTO;
33     }
34 
35 }

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 區塊類用 JavaScript 寫出來大致的樣子: 創造一個鏈Blockchain 類中將區塊鏈接起來 使用區塊鏈 區塊鏈是不可變的。一旦添加,區塊就不可能再變更了。在這裡可以試一下。 以上僅僅是一個簡單的區塊鏈工作原理 ...
  • js代碼 把代碼直接放到需要放的位置即可 效果 ...
  • 什麼是腳本語言? ①腳本語言介於HTML和C,C++,Java,C#等編程語言之間 ②腳本語言與編程語言有相似地方,其函數與編程語言類似,也有變數。與編程語言之間最大的區別是編程語言的語法和規則更為嚴格和複雜一些. ③腳本語言是一種解釋性語言,例如Python、vbscript,javascript ...
  • Nginx與瀏覽器緩存 一、瀏覽器對緩存的處理:Internet選項 ★ 控制請求伺服器策略:是忽略資源的緩存策略的情況下額外強制請求伺服器的意思。 ★ 檢查存儲的頁面較新版本 1.每次訪問網頁時 不管是否有緩存、資源狀態是否過期,都會再次請求伺服器。 2.每次啟動Internet Explorer ...
  • ghostinit.php 用法: ghostwu@dev:~/php/php1/10$ ls ghost ghostinit.php ghostwu@dev:~/php/php1/10$ ./ghost init pls input project name? hello pls input au ...
  • Description 某天,Lostmonkey發明瞭一種超級彈力裝置,為了在他的綿羊朋友面前顯擺,他邀請小綿羊一起玩個游戲。游戲一開始,Lostmonkey在地上沿著一條直線擺上n個裝置,每個裝置設定初始彈力繫數ki,當綿羊達到第i個裝置時,它會往後彈ki步,達到第i+ki個裝置,若不存在第i+ ...
  • 實現一個功能即在站內搜索的時候敲入空格和沒有輸入的時候不會進行模糊搜索 ...
  • 嗨,我最親愛的伙計們,很高興我們又見面了。 首先先感謝朋友們的關註。當然我更希望認識與電腦相關的領域的朋友咱們一起探討交流。重點說一下,我是真人,不是那些扒文章的自媒體組織,大家可以相互交流的! 本篇文章我們來講一下關於AI相關的人臉追蹤,人臉識別相關的一些知識。當然本篇教程為(上)部分,講一下利 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...