<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          實(shí)戰(zhàn)篇:通用返回值 & 異常處理設(shè)計(jì) | SpringMVC第14篇

          共 12357字,需瀏覽 25分鐘

           ·

          2021-09-04 14:25

          大家好,我是路人,這是 SpringMVC 系列第 14 篇。

          1、本文目的

          目前多數(shù)系統(tǒng)都采用前后端分離的方式,后端只負(fù)責(zé)提供 restfull 接口,返回 json 格式的數(shù)據(jù)就可以了,前端負(fù)責(zé)渲染。

          本文帶大家主要解決 2 個(gè)問題,在 springmvc 提供 json 格式的接口的時(shí)候,需要解決 2 個(gè)問題

          • 問題 1:所有接口的返回值采用統(tǒng)一的格式
          • 問題 2:系統(tǒng)中異常處理設(shè)計(jì)的問題,采用一種非常好的方式來解決這個(gè)問題

          下面咱們一起來解決這 2 個(gè)問題。

          2、解決問題 1:實(shí)現(xiàn)統(tǒng)一的返回值

          所有的接口均返回 ResultDto 類型的數(shù)據(jù),ResultDto 類的代碼如下,主要有 4 個(gè)字段

          • success:表示接口是成功還是失敗
          • code:錯(cuò)誤碼,當(dāng)有異常的時(shí)候,可以返回具體的錯(cuò)誤碼
          • msg:提示信息,比如:操作成功、用戶名有誤、密碼有誤等等
          • data:類型是一個(gè)泛型,表示任意類型,這個(gè)用來存放接口中具體返回的數(shù)據(jù),可以是任意類型的對(duì)象
          • 還提供了幾個(gè)靜態(tài)方法,方便創(chuàng)建 ResultDto 對(duì)象
          /**
           * rest接口通用返回值數(shù)據(jù)結(jié)構(gòu)
           *
           * @param <T>
           */

          public class ResultDto<T{
              //接口狀態(tài)(成功還是失?。?/span>
              private Boolean success;
              //錯(cuò)誤碼
              private String code;
              //提示信息
              private String msg;
              //數(shù)據(jù)
              private T data;

              public Boolean getSuccess() {
                  return success;
              }

              public void setSuccess(Boolean success) {
                  this.success = success;
              }

              public String getCode() {
                  return code;
              }

              public void setCode(String code) {
                  this.code = code;
              }

              public String getMsg() {
                  return msg;
              }

              public void setMsg(String msg) {
                  this.msg = msg;
              }

              public T getData() {
                  return data;
              }

              public void setData(T data) {
                  this.data = data;
              }

              public static <T> ResultDto<T> success(T data) {
                  return success(data, "操作成功!");
              }

              public static <T> ResultDto<T> success(T data, String msg) {
                  ResultDto<T> result = new ResultDto<>();
                  result.setSuccess(Boolean.TRUE);
                  result.setMsg(msg);
                  result.setData(data);
                  return result;
              }

              public static <T> ResultDto<T> error(String msg) {
                  return error(null,msg);
              }
              public static <T> ResultDto<T> error(String code,String msg) {
                 return error(code,msg,null);
              }
              public static <T> ResultDto<T> error(String code, String msg, T data) {
                  ResultDto<T> result = new ResultDto<>();
                  result.setSuccess(Boolean.FALSE);
                  result.setCode(code);
                  result.setMsg(msg);
                  result.setData(data);
                  return result;
              }
          }

          3、解決問題 2:統(tǒng)一處理異常

          3.1、如何做?

          異常處理這塊,我們的設(shè)計(jì)主要有 2 點(diǎn),通過這 2 點(diǎn)來解決異常處理的問題

          • 第一點(diǎn):定義一個(gè)基礎(chǔ)的業(yè)務(wù)異常類(BusException),業(yè)務(wù)代碼中手動(dòng)拋出異常的時(shí)候,統(tǒng)一拋出這種類型的異常,異常類型中可以攜帶更詳細(xì)的錯(cuò)誤信息,比如錯(cuò)誤碼、提示信息、擴(kuò)展數(shù)據(jù)等等
          • 第 2 點(diǎn):采用 springmvc 全局來處理異常,控制器中不要捕獲異常,將一次交給 springmvc 框架來統(tǒng)一處理。

          3.2、具體代碼

          下面我們來看具體的代碼片段,主要有 2 個(gè)類

          業(yè)務(wù)異常類:BusException

          代碼比較簡單,主要有 2 個(gè)屬性和幾個(gè)靜態(tài)方法

          • code:異常錯(cuò)誤碼,最終會(huì)丟給 ResultDto 的 code 屬性輸出到客戶端
          • data:異常的時(shí)候,可以傳遞一些擴(kuò)展信息,此時(shí)可以丟到 data 中,最終會(huì)丟給 ResultDto 的 data 屬性輸出到客戶端
          • 提供了幾個(gè)靜態(tài)方法,便于拋出 BusException 異常
          • 當(dāng)我們的業(yè)務(wù)代碼中需要拋出異常的時(shí)候,要求均拋出 BusException 類型的異常
          /**
           * 業(yè)務(wù)異常
           */

          public class BusException extends RuntimeException {
              //異常錯(cuò)誤碼
              private String code;
              //錯(cuò)誤擴(kuò)展信息
              private Object data;

              public BusException(String msg) {
                  this(null, msg);
              }

              public BusException(String code, String msg) {
                  this(code, msg, null);
              }

              public BusException(String code, String msg, Object data) {
                  super(msg);
                  this.code = code;
                  this.data = data;
              }

              public String getCode() {
                  return code;
              }

              public void setCode(String code) {
                  this.code = code;
              }

              public Object getData() {
                  return data;
              }

              public void setData(Object data) {
                  this.data = data;
              }

              public static void throwBusException(String msg) {
                  throwBusException(null, msg);
              }

              public static void throwBusException(String code, String msg) {
                  throwBusException(code, msg, null);
              }

              public static void throwBusException(String code, String msg, Object data) {
                  throw new BusException(code, msg, data);
              }
          }

          全局異常統(tǒng)一處理類:GlobalExceptionHandle

          如下代碼,大家對(duì) springmvc 統(tǒng)一異常處理不了解,建議先看一下上一篇文章。

          注意下面代碼中的@1,這里使用到了@RestControllerAdvice,這個(gè)注解之前沒有介紹過,他和@ControllerAdvice 功能類似,只是這個(gè)注解內(nèi)部定義的時(shí)候上面多了一個(gè)@ResponseBody 注解,表示下面這個(gè)類中處理異常的方法返回值最終都會(huì)以 json 格式輸出到客戶端

          /**
           * 全局異常處理
           */

          @RestControllerAdvice // @1
          public class GlobalExceptionHandle {
              /**
               * 統(tǒng)一處理業(yè)務(wù)異常
               *
               * @param e
               * @param <T>
               * @return
               */

              @ExceptionHandler(BusException.class)
              public <TResultDto<TdoBusException(BusException e
          {
                  //1、記錄錯(cuò)誤日志
                  //2、返回結(jié)果
                  return ResultDto.error(e.getCode(), e.getMessage(), (T) e.getData());
              }

              /**
               * 處理其他異常
               *
               * @param e
               * @param <T>
               * @return
               */

              @ExceptionHandler
              public <T> ResultDto<T> doException(Exception e) {
                  //1、記錄錯(cuò)誤日志
                  //2、返回結(jié)果
                  return ResultDto.error("系統(tǒng)異常,請(qǐng)聯(lián)系管理員,錯(cuò)誤詳情:" + e.getMessage());
              }
          }

          2 個(gè)問題解決了,下面我們來看看 controller 中如何使用。

          4、Controller 中代碼如何寫?

          來個(gè)案例

          如下代碼,注意兩點(diǎn)信息

          • 內(nèi)部提供了 2 個(gè)接口,接口的返回值都是 ResultDto 類型的
          • 代碼中,沒有了 try catch,而是將異常類型封裝為 BusException 類型拋出,比如驗(yàn)證碼有誤,會(huì)拋出了 BusException,順便攜帶了錯(cuò)誤碼和錯(cuò)誤提示信息,這些都會(huì)通過全局異常的處理,輸出到客戶端
          @RestController
          @RequestMapping("/user")
          public class UserController {

              /**
               * 獲取用戶id
               *
               * @param code
               * @return
               */

              @RequestMapping("/getUserName")
              public ResultDto<String> getUserName(@RequestParam("code") Integer code) {
                  if (!Integer.valueOf(6666).equals(code)) {
                      //驗(yàn)證碼有誤的時(shí)候,返回4001錯(cuò)誤碼
                      BusException.throwBusException("4001""驗(yàn)證碼有誤!");
                  }
                  return ResultDto.success("路人");
              }

              /**
               * 獲取用戶id
               *
               * @param code
               * @return
               */

              @RequestMapping("/getUserId")
              public ResultDto<String> getUserId(@RequestParam("code") Integer code) {
                  if (!Integer.valueOf(6666).equals(code)) {
                      BusException.throwBusException("4001""驗(yàn)證碼有誤!");
                  }
                  return ResultDto.success("8888");
              }

          }

          驗(yàn)證效果

          下面我們通過 idea 提供的 HTTP client 工具搞三個(gè)測(cè)試用例,測(cè)試下接口的效果,如下圖,大家可以分別運(yùn)行一下 3 個(gè)案例。

          用例 1 輸出結(jié)果:

          {
            "success"true,
            "code"null,
            "msg""操作成功!",
            "data""路人"
          }

          用例 2 輸出結(jié)果:

          {
            "success"false,
            "code""4001",
            "msg""驗(yàn)證碼有誤!",
            "data"null
          }

          用例 3 輸出的結(jié)果:

          {
            "success"false,
            "code"null,
            "msg""系統(tǒng)異常,請(qǐng)聯(lián)系管理員,錯(cuò)誤詳情:Failed to convert value of type 'java.lang.String' to required type 'java.lang.Integer'; nested exception is java.lang.NumberFormatException: For input string: \"abc\"",
            "data"null
          }

          5、總結(jié)

          本文內(nèi)容主要有 2 點(diǎn):統(tǒng)一返回值、統(tǒng)一異常的處理,這 2 點(diǎn)大家要好好掌握,目前業(yè)界很少使用 springmvc 直接開發(fā)接口了,更多的是采用 springboot 來開發(fā)接口,本文的內(nèi)容直接可以用到 springboot 中,來優(yōu)化咱們的系統(tǒng)。

          6、案例代碼

          git地址:https://gitee.com/javacode2018/springmvc-series

          7、SpringMVC 系列

          1. SpringMVC 系列第 1 篇:helloword
          2. SpringMVC 系列第 2 篇:@Controller、@RequestMapping
          3. SpringMVC 系列第 3 篇:異常高效的一款接口測(cè)試?yán)?/a>
          4. SpringMVC 系列第 4 篇:controller 常見的接收參數(shù)的方式
          5. SpringMVC 系列第 5 篇:@RequestBody 大解密,說點(diǎn)你不知道的
          6. SpringMVC 系列第 6 篇:上傳文件的 4 種方式,你都會(huì)么?
          7. SpringMVC 系列第 7 篇:SpringMVC 返回視圖常見的 5 種方式,你會(huì)幾種?
          8. SpringMVC 系列第 8 篇:返回 json & 通用返回值設(shè)計(jì)
          9. SpringMVC 系列第 9 篇:SpringMVC 返回 null 是什么意思?
          10. SpringMVC 系列第 10 篇:異步處理
          11. SpringMVC 系列第 11 篇:集成靜態(tài)資源
          12. SpringMVC 系列第 12 篇:攔截器
          13. SpringMVC 系列第 13 篇:統(tǒng)一異常處理

          8、更多好文章

          1. Spring 高手系列(共 56 篇)
          2. Java 高并發(fā)系列(共 34 篇)
          3. MySql 高手系列(共 27 篇)
          4. Maven 高手系列(共 10 篇)
          5. Mybatis 系列(共 12 篇)
          6. 聊聊 db 和緩存一致性常見的實(shí)現(xiàn)方式
          7. 接口冪等性這么重要,它是什么?怎么實(shí)現(xiàn)?
          8. 泛型,有點(diǎn)難度,會(huì)讓很多人懵逼,那是因?yàn)槟銢]有看這篇文章!
          瀏覽 82
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  操逼视频网页 | 欧美色大香蕉 | 俺也去官网 | 影音先锋av成人网 | 天天干美女少妇 |