SpringBoot定義優(yōu)雅全局統(tǒng)一Restful API 響應(yīng)框架完結(jié)撒花篇封裝starter組件
之前我們已經(jīng),出了一些列文章。 講解如何封統(tǒng)一全局響應(yīng)Restful API。
感興趣的可以看我前面幾篇文章 (整個starter項目發(fā)展史)
SpringBoot定義優(yōu)雅全局統(tǒng)一Restful API 響應(yīng)框架
SpringBoot定義優(yōu)雅全局統(tǒng)一Restful API 響應(yīng)框架二
SpringBoot定義優(yōu)雅全局統(tǒng)一Restful API 響應(yīng)框架三
SpringBoot定義優(yōu)雅全局統(tǒng)一Restful API 響應(yīng)框架四
SpringBoot定義優(yōu)雅全局統(tǒng)一Restful API 響應(yīng)框架五
SpringBoot定義優(yōu)雅全局統(tǒng)一Restful API 響應(yīng)框架六
后續(xù)我萌生里新的想法,SpringBoot 不是提供了自己的starter。我們也可以自定義「starter」嗎,于是我定義了「rest-api-spring-boot-starter」,已經(jīng)發(fā)布到maven中央倉庫,對之前Restful API 響應(yīng)框架 做了集成和重構(gòu),
在這個基礎(chǔ)上我又總結(jié)封裝了我自己工作以常用的很多工具,結(jié)合SpringBoot 封裝了全能的工具。 已經(jīng)更新到了1.3.0 不耦合任何依賴 請使用最新版本

目前更新版本1.3.0 功能如下
支持一鍵配置自定義RestFull API 統(tǒng)一格式返回
支持RestFull API 錯誤國際化
支持全局異常處理,全局參數(shù)驗證處理
業(yè)務(wù)錯誤斷言工具封裝,遵循錯誤優(yōu)先返回原則
redis工作封裝。支持所有key操作工具
RestTemplate 封裝 POST,GET 請求工具
日志集成。自定義日志路徑,按照日志等級分類,支持壓縮和文件大小分割。按時間顯示
工具庫集成 集成了lombok,hutool,commons-lang3,guava。不需要自己單個引入
集成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;
????}
返回的就是全局統(tǒng)一RestFull API

我們也可以這么寫

提供了很多返回方法。
當然如果你這個接口不想包裝成全局返回,想自定義單獨返回 如我們只需要在方法上加上@NoRestFulApi
注解即可
???@PostMapping("/chat")
????@NoRestFulApi
????public?HashMap?chatDialogue()?{
????????HashMap?m?=?new?HashMap();
????????m.put("age",?26);
????????m.put("name",?"Judy");
????????return?m;
????}
就不會對返回內(nèi)容進行任何包裝處理。

全局錯誤攔截,參數(shù)校驗
幫你封裝好了所有http常見錯誤,和所有請求類型和參數(shù)錯誤。
如請求錯誤
{
????"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"
}
參數(shù)校驗錯誤
驗證Studen對象參數(shù)
/**
?*?@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;
????}
請求結(jié)果

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


錯誤國際化
內(nèi)置封裝錯誤默認支持英文和中文兩種國際化。你不做任何配置自動支持
如果需要內(nèi)置支持更多語言,覆蓋即可。
自定義自己錯誤國際化和語言
??i18n:
????#?若前端無header傳參則返回中文信息
????i18n-header:?Lang
????default-lang:?cn
????message:
??????#?admin
??????internal_server_error:
????????en:?Internal?Server?Error
????????cn:?系統(tǒng)錯誤
??????not_found:
????????en:?Not?Found
????????cn:?請求資源不存在
message 對應(yīng)錯誤提示 對應(yīng)internal_server_error 自定義 下面語言自己定義 和前端傳入i18n-header 對應(yīng)上,就顯你定義錯誤語言
我不傳錯誤國際化默認就是中文在 「default-lang: cn」 進行配置

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

自定義錯誤響應(yīng)
如果我內(nèi)置錯誤無法滿足你業(yè)務(wù)需求,你也可以自定義自己錯誤碼
你自定義錯誤枚舉 只需要實現(xiàn)「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
?*?響應(yīng)碼接口,自定義響應(yīng)碼,實現(xiàn)此接口
?*/
public?interface?ResultCode?extends?I18NKey?{
????String?getCode();
????String?getMessage();
}
如果要支持國際化還需要實現(xiàn)國際化接口「I18NKey」 參考我內(nèi)部「HttpStatus」實現(xiàn)即可
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?{
????/**
?????*?系統(tǒng)內(nèi)部錯誤
?????*/
????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:?系統(tǒng)錯誤
??????bad_gateway:
????????en:?Bad?Gateway
????????cn:?錯誤的請求
??????unauthorized:
????????en:?Unauthorized
????????cn:?未授權(quán)
??????forbidden:
????????en:?Forbidden
????????cn:?資源禁止訪問
??????method_not_allowed:
????????en:?Method?Not?Allowed
????????cn:?方法不被允許
??????request_timeout:
????????en:?Request?Timeout
????????cn:?請求超時
??????invalid_argument:
????????en:?Invalid?Argument?{}
????????cn:?參數(shù)錯誤?{}
??????argument_analyze:
????????en:?Argument?Analyze?{}
????????cn:?參數(shù)解析異常?{}
??????business_exception:
????????en:?Business?Exception
????????cn:?業(yè)務(wù)錯誤
??????not_found:
????????en:?Not?Found
????????cn:?請求資源不存在




內(nèi)部錯誤不需要做任何配置,自動支持國際化。如果需要支持更多語言,可以自定義進行覆蓋。
業(yè)務(wù)異常斷言
在項目開發(fā)中我們有時需要封裝自己異常類,信息我封裝了統(tǒng)一的錯誤異常類。 「BusinessException」 對業(yè)務(wù)異常類做了全局錯誤攔截,
封裝·了統(tǒng)一業(yè)務(wù)異常斷言工具,遵循錯誤優(yōu)先返回原則。代碼更優(yōu)雅

????@GetMapping("/exception")
????public?Result?exception(){
????????Student?s=null;
????????Assert.isFalse(s==null,"學(xué)生不能為空");
????????return?Result.buildSuccess();
????}
拋出統(tǒng)一業(yè)務(wù)異常

當然如果你要定義自己的異常類。可以定義自己異常類·繼承我的「BusinessException」
Redis 工具庫使用
進一步封裝的對「Redis」所以相關(guān)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());
????}
日志使用
進一步封裝了 日志處理達到開箱即用。在屬性文件中配置相關(guān)日志配置即可
rest-api:
??enabled:?false
??logging:
????path:?./logs???#日志存儲路徑(服務(wù)器上絕對)
????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任何相關(guān)包。如果需要使用自動代碼生成引入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>
你可以直接寫測試類,然后直接去調(diào)用代碼生成即可
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");
????????//生成代碼保存路徑,不設(shè)置就是當前項目下路徑,如何設(shè)置請使用絕對路徑
????????config.setProjectPath("superaide");
????????config.setPackages("cn.soboys.superaide");
????????MyBatisPlusGenerator.generate(config);
????}
}
效果如下

關(guān)注公眾號,「程序員三時」 持續(xù)輸出優(yōu)質(zhì)內(nèi)容 希望給你帶來一點啟發(fā)和幫助
下篇文章就這個源碼剖析講解 如何封裝自己的「stater」