<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>

          SpringBoot:如何優(yōu)雅地進(jìn)行參數(shù)傳遞、響應(yīng)數(shù)據(jù)封裝、異常處理?

          共 11438字,需瀏覽 23分鐘

           ·

          2021-07-27 12:47

          作者:云深i不知處

          blog.csdn.net/mu_wind/article/details/99960645

          在項目開發(fā)中,接口與接口之間、前后端之間的數(shù)據(jù)傳輸都使用 JSON 格式。

          1 fastjson使用

          阿里巴巴的 fastjson是目前應(yīng)用最廣泛的JSON解析框架。本文也將使用fastjson。

          1.1 引入依賴

          <dependency>
              <groupId>com.alibaba</groupId>
              <artifactId>fastjson</artifactId>
              <version>1.2.35</version>
          </dependency>

          2 統(tǒng)一封裝返回數(shù)據(jù)

          在web項目中,接口返回數(shù)據(jù)一般要包含狀態(tài)碼、信息、數(shù)據(jù)等,例如下面的接口示例:

          import com.alibaba.fastjson.JSONObject;
          import org.springframework.web.bind.annotation.RequestMapping;
          import org.springframework.web.bind.annotation.RequestMethod;
          import org.springframework.web.bind.annotation.RestController;

          /**
           * @author guozhengMu
           * @version 1.0
           * @date 2019/8/21 14:55
           * @description
           * @modify
           */
          @RestController
          @RequestMapping(value = "/test", method = RequestMethod.GET)
          public class TestController {
              @RequestMapping("/json")
              public JSONObject test() {
                  JSONObject result = new JSONObject();
                  try {
                      // 業(yè)務(wù)邏輯代碼
                      result.put("code", 0);
                      result.put("msg""操作成功!");
                      result.put("data""測試數(shù)據(jù)");
                  } catch (Exception e) {
                      result.put("code", 500);
                      result.put("msg""系統(tǒng)異常,請聯(lián)系管理員!");
                  }
                  return result;
              }
          }

          這樣的話,每個接口都這樣處理,非常麻煩,需要一種更優(yōu)雅的實(shí)現(xiàn)方式。

          2.1 定義統(tǒng)一的JSON結(jié)構(gòu)

          統(tǒng)一的 JSON 結(jié)構(gòu)中屬性包括數(shù)據(jù)、狀態(tài)碼、提示信息,其他項可以自己根據(jù)需要添加。一般來說,應(yīng)該有默認(rèn)的返回結(jié)構(gòu),也應(yīng)該有用戶指定的返回結(jié)構(gòu)。由于返回數(shù)據(jù)類型無法確定,需要使用泛型,代碼如下:

          public class ResponseInfo<T> {
              /**
               * 狀態(tài)碼
               */
              protected String code;
              /**
               * 響應(yīng)信息
               */
              protected String msg;
              /**
               * 返回數(shù)據(jù)
               */
              private T data;

              /**
               * 若沒有數(shù)據(jù)返回,默認(rèn)狀態(tài)碼為 0,提示信息為“操作成功!”
               */
              public ResponseInfo() {
                  this.code = 0;
                  this.msg = "操作成功!";
              }

              /**
               * 若沒有數(shù)據(jù)返回,可以人為指定狀態(tài)碼和提示信息
               * @param code
               * @param msg
               */
              public ResponseInfo(String code, String msg) {
                  this.code = code;
                  this.msg = msg;
              }

              /**
               * 有數(shù)據(jù)返回時,狀態(tài)碼為 0,默認(rèn)提示信息為“操作成功!”
               * @param data
               */
              public ResponseInfo(T data) {
                  this.data = data;
                  this.code = 0;
                  this.msg = "操作成功!";
              }

              /**
               * 有數(shù)據(jù)返回,狀態(tài)碼為 0,人為指定提示信息
               * @param data
               * @param msg
               */
              public ResponseInfo(T data, String msg) {
                  this.data = data;
                  this.code = 0;
                  this.msg = msg;
              }
              // 省略 get 和 set 方法
          }

          2.2 使用統(tǒng)一的JSON結(jié)構(gòu)

          我們封裝了統(tǒng)一的返回數(shù)據(jù)結(jié)構(gòu)后,在接口中就可以直接使用了。如下:

          import com.example.demo.model.ResponseInfo;
          import org.springframework.web.bind.annotation.RequestMapping;
          import org.springframework.web.bind.annotation.RequestMethod;
          import org.springframework.web.bind.annotation.RestController;

          /**
           * @author guozhengMu
           * @version 1.0
           * @date 2019/8/21 14:55
           * @description
           * @modify
           */
          @RestController
          @RequestMapping(value = "/test", method = RequestMethod.GET)
          public class TestController {
              @RequestMapping("/json")
              public ResponseInfo test() {
                  try {
                      // 模擬異常業(yè)務(wù)代碼
                      int num = 1 / 0;
                      return new ResponseInfo("測試數(shù)據(jù)");
                  } catch (Exception e) {
                      return new ResponseInfo(500, "系統(tǒng)異常,請聯(lián)系管理員!");
                  }
              }
          }

          如上,接口的返回數(shù)據(jù)處理便優(yōu)雅了許多。針對上面接口做個測試,啟動項目,通過瀏覽器訪問:localhost:8096/test/json,得到響應(yīng)結(jié)果:

          {"code":500,"msg":"系統(tǒng)異常,請聯(lián)系管理員!","data":null}

          3 全局異常處理

          3.1 系統(tǒng)定義異常處理

          新建一個 ExceptionHandlerAdvice 全局異常處理類,然后加上 @RestControllerAdvice 注解即可攔截項目中拋出的異常,如下代碼中包含了幾個異常處理,如參數(shù)格式異常、參數(shù)缺失、系統(tǒng)異常等,見下例:

          @RestControllerAdvice
          @Slf4j
          public class ExceptionHandlerAdvice {

              // 參數(shù)格式異常處理
              @ExceptionHandler({IllegalArgumentException.class})
              @ResponseStatus(HttpStatus.BAD_REQUEST)
              public ResponseInfo badRequestException(IllegalArgumentException exception) {
               log.error("參數(shù)格式不合法:" + e.getMessage());
                  return new ResponseInfo(HttpStatus.BAD_REQUEST.value() + """參數(shù)格式不符!");
              }

           // 權(quán)限不足異常處理
              @ExceptionHandler({AccessDeniedException.class})
              @ResponseStatus(HttpStatus.FORBIDDEN)
              public ResponseInfo badRequestException(AccessDeniedException exception) {
                  return new ResponseInfo(HttpStatus.FORBIDDEN.value() + "", exception.getMessage());
              }

           // 參數(shù)缺失異常處理
              @ExceptionHandler({MissingServletRequestParameterException.class})
              @ResponseStatus(HttpStatus.BAD_REQUEST)
              public ResponseInfo badRequestException(Exception exception) {
                  return new ResponseInfo(HttpStatus.BAD_REQUEST.value() + """缺少必填參數(shù)!");
              }

              // 空指針異常
              @ExceptionHandler(NullPointerException.class)
              @ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR)
              public ResponseInfo handleTypeMismatchException(NullPointerException ex) {
                  log.error("空指針異常,{}", ex.getMessage());
                  return new JsonResult("500""空指針異常");
              }

              @ExceptionHandler(Exception.class)
              @ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR)
              public JsonResult handleUnexpectedServer(Exception ex) {
                  log.error("系統(tǒng)異常:", ex);
                  return new JsonResult("500""系統(tǒng)發(fā)生異常,請聯(lián)系管理員");
              }
              
              // 系統(tǒng)異常處理
              @ExceptionHandler(Throwable.class)
              @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
              public ResponseInfo exception(Throwable throwable) {
                  log.error("系統(tǒng)異常", throwable);
                  return new ResponseInfo(HttpStatus.INTERNAL_SERVER_ERROR.value() + "系統(tǒng)異常,請聯(lián)系管理員!");
              }
          }
          1. @RestControllerAdvice 注解包含了 @Component 注解,說明在 Spring Boot 啟動時,也會把該類作為組件交給 Spring 來管理。
          2. @RestControllerAdvice 注解包含了 @ResponseBody 注解,為了異常處理完之后給調(diào)用方輸出一個 JSON 格式的封裝數(shù)據(jù)。
          3. @RestControllerAdvice 注解還有個 basePackages 屬性,該屬性用來攔截哪個包中的異常信息,一般我們不指定這個屬性,我們攔截項目工程中的所有異常。
          4. 在方法上通過 @ExceptionHandler 注解來指定具體的異常,然后在方法中處理該異常信息,最后將結(jié)果通過統(tǒng)一的 JSON 結(jié)構(gòu)體返回給調(diào)用者。
          5. 但在項目中,我們一般都會比較詳細(xì)地去攔截一些常見異常,攔截 Exception 雖然可以一勞永逸,但是不利于我們?nèi)ヅ挪榛蛘叨ㄎ粏栴}。實(shí)際項目中,可以把攔截 Exception 異常寫在 GlobalExceptionHandler 最下面,如果都沒有找到,最后再攔截一下 Exception 異常,保證輸出信息友好。

          下面我們通過一個接口來進(jìn)行測試:

          @RestController
          @RequestMapping(value = "/test", method = RequestMethod.POST)
          public class TestController {
              @RequestMapping("/json")
              public ResponseInfo test(@RequestParam String userName, @RequestParam String password) {
                  try {
                      String data = "登錄用戶:" + userName + ",密碼:" + password;
                      return new ResponseInfo("0""操作成功!", data);
                  } catch (Exception e) {
                      return new ResponseInfo("500""系統(tǒng)異常,請聯(lián)系管理員!");
                  }
              }
          }

          接口調(diào)用,password這項故意空缺:

          瀏覽 67
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          <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>
                  欧美成人网站在线导航 | 亚洲精品视频在线观看免费无码 | 欧美特级视频 | 丁香五月天婷国产 | 亚洲天堂视频在线免费观看 |