SpringBoot定義優雅全域性統一Restful API 響應框架完結撒花篇封裝starter元件

2023-07-06 12:01:25

之前我們已經,出了一些列文章。 講解如何封統一全域性響應Restful API。

感興趣的可以看我前面幾篇文章 (整個starter專案發展史)

SpringBoot定義優雅全域性統一Restful API 響應框架

SpringBoot定義優雅全域性統一Restful API 響應框架二

SpringBoot定義優雅全域性統一Restful API 響應框架三

SpringBoot定義優雅全域性統一Restful API 響應框架四

SpringBoot定義優雅全域性統一Restful API 響應框架五

SpringBoot定義優雅全域性統一Restful API 響應框架六

後續我萌生裡新的想法,SpringBoot 不是提供了自己的starter。我們也可以自定義starter嗎,於是我定義了rest-api-spring-boot-starter,已經發布到maven中央倉庫,對之前Restful API 響應框架 做了整合和重構,

在這個基礎上我又總結封裝了我自己工作以常用的很多工具,結合SpringBoot 封裝了全能的工具。 已經更新到了1.3.0 不耦合任何依賴 請使用最新版本

目前更新版本1.3.0 功能如下

  1. 支援一鍵設定自定義RestFull API 統一格式返回
  2. 支援RestFull API 錯誤國際化
  3. 支援全域性例外處理,全域性引數驗證處理
  4. 業務錯誤斷言工具封裝,遵循錯誤優先返回原則
  5. redis工作封裝。支援所有key操作工具
  6. RestTemplate 封裝 POST,GET 請求工具
  7. 紀錄檔整合。自定義紀錄檔路徑,按照紀錄檔等級分類,支援壓縮和檔案大小分割。按時間顯示
  8. 工具庫整合 整合了lombok,hutool,commons-lang3,guava。不需要自己單個引入
  9. 整合mybatisPlus一鍵程式碼生成

github 地址

下面我講一下怎麼在專案中去使用

我們新建一個SpringBoot Web專案

我們只需要在pom中引入即可

 <dependency>
            <groupId>cn.soboys</groupId>
            <artifactId>rest-api-spring-boot-starter</artifactId>
            <version>1.2.0</version>
        </dependency>

在啟動類或者設定類中加上 @EnableRestFullApi 註解即可

RestFull API使用

這樣在專案controller中我們寫普通的請求如:

 @PostMapping("/chat")
    public HashMap chatDialogue() {
        HashMap m = new HashMap();
        m.put("age", 26);
        m.put("name", "Judy");
        return m;
    }

返回的就是全域性統一RestFull API

我們也可以這麼寫

提供了很多返回方法。

當然如果你這個介面不想包裝成全域性返回,想自定義單獨返回 如我們只需要在方法上加上@NoRestFulApi 註解即可

   @PostMapping("/chat")
    @NoRestFulApi
    public HashMap chatDialogue() {
        HashMap m = new HashMap();
        m.put("age", 26);
        m.put("name", "Judy");
        return m;
    }

就不會對返回內容進行任何包裝處理。

全域性錯誤攔截,引數校驗

幫你封裝好了所有http常見錯誤,和所有請求型別和引數錯誤。

如請求錯誤

{
    "success": false,
    "code": "405",
    "msg": "方法不被允許",
    "timestamp": "2023-07-03 22:36:47",
    "data": "Request method 'GET' not supported"
}

請求資源不存在

{
    "success": false,
    "code": "404",
    "msg": "請求資源不存在",
    "timestamp": "2023-07-03 22:42:35",
    "data": "/api"
}

引數校驗錯誤

驗證Studen物件引數

/**
 * @author 公眾號 程式設計師三時
 * @version 1.0
 * @date 2023/6/26 22:10
 * @webSite https://github.com/coder-amiao
 */
@Data
public class Student {
    @NotBlank
    private String nam;
    @NotBlank
    private String hobby;
}
    @PostMapping("/chat")
    public HashMap chatDialogue(@Validated  Student student) {
        HashMap m = new HashMap();
        m.put("age", 26);
        m.put("name", "Judy");
        return m;
    }

請求結果

JSON Body引數

    @PostMapping("/chat")
    public HashMap chatDialogue(@RequestBody @Validated  Student student) {
        HashMap m = new HashMap();
        m.put("age", 26);
        m.put("name", "Judy");
        return m;
    }

錯誤國際化

內建封裝錯誤預設支援英文和中文兩種國際化。你不做任何設定自動支援

如果需要內建支援更多語言,覆蓋即可。

自定義自己錯誤國際化和語言

  i18n:
    # 若前端無header傳參則返回中文資訊
    i18n-header: Lang
    default-lang: cn
    message:
      # admin
      internal_server_error:
        en: Internal Server Error
        cn: 系統錯誤
      not_found:
        en: Not Found
        cn: 請求資源不存在

message 對應錯誤提示
對應internal_server_error 自定義
下面語言自己定義 和前端傳入i18n-header 對應上,就顯你定義錯誤語言

我不傳錯誤國際化預設就是中文在 default-lang: cn
進行設定

當我傳入 指定語言 就會按照你設定的國際化自定義返回錯誤提示

自定義錯誤響應

如果我內建錯誤無法滿足你業務需求,你也可以自定義自己錯誤碼

你自定義錯誤列舉 只需要實現ResultCode介面即可

package cn.soboys.restapispringbootstarter;

import cn.soboys.restapispringbootstarter.i18n.I18NKey;

/**
 * @author 公眾號 程式設計師三時
 * @version 1.0
 * @date 2023/6/26 10:21
 * @webSite https://github.com/coder-amiao
 * 響應碼介面,自定義響應碼,實現此介面
 */
public interface ResultCode extends I18NKey {

    String getCode();

    String getMessage();

}

如果要支援國際化還需要實現國際化介面I18NKey 參考我內部HttpStatus實現即可

package cn.soboys.restapispringbootstarter;

import cn.soboys.restapispringbootstarter.i18n.I18NKey;

/**
 * @author 公眾號 程式設計師三時
 * @version 1.0
 * @date 2023/6/26 11:01
 * @webSite https://github.com/coder-amiao
 */
public enum HttpStatus implements ResultCode, I18NKey {
    /**
     * 系統內部錯誤
     */
    INTERNAL_SERVER_ERROR("500", "internal_server_error"),
    BAD_GATEWAY("502", "bad_gateway"),
    NOT_FOUND("404", "not_found"),
    UNAUTHORIZED("401", "unauthorized"),
    FORBIDDEN("403", "forbidden"),
    METHOD_NOT_ALLOWED("405", "method_not_allowed"),
    REQUEST_TIMEOUT("408", "request_timeout"),

    INVALID_ARGUMENT("10000", "invalid_argument"),
    ARGUMENT_ANALYZE("10001", "argument_analyze"),
    BUSINESS_EXCEPTION("20000", "business_exception");


    private final String value;

    private final String message;

    HttpStatus(String value, String message) {
        this.value = value;
        this.message = message;
    }


    @Override
    public String getCode() {
        return value;
    }

    @Override
    public String getMessage() {
        return message;
    }


    @Override
    public String key() {
        return message;
    }
}


rest-api:
  enabled: false
  i18n:
    # 若前端無header傳參則返回中文資訊
    i18n-header: Lang
    default-lang: cn
    message:
      # admin
      internal_server_error:
        en: Internal Server Error
        cn: 系統錯誤
      bad_gateway:
        en: Bad Gateway
        cn: 錯誤的請求
      unauthorized:
        en: Unauthorized
        cn: 未授權
      forbidden:
        en: Forbidden
        cn: 資源禁止存取
      method_not_allowed:
        en: Method Not Allowed
        cn: 方法不被允許
      request_timeout:
        en: Request Timeout
        cn: 請求超時
      invalid_argument:
        en: Invalid Argument {}
        cn: 引數錯誤 {}
      argument_analyze:
        en: Argument Analyze {}
        cn: 引數解析異常 {}
      business_exception:
        en: Business Exception
        cn: 業務錯誤
      not_found:
        en: Not Found
        cn: 請求資源不存在

內部錯誤不需要做任何設定,自動支援國際化。如果需要支援更多語言,可以自定義進行覆蓋。

業務異常斷言

在專案開發中我們有時需要封裝自己異常類,資訊我封裝了統一的錯誤異常類。
BusinessException 對業務異常類做了全域性錯誤攔截,

封裝·了統一業務異常斷言工具,遵循錯誤優先返回原則。程式碼更優雅

    @GetMapping("/exception")
    public Result exception(){
        Student s=null;
        Assert.isFalse(s==null,"學生不能為空");
        return Result.buildSuccess();
    }

丟擲統一業務異常

當然如果你要定義自己的異常類。可以定義自己異常類·繼承我的BusinessException

Redis 工具庫使用

進一步封裝的對Redis所以相關key,value操作,在使用redis工具庫時候。我們需要引入

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

預設不會幫你引入。

然後在使用時候注入就行

@Autowired
    private RedisTempUtil redisTempUtil;

    @GetMapping("/redis")
    public Result redis() {
        redisTempUtil.set("test", "123456");
        return Result.buildSuccess();
    }


    @GetMapping("/redis/get")
    public Result redisGet() {
        String value = redisTempUtil.get("test").toString();
        log.info("redis值{}", value);
        return Result.buildSuccess();
    }

RestTemplate 請求工具

進一步封裝了RestTemplate請求 Post和GET
專案中使用時注入

 @Autowired
    private RestFulTemp restFulTemp;

    @GetMapping("/doGet")
    public Result doGet() {
        ResponseEntity<String> response = restFulTemp.doGet("http://127.0.0.1:8000/redis/get");
        return Result.buildSuccess(response.getBody());
    }

紀錄檔使用

進一步封裝了 紀錄檔處理達到開箱即用。在屬性檔案中設定相關紀錄檔設定即可

rest-api:
  enabled: false
  logging:
    path: ./logs   #紀錄檔儲存路徑(伺服器上絕對)
    max-history: 90 # 儲存多少天
    max-file-size: 3MB  # 每個檔案大小
    max-total-size-cap: 1GB  #總檔案大小超過多少壓縮
    level-root: INFO    # 這裡的INFO可以替換為其他紀錄檔等級,如DEBUG, WARN, ERROR, TRACE, FATAL, OFF等。 紀錄檔等級由低到高分別是debugger-info-warn-error

如果你的屬性檔案不做任何紀錄檔設定,預設紀錄檔就是上面這樣設定。

整合mybatisPlus一鍵程式碼生成

在專案中我們會頻繁使用到mybatisPlus 但是簡單的模板程式碼我們一鍵生成就好。 預設不依賴mybatisPlus任何相關包。如果需要使用自動程式碼生成引入mybatisPlus 程式碼生成依賴包即可。

 <!--生成器依賴-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-generator</artifactId>
            <version>3.4.1</version>
            <optional>true</optional>
        </dependency>
        <!-- MySQL -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.28</version>
            <optional>true</optional>
        </dependency>
        <!--程式碼生成依賴的模板引擎-->
        <dependency>
            <groupId>org.freemarker</groupId>
            <artifactId>freemarker</artifactId>
            <version>2.3.31</version>
            <optional>true</optional>
        </dependency>

你可以直接寫測試類,然後直接去呼叫程式碼生成即可

public class Test {
    public static void main(String[] args) {
        GenerateCodeConfig config=new GenerateCodeConfig();
        config.setDriverName("com.mysql.cj.jdbc.Driver");
        config.setUsername("root");
        config.setPassword("root");
        config.setUrl("jdbc:mysql://127.0.0.1:3306/ry?useUnicode=true&useSSL=false&characterEncoding=utf8");
        //生成程式碼儲存路徑,不設定就是當前專案下路徑,如何設定請使用絕對路徑
        config.setProjectPath("superaide");
        config.setPackages("cn.soboys.superaide");
        MyBatisPlusGenerator.generate(config);
    }
}

效果如下

關注公眾號,程式設計師三時 持續輸出優質內容 希望給你帶來一點啟發和幫助

下篇文章就這個原始碼剖析講解 如何封裝自己的stater