最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會員登陸 & 注冊

我開源了團(tuán)隊(duì)內(nèi)部基于SpringBoot Web快速開發(fā)的API腳手架stater

2023-07-18 10:08 作者:程序員三時(shí)  | 我要投稿

我們現(xiàn)在使用「SpringBoot」 做Web 開發(fā)已經(jīng)比之前SprngMvc 那一套強(qiáng)大很多了。 但是 用SpringBoot Web 做API 開發(fā)還是不夠簡潔有一些。

每次Web API常用功能都需要重新寫一遍。或者復(fù)制之前項(xiàng)目代碼。于是我封裝了這么一個(gè)

抽出「SpringBoot Web API」 每個(gè)項(xiàng)目必備需要重復(fù)寫的模塊,和必備功能。 并且擴(kuò)展了我工作中用到的 所有工具庫。

基于它,你可以輕松開發(fā)SpringBoot WEB API,提高效率。不在去關(guān)心一些繁瑣。重復(fù)工作,而是把重點(diǎn)聚焦到業(yè)務(wù)。

目前更新版本到1.5.2 功能如下

  1. 支持一鍵配置自定義RestFull API 統(tǒng)一格式返回

  2. 支持RestFull API 錯(cuò)誤國際化

  3. 支持全局異常處理,全局參數(shù)驗(yàn)證處理

  4. 業(yè)務(wù)錯(cuò)誤斷言工具封裝,遵循錯(cuò)誤優(yōu)先返回原則

  5. 封裝Redis key,value 操作工具類。統(tǒng)一key管理 spring cache緩存實(shí)現(xiàn)

  6. RestTemplate 封裝 POST,GET 請求工具

  7. 日志集成。自定義日志路徑,按照日志等級分類,支持壓縮和文件大小分割。按時(shí)間顯示

  8. 工具庫集成 集成了lombok,hutool,commons-lang3,guava。不需要自己單個(gè)引入

  9. 集成mybatisPlus一鍵代碼生成

  10. 日志記錄,服務(wù)監(jiān)控,支持日志鏈路查詢。自定義數(shù)據(jù)源

  11. OpenApi3文檔一鍵配置。支持多種文檔和自動配置

  12. 接口限流,Ip城市回顯

  13. HttpUserAgent請求設(shè)備工具封裝

  14. RequestUtil參數(shù)解析封裝工具

后續(xù)會持續(xù)更新。項(xiàng)目中重復(fù)使用,必備模塊和工具。

  • GitHub 地址

  • gitee 地址

「rest-api-spring-boot-starter」 適用于SpringBoot Web API 快速構(gòu)建讓開發(fā)人員快速構(gòu)建統(tǒng)一規(guī)范的業(yè)務(wù)RestFull API 不在去關(guān)心一些繁瑣。重復(fù)工作,而是把重點(diǎn)聚焦到業(yè)務(wù)。

快速開始

  1. 項(xiàng)目pom中引入依賴

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

  1. 在SpringBoot啟動類或者配置類上通過 「@EnableRestFullApi」注解開啟rest-api


@SpringBootApplication
@EnableRestFullApi
public?class?SuperaideApplication?{

????public?static?void?main(String[]?args)?{
????????SpringApplication.run(SuperaideApplication.class,?args);
????}
}

到此你項(xiàng)目中就可以使用所有的功能了。

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

{
????"success":?true,
????"code":?"OK",
????"msg":?"操作成功",
????"requestId":?"IPbHLE5SZ1fqI0lgNXlB",
????"timestamp":?"2023-07-09?02:39:40",
????"data":?{
????????"name":?"judy",
????????"hobby":?"swing",
????????"age":?18
????}
}

也可以基于Result構(gòu)建

@PostMapping("/chat")
public?Result?chatDialogue(@Validated?EntityParam?s)?{
????return?Result.buildSuccess(s);
}

分頁支持

我們在日常中分頁是一個(gè)比較特殊返回。也是非常常用的。

@PostMapping("/page")
@Log("分頁查詢用戶數(shù)據(jù)")
public?Result?page(@Validated?EntityParam?s)?{
????ResultPage<List<EntityParam>>?resultPage=new?ResultPage<>();
????List?a=new?ArrayList();
????a.add(s);
????resultPage.setPageData(a);
????return?ResultPage.buildSuccess(resultPage);
}

  1. 構(gòu)建自定義自己的分頁數(shù)據(jù)

ResultPage<List<EntityParam>>?resultPage=new?ResultPage<>();

  1. 通過ResultPage.buildSuccess(resultPage)進(jìn)行構(gòu)建返回

返回統(tǒng)一響應(yīng)格式

{
????"previousPage":?1,
????"nextPage":?1,
????"pageSize":?1,
????"totalPageSize":?1,
????"hasNext":?"false",
????"success":?true,
????"code":?"OK",
????"msg":?"操作成功",
????"requestId":?"D9AMALgkZ6gVfe6Pi0Oh",
????"timestamp":?"2023-07-09?02:39:40",
????"data":?[
????????{
????????????"name":?"judy",
????????????"hobby":?"swing",
????????????"age":?18
????????}
????]
}

自定義返回格式

{
????"previousPage":?1,
????"nextPage":?1,
????"pageSize":?1,
????"totalPageSize":?1,
????"hasNext":?"false",
????"success":?true,
????"code":?"OK",
????"msg":?"操作成功",
????"requestId":?"D9AMALgkZ6gVfe6Pi0Oh",
????"timestamp":?"2023-07-09?02:39:40",
????"data":?[
????????{
????????????"name":?"judy",
????????????"hobby":?"swing",
????????????"age":?18
????????}
????]
}

上述統(tǒng)一返回格式,可能不符合你項(xiàng)目中接口統(tǒng)一格式如:

{
????"success":?true,
????"code":?"OK",
????"msg":?"操作成功",
????"requestId":?"ztf4S-lP9yrtKPSiwldZ",
????"timestamp":?"2023-07-11?13:46:53",
????"data":?{
????????"previousPage":?1,
????????"nextPage":?1,
????????"pageSize":?1,
????????"totalPageSize":?1,
????????"hasNext":?"false",
????????"pageData":?[
????????????{
????????????????"name":?"judy",
????????????????"hobby":?"swing",
????????????????"age":?18
????????????}
????????]
????}
}

page分頁數(shù)據(jù)是在data里面你可以定義pageWrap屬性true包裝返回定義pageDatakey值如records

你需要自定義keymsg你可能對應(yīng)message,success你可能對應(yīng)status只需要在配置文件中配置自定義key

自定義返回成功值你的成功返回可能是200你可以配置code-success-value

rest-api:
??enabled:?false
??msg:?msg
??code:?code
??code-success-value:?OK
??success:?success
??previousPage:?previousPage
??nextPage:?nextPage
??pageSize:?pageSize
??hasNext:?hasNext
??totalPageSize:?totalPageSize
??data:?info

當(dāng) enabled開啟后會讀取你自定義配置的key

rest-api:
??enabled:?true
??msg:?msg1
??code:?code1
??code-success-value:?200
??success:?success1
??previousPage:?previousPage1
??nextPage:?nextPage1
??pageSize:?pageSize1
??hasNext:?hasNext1
??totalPageSize:?totalPageSize1
??data:?info

對應(yīng)返回內(nèi)容

{
????"success":?true,
????"code":?"OK",
????"msg":?"操作成功",
????"requestId":?"ztf4S-lP9yrtKPSiwldZ",
????"timestamp":?"2023-07-11?13:46:53",
????"data":?{
????????"previousPage":?1,
????????"nextPage":?1,
????????"pageSize":?1,
????????"totalPageSize":?1,
????????"hasNext":?"false",
????????"pageData":?[
????????????{
????????????????"name":?"judy",
????????????????"hobby":?"swing",
????????????????"age":?18
????????????}
????????]
????}
}

自定義返回

有時(shí)候我們需要自定義返回。不去包裝統(tǒng)一響應(yīng)RestFull API格式

  1. 可以通過注解@NoRestFulApi實(shí)現(xiàn)如

@GetMapping("/test")
@NoRestFulApi
public?Map?chatDialogue()?{
????Map??m=?new?HashMap<>();
????m.put("name","judy");
????m.put("age",26);
????return?m;
}

  1. 通過類掃描去實(shí)現(xiàn) 默認(rèn)會過濾String類型認(rèn)為是頁面路徑。

通過屬性配置文件include-packages需要統(tǒng)一返回包。exclude-packages不需統(tǒng)一返回的包

include-packages:?cn.soboys.superaide.controller
exclude-packages:?xx.xxx.xxx

OpenApi文檔生成

已經(jīng)內(nèi)置自動支持。swagger文檔。和最新的OpenApi3 文檔。項(xiàng)目啟動后即可訪問。

  1. swagger-ui.html 文檔。路徑/swagger-ui.html

  2. 基于spring-doc 文檔UI增強(qiáng) 路徑/doc.html

  3. 接口文檔屬性信息

??openapi:
????description:
????title:
????version:
????license:?
????contact:
??????name:
??????email:
??????url:?

  • 啟動項(xiàng)目后,訪問 http://server:port/context-path/swagger-ui.html 即可進(jìn)入 Swagger UI 頁面,OpenAPI 描述將在以下 json 格式的 url 中 提供:http://server:port/context-path/v3/api-docs

  • server:域名 或 IP

  • port:服務(wù)器端口

  • context-path:應(yīng)用程序的上下文路徑,springboot 默認(rèn)為空

  • 文檔也可以 yaml 格式提供,位于以下路徑:/v3/api-docs.yaml

如果嫌棄官方提供的 swagger-ui 不美觀,或者使用不順手,可以選擇關(guān)閉 ui,還可以剔除掉 ui 相關(guān)的 webjar 的引入。

springdoc:
??swagger-ui:
????enabled:?false

OpenAPI 文檔信息,默認(rèn)可在此 url 中獲取: http://server:port/context-path/v3/api-docs。 可以利用其他支持 OpenAPI 協(xié)議的工具,通過此地址,進(jìn)行 API 展示,如 Apifox。 ( Postman 的 api 測試也可以利用此地址進(jìn)行導(dǎo)入生成 )

Knife4j (原 swagger-bootstrap-ui) 3.x 版本提供了對于 OpenAPI 協(xié)議的部分支持。

::: tip Knife4j 很多地方?jīng)]有按照協(xié)議規(guī)范實(shí)現(xiàn),所以使用起來會有很多問題,另外項(xiàng)目也很久沒有維護(hù)了,不推薦使用。 :::

?

由于 knife4j 對于規(guī)范支持的不全面,無法直接使用單文檔源數(shù)據(jù),所以必須進(jìn)行分組或者 urls 的指定。

?

#?urls
springdoc:
??swagger-ui:
????urls:
??????-?{?name:?'sample',?url:?'/v3/api-docs'?}

或者

#分組
springdoc:
??group-configs:
????-?{?group:?'sample',?packages-to-scan:?'com.example'?}

Knife4j 的 UI 訪問地址有所不同,頁面映射在 doc.html 路徑下,啟動項(xiàng)目后,訪問 http://server:port/context-path/doc.html

即可進(jìn)入 Knife4j 的 Swagger UI 頁面。

全局錯(cuò)誤攔截,參數(shù)校驗(yàn)

幫你封裝好了所有http常見錯(cuò)誤,和所有請求參數(shù)驗(yàn)證錯(cuò)誤。

如請求錯(cuò)誤

{
????"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"
}

?

如果需要攔截上面錯(cuò)誤請?jiān)趕pringboot 配置文件中加入

?

#出現(xiàn)錯(cuò)誤時(shí),?直接拋出異常
spring.mvc.throw-exception-if-no-handler-found=true
#不要為我們工程中的資源文件建立映射
spring.web.resources.add-mappings=false

「參數(shù)校驗(yàn)錯(cuò)誤」

驗(yàn)證Studen對象參數(shù)

/**
?*?@author?公眾號?程序員三時(shí)
?*?@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;
????}

錯(cuò)誤國際化

內(nèi)置封裝錯(cuò)誤默認(rèn)支持英文和中文兩種國際化。你不做任何配置自動支持

如果需要內(nèi)置支持更多語言,覆蓋即可。

自定義自己錯(cuò)誤國際化和語言

??i18n:
????#?若前端無header傳參則返回中文信息
????i18n-header:?Lang
????default-lang:?cn
????message:
??????#?admin
??????internal_server_error:
????????en:?Internal?Server?Error
????????cn:?系統(tǒng)錯(cuò)誤
??????not_found:
????????en:?Not?Found
????????cn:?請求資源不存在

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

我不傳錯(cuò)誤國際化默認(rèn)就是中文在 「default-lang: cn」進(jìn)行配置

當(dāng)我傳入 指定語言 就會按照你配置的國際化自定義返回錯(cuò)誤提示

日志鏈路追蹤

RestFull API 統(tǒng)一返回有一個(gè)requestId 它是每個(gè)接口唯一標(biāo)識。用于接口請求日志鏈路追蹤。日志查詢。 如:

{
????"msg":?"操作成功",
????"code":?"OK",
????"previousPage":?1,
????"success":?true,
????"requestId":?"udYNdbbMFE45R84OPu9m",
????"nextPage":?1,
????"pageSize":?1,
????"totalPageSize":?1,
????"hasNext":?"false",
????"timestamp":?"2023-07-09?03:00:27",
????"info":?[
????????{
????????????"name":?"judy",
????????????"hobby":?"swing",
????????????"age":?18
????????}
????]
}

通過requestId你可以很輕松的在你的日志文件查詢定位到每次錯(cuò)誤的請求。

通過Log注解記錄你想要記錄請求

@PostMapping("/page")
@Log(value?=?"查詢用戶數(shù)據(jù)",apiType=?LogApiTypeEnum.USER,CURDType=?LogCURDTypeEnum.RETRIEVE)
public?Result?page(@Validated?EntityParam?s)?{
????ResultPage<List<EntityParam>>?resultPage=new?ResultPage<>();
????List?a=new?ArrayList();
????a.add(s);
????resultPage.setPageData(a);
????return?ResultPage.buildSuccess(resultPage);
}

?

系統(tǒng)默認(rèn)日志記錄數(shù)據(jù)源為日志文件。如

?

2023-07-13?11:21:25?INFO??http-nio-8888-exec-2?cn.soboys.restapispringbootstarter.aop.LimitAspect?IP:192.168.1.8?第?1?次訪問key為?[_kenx:chat192.168.1.8],描述為?[接口限流]?的接口
2023-07-13?11:21:26?INFO??http-nio-8888-exec-2?cn.soboys.restapispringbootstarter.log.LogFileDefaultDataSource?{
????"description":?"日志記錄測試",
????"method":?"cn.soboys.restapispringbootstarter.controller.ApiRestController.chatDialogue()",
????"params":?{
????},
????"logType":?"INFO",
????"requestIp":?"192.168.1.8",
????"path":?"/chat",
????"address":?"0|0|0|內(nèi)網(wǎng)IP|內(nèi)網(wǎng)IP",
????"time":?128,
????"os":?"Mac",
????"browser":?"Chrome",
????"result":?{
????????"success":?true,
????????"code":?"OK",
????????"msg":?"操作成功",
????????"requestId":?"5RgKzWGFNa9XSPwhw2Pi",
????????"timestamp":?"2023-07-13?11:21:25",
????????"data":?"接口限流測試"
????},
????"apiType":?"USER",
????"device":?"Mozilla/5.0?(Macintosh;?Intel?Mac?OS?X?10_15_7)?AppleWebKit/537.36?(KHTML,?like?Gecko)?Chrome/114.0.0.0?Safari/537.36"
}

你可以自定義自己的日志數(shù)據(jù)源實(shí)現(xiàn)LogDataSource接口 日志操作支持異步。需要在配置類。或者啟動類加上@EnableAsync注解

package?cn.soboys.restapispringbootstarter.log;

import?org.springframework.scheduling.annotation.Async;

import?java.util.Map;

/**
?*?@Author:?kenx
?*?@Since:?2021/6/23?13:55
?*?@Description:
?*/

public?interface?LogDataSource?{

????/**
?????*?獲取拓展數(shù)據(jù)
?????*?@return
?????*?@param?logEntry
?????*/

????@Async
????void??save(LogEntry?logEntry);
}

或者你可以繼承我默認(rèn)的日志數(shù)據(jù)源實(shí)現(xiàn)類LogFileDefaultDataSource 重寫save(LogEntry logEntry)方法。

@Slf4j
public?class?LogFileDefaultDataSource?implements?LogDataSource?{

????/**
?????*?自定義保存數(shù)據(jù)源
?????*
?????*?@param
?????*?@return?LogEntry
?????*/

????@Override
????public?void?save(LogEntry?logEntry)?{
????????log.info(JSONUtil.toJsonPrettyStr(logEntry));
????}
}

?

如果是自定義日志數(shù)據(jù)源實(shí)現(xiàn)需要再配置文件,配置日志數(shù)據(jù)源。如:

?

logging:
????path:?./logs???#日志存儲路徑(服務(wù)器上絕對)
????max-history:?90?#?保存多少天
????max-file-size:?3MB??#?每個(gè)文件大小
????max-total-size-cap:?1GB??#總文件大小超過多少壓縮
????level-root:?INFO????#?這里的INFO可以替換為其他日志等級,如DEBUG,?WARN,?ERROR,?TRACE,?FATAL,?OFF等。?日志等級由低到高分別是debugger-info-warn-error
????logDataSourceClass:?cn.soboys.restapispringbootstarter.log.LogFileDefaultDataSource?#?日志數(shù)據(jù)源

Ip城市記錄

日志記錄提供Ip城市回顯記錄

@PostMapping("/page")
@Log(value?=?"查詢用戶數(shù)據(jù)",?apiType?=?LogApiTypeEnum.USER,?CURDType?=?LogCURDTypeEnum.RETRIEVE,ipCity?=?true)
public?Result?page(@Validated?EntityParam?s)?{
????ResultPage<List<EntityParam>>?resultPage?=?new?ResultPage<>();
????List?a?=?new?ArrayList();
????a.add(s);
????resultPage.setPageData(a);
????return?ResultPage.buildSuccess(resultPage);
}

通過配置ipCity屬性,默認(rèn)是true會記錄IP對應(yīng)物理地址詳細(xì)信息即國家城市等Ip城市查詢通過ip2region獲取。

你可配置屬性 location 配置自己的ip2region.xdb文件。

??ip2region:
????external:?false
????location:?classpath:ip2region/ip2region.xdb

默認(rèn)不配置會幫你自動生成一個(gè)?;?.7.x最新的數(shù)據(jù) 獲取最新自定義ip數(shù)據(jù) Github 倉庫

當(dāng)然也幫你封裝了。你可以通過工具類HttpUserAgent的靜態(tài)方法getIpToCityInfo(String ip) 去獲取查詢ip對應(yīng)城市信息

屬性配置

配置語言國際化,日志等,

::: tip 默認(rèn)不用配置任何參數(shù)。會使用默認(rèn)的,配置了會使用你項(xiàng)目中的配置。 :::

默認(rèn)配置

rest-api:
??enabled:?false
??msg:?msg
??code:?code
??code-success-value:?OK
??success:?success
??previousPage:?previousPage
??nextPage:?nextPage
??pageSize:?pageSize
??hasNext:?hasNext
??totalPageSize:?totalPageSize
??data:?info
??include-packages:?cn.soboys.superaide.controller
??exclude-packages:?xx.xxx.xxx
??redis:
????key-prefix:?rest
??openapi:
????description:
????title:
????version:
????license:?
????contact:
??????name:
??????email:
??????url:
??logging:
????path:?./logs???#日志存儲路徑(服務(wù)器上絕對)
????max-history:?90?#?保存多少天
????max-file-size:?3MB??#?每個(gè)文件大小
????max-total-size-cap:?1GB??#總文件大小超過多少壓縮
????level-root:?INFO????#?這里的INFO可以替換為其他日志等級,如DEBUG,?WARN,?ERROR,?TRACE,?FATAL,?OFF等。?日志等級由低到高分別是debugger-info-warn-error
????logDataSourceClass:?cn.soboys.restapispringbootstarter.log.LogFileDefaultDataSource?#?日志數(shù)據(jù)源
??i18n:
????#?若前端無header傳參則返回中文信息
????i18n-header:?Lang
????default-lang:?cn
????message:
??????#?admin
??????internal_server_error:
????????en:?Internal?Server?Error
????????cn:?系統(tǒng)錯(cuò)誤
??????bad_gateway:
????????en:?Bad?Gateway
????????cn:?錯(cuò)誤的請求
??????unauthorized:
????????en:?Unauthorized
????????cn:?未授權(quán)
??????forbidden:
????????en:?Forbidden
????????cn:?資源禁止訪問
??????method_not_allowed:
????????en:?Method?Not?Allowed
????????cn:?方法不被允許
??????request_timeout:
????????en:?Request?Timeout
????????cn:?請求超時(shí)
??????invalid_argument:
????????en:?Invalid?Argument?{}
????????cn:?參數(shù)錯(cuò)誤?{}
??????argument_analyze:
????????en:?Argument?Analyze?{}
????????cn:?參數(shù)解析異常?{}
??????business_exception:
????????en:?Business?Exception
????????cn:?業(yè)務(wù)錯(cuò)誤
??????not_found:
????????en:?Not?Found
????????cn:?請求資源不存在

代碼生成配置

支持MybatisPlus代碼一鍵生成 默認(rèn)不引入MybatisPlus生成依賴需要手動引入

package?cn.soboys.restapispringbootstarter.config;

import?lombok.Data;

/**
?*?@author?公眾號?程序員三時(shí)
?*?@version?1.0
?*?@date?2023/7/5?00:05
?*?@webSite?https://github.com/coder-amiao
?*/

@Data
public?class?GenerateCodeConfig?{
????/**
?????*?數(shù)據(jù)庫驅(qū)動
?????*/

????private?String?driverName;
????/**
?????*?數(shù)據(jù)庫連接用戶名
?????*/

????private?String?username;
????/**
?????*?數(shù)據(jù)庫連接密碼
?????*/

????private?String?password;
????/**
?????*?數(shù)據(jù)庫連接url
?????*/

????private?String?url;
????/**
?????*?生成代碼?保存路徑。默認(rèn)當(dāng)前項(xiàng)目下。
?????*?如需修改,使用覺得路徑
?????*/

????private?String?projectPath;
????/**
?????*?代碼生成包位置
?????*/

????private?String?packages;
}

RestFull API

Controller中直接使用

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

Result構(gòu)建返回

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

分頁支持

我們在日常中分頁是一個(gè)比較特殊返回。也是非常常用的。

@PostMapping("/page")
@Log("分頁查詢用戶數(shù)據(jù)")
public?Result?page(@Validated?EntityParam?s)?{
????ResultPage<List<EntityParam>>?resultPage=new?ResultPage<>();
????List?a=new?ArrayList();
????a.add(s);
????resultPage.setPageData(a);
????return?ResultPage.buildSuccess(resultPage);
}

  1. 構(gòu)建自定義自己的分頁數(shù)據(jù)

ResultPage<List<EntityParam>>?resultPage=new?ResultPage<>();

  1. 通過ResultPage.buildSuccess(resultPage)進(jìn)行構(gòu)建返回

返回統(tǒng)一響應(yīng)格式

{
????"previousPage":?1,
????"nextPage":?1,
????"pageSize":?1,
????"totalPageSize":?1,
????"hasNext":?"false",
????"success":?true,
????"code":?"OK",
????"msg":?"操作成功",
????"requestId":?"D9AMALgkZ6gVfe6Pi0Oh",
????"timestamp":?"2023-07-09?02:39:40",
????"data":?[
????????{
????????????"name":?"judy",
????????????"hobby":?"swing",
????????????"age":?18
????????}
????]
}

自定義返回格式

{
????"previousPage":?1,
????"nextPage":?1,
????"pageSize":?1,
????"totalPageSize":?1,
????"hasNext":?"false",
????"success":?true,
????"code":?"OK",
????"msg":?"操作成功",
????"requestId":?"D9AMALgkZ6gVfe6Pi0Oh",
????"timestamp":?"2023-07-09?02:39:40",
????"data":?[
????????{
????????????"name":?"judy",
????????????"hobby":?"swing",
????????????"age":?18
????????}
????]
}

上述統(tǒng)一返回格式,可能不符合你項(xiàng)目中接口統(tǒng)一格式如:

{
????"success":?true,
????"code":?"OK",
????"msg":?"操作成功",
????"requestId":?"ztf4S-lP9yrtKPSiwldZ",
????"timestamp":?"2023-07-11?13:46:53",
????"data":?{
????????"previousPage":?1,
????????"nextPage":?1,
????????"pageSize":?1,
????????"totalPageSize":?1,
????????"hasNext":?"false",
????????"pageData":?[
????????????{
????????????????"name":?"judy",
????????????????"hobby":?"swing",
????????????????"age":?18
????????????}
????????]
????}
}

page分頁數(shù)據(jù)是在data里面你可以定義pageWrap屬性true包裝返回定義pageDatakey值如records

你需要自定義keymsg你可能對應(yīng)message,success你可能對應(yīng)status只需要在配置文件中配置自定義key

自定義返回成功值你的成功返回可能是200你可以配置code-success-value

rest-api:
??enabled:?false
??msg:?msg
??code:?code
??code-success-value:?OK
??success:?success
??previousPage:?previousPage
??nextPage:?nextPage
??pageSize:?pageSize
??hasNext:?hasNext
??totalPageSize:?totalPageSize
??data:?info

當(dāng) enabled開啟后會讀取你自定義配置的key

rest-api:
??enabled:?true
??msg:?msg1
??code:?code1
??code-success-value:?200
??success:?success1
??previousPage:?previousPage1
??nextPage:?nextPage1
??pageSize:?pageSize1
??hasNext:?hasNext1
??totalPageSize:?totalPageSize1
??data:?info

對應(yīng)返回內(nèi)容

{
????"success":?true,
????"code":?"OK",
????"msg":?"操作成功",
????"requestId":?"ztf4S-lP9yrtKPSiwldZ",
????"timestamp":?"2023-07-11?13:46:53",
????"data":?{
????????"previousPage":?1,
????????"nextPage":?1,
????????"pageSize":?1,
????????"totalPageSize":?1,
????????"hasNext":?"false",
????????"pageData":?[
????????????{
????????????????"name":?"judy",
????????????????"hobby":?"swing",
????????????????"age":?18
????????????}
????????]
????}
}

自定義返回

有時(shí)候我們需要自定義返回。不去包裝統(tǒng)一響應(yīng)RestFull API格式

  1. 可以通過注解@NoRestFulApi實(shí)現(xiàn)如

@GetMapping("/test")
@NoRestFulApi
public?Map?chatDialogue()?{
????Map??m=?new?HashMap<>();
????m.put("name","judy");
????m.put("age",26);
????return?m;
}

  1. 通過類掃描去實(shí)現(xiàn) 默認(rèn)會過濾String類型認(rèn)為是頁面路徑。

通過屬性配置文件include-packages需要統(tǒng)一返回包。exclude-packages不需統(tǒng)一返回的包

include-packages:?cn.soboys.superaide.controller
exclude-packages:?xx.xxx.xxx

錯(cuò)誤國際化支持

內(nèi)置常見的錯(cuò)誤??梢钥碒ttpStatus。默認(rèn)錯(cuò)誤支持中文和英文兩種國際化。配置如下

??i18n:
????#?若前端無header傳參則返回中文信息
????i18n-header:?Lang
????default-lang:?cn
????message:
??????#?admin
??????internal_server_error:
????????en:?Internal?Server?Error
????????cn:?系統(tǒng)錯(cuò)誤
??????bad_gateway:
????????en:?Bad?Gateway
????????cn:?錯(cuò)誤的請求
??????unauthorized:
????????en:?Unauthorized
????????cn:?未授權(quán)
??????forbidden:
????????en:?Forbidden
????????cn:?資源禁止訪問
??????method_not_allowed:
????????en:?Method?Not?Allowed
????????cn:?方法不被允許
??????request_timeout:
????????en:?Request?Timeout
????????cn:?請求超時(shí)
??????invalid_argument:
????????en:?Invalid?Argument?{}
????????cn:?參數(shù)錯(cuò)誤?{}
??????argument_analyze:
????????en:?Argument?Analyze?{}
????????cn:?參數(shù)解析異常?{}
??????business_exception:
????????en:?Business?Exception
????????cn:?業(yè)務(wù)錯(cuò)誤
??????not_found:
????????en:?Not?Found
????????cn:?請求資源不存在

可以自行覆蓋擴(kuò)充

全局錯(cuò)誤攔截和響應(yīng)

默認(rèn)攔所有未知錯(cuò)誤異常和validation參數(shù)校驗(yàn)失敗異常,以及Http請求異常。 還有全局自定義「BusinessException」 業(yè)務(wù)異常 自動集成spring-boot-starter-validation 你項(xiàng)目中不需要再單獨(dú)引入

<!--參數(shù)校驗(yàn)-->
<dependency>
????<groupId>org.springframework.boot</groupId>
????<artifactId>spring-boot-starter-validation</artifactId>
</dependency>

也內(nèi)置擴(kuò)展了許多自定義參數(shù)校驗(yàn)參考

第三方請求

有時(shí)候我們項(xiàng)目中需要調(diào)用第三方接口服務(wù)?;?code>RestTemplate 進(jìn)一步封裝了直接的POST,GET,請求。

在需要使用地方注入RestFulTemp

@Resource
private?RestFulTemp?restFulTemp;

GET請求

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

POST 請求

/**
?*?POST?請求參?數(shù)為body?json體格式
?*?@return
?*/

@PostMapping("/doPost")
public?Result?doPost()?{
????Student?s=new?Student();
????s.setHobby("swing");
????s.setNam("judy");
????//自動把對象轉(zhuǎn)換為JSON
????ResponseEntity<String>?response?=?
????????????restFulTemp.doPost("http://127.0.0.1:9000/redis/get",s);
????return?Result.buildSuccess();
}
/**
?*?POST請求?參數(shù)為FORM?表單參數(shù)
?*?@return
?*/

@PostMapping("/doPost")
public?Result?doPostForm()?{
????EntityParam?s=new?EntityParam();
????s.setAge(19);
????s.setHobby("swing");
????s.setName("judy");

????ResponseEntity<String>?response?=
????????????restFulTemp.doPostForm("http://127.0.0.1:8000/chat",?BeanUtil.beanToMap(s));
????return?Result.buildSuccess(response.getBody());
}

DELETE請求

@GetMapping("/doDelete")
public?Result?doDelete()?{
????restFulTemp.doDelete("http://127.0.0.1:8000/chat");
????return?Result.buildSuccess();
}

PUT請求

@GetMapping("/doPut")
public?Result?doPut()?{
????EntityParam?s=new?EntityParam();
????restFulTemp.doPut("http://127.0.0.1:8000/chat",s);
????return?Result.buildSuccess(s);
}

錯(cuò)誤異常自定義

我內(nèi)置錯(cuò)誤異常和業(yè)務(wù)異常可能無法滿足你自身接口業(yè)務(wù)異常需要。你可以自定義錯(cuò)誤異常類,和錯(cuò)誤響應(yīng)枚舉碼。

?

自定義錯(cuò)誤枚舉 需要實(shí)現(xiàn)「ResultCode」接口

?

package?cn.soboys.restapispringbootstarter;

import?cn.soboys.restapispringbootstarter.i18n.I18NKey;

/**
*?@author?公眾號?程序員三時(shí)
*?@version?1.0
*?@date?2023/6/26?10:21
*?@webSite?https://github.com/coder-amiao
*?響應(yīng)碼接口,自定義響應(yīng)碼,實(shí)現(xiàn)此接口
*/

public?interface?ResultCode?extends?I18NKey?{

???String?getCode();

???String?getMessage();

}

如果要支持國際化還需要實(shí)現(xiàn)國際化接口「I18NKey」 參考我內(nèi)部「HttpStatus」實(shí)現(xiàn)即可

package?cn.soboys.restapispringbootstarter;

import?cn.soboys.restapispringbootstarter.i18n.I18NKey;

/**
?*?@author?公眾號?程序員三時(shí)
?*?@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)部錯(cuò)誤
?????*/

????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)錯(cuò)誤
??????bad_gateway:
????????en:?Bad?Gateway
????????cn:?錯(cuò)誤的請求
??????unauthorized:
????????en:?Unauthorized
????????cn:?未授權(quán)
??????forbidden:
????????en:?Forbidden
????????cn:?資源禁止訪問
??????method_not_allowed:
????????en:?Method?Not?Allowed
????????cn:?方法不被允許
??????request_timeout:
????????en:?Request?Timeout
????????cn:?請求超時(shí)
??????invalid_argument:
????????en:?Invalid?Argument?{}
????????cn:?參數(shù)錯(cuò)誤?{}
??????argument_analyze:
????????en:?Argument?Analyze?{}
????????cn:?參數(shù)解析異常?{}
??????business_exception:
????????en:?Business?Exception
????????cn:?業(yè)務(wù)錯(cuò)誤
??????not_found:
????????en:?Not?Found
????????cn:?請求資源不存在

業(yè)務(wù)斷言

封裝了業(yè)務(wù)錯(cuò)誤斷言工具。Assert 遵循錯(cuò)誤優(yōu)先返回原則。

你要自定義自己的業(yè)務(wù)異常。繼承BusinessException重寫對應(yīng)方法

package?cn.soboys.restapispringbootstarter.exception;

import?cn.soboys.restapispringbootstarter.HttpStatus;
import?cn.soboys.restapispringbootstarter.ResultCode;
import?lombok.Data;

/**
?*?@author?公眾號?程序員三時(shí)
?*?@version?1.0
?*?@date?2023/6/26?16:45
?*?@webSite?https://github.com/coder-amiao
?*/

@Data
public?class?BusinessException?extends?RuntimeException?{

????/**
?????*?錯(cuò)誤碼
?????*/

????private?String?code="20000";

????/**
?????*?錯(cuò)誤提示
?????*/

????private?String?message;


????public?BusinessException(String?message)?{
????????this.message?=?message;

????}

????public?BusinessException(String?message,?String?code)?{
????????this.message?=?message;
????????this.code?=?code;

????}

????public?BusinessException(ResultCode?resultCode)?{
????????this.message?=?resultCode.getMessage();
????????this.code?=?resultCode.getCode();

????}
}

項(xiàng)目中日志是非常常用的,而且還是必須的。已經(jīng)自動配置集成spring-boot-starter-logging 你不需要在項(xiàng)目中單獨(dú)引入

<!--日志集成-->
<dependency>
????<groupId>org.springframework.boot</groupId>
????<artifactId>spring-boot-starter-logging</artifactId>
</dependency>

默認(rèn)日志配置

logging:
????path:?./logs???#日志存儲路徑(服務(wù)器上絕對)
????max-history:?90?#?保存多少天
????max-file-size:?3MB??#?每個(gè)文件大小
????max-total-size-cap:?1GB??#總文件大小超過多少壓縮
????level-root:?INFO????#?這里的INFO可以替換為其他日志等級,如DEBUG,?WARN,?ERROR,?TRACE,?FATAL,?OFF等。?日志等級由低到高分別是debugger-info-warn-error
????logDataSourceClass:?cn.soboys.restapispringbootstarter.log.LogFileDefaultDataSource?#?日志數(shù)據(jù)源

日志記錄與追蹤

RestFull API 統(tǒng)一返回有一個(gè)requestId 它是每個(gè)接口唯一標(biāo)識。用于接口請求日志鏈路追蹤。日志查詢。 如:

{
????"msg":?"操作成功",
????"code":?"OK",
????"previousPage":?1,
????"success":?true,
????"requestId":?"udYNdbbMFE45R84OPu9m",
????"nextPage":?1,
????"pageSize":?1,
????"totalPageSize":?1,
????"hasNext":?"false",
????"timestamp":?"2023-07-09?03:00:27",
????"info":?[
????????{
????????????"name":?"judy",
????????????"hobby":?"swing",
????????????"age":?18
????????}
????]
}

通過requestId你可以很輕松的在你的日志文件查詢定位到每次錯(cuò)誤的請求。

通過Log注解記錄你想要記錄請求

@PostMapping("/page")
@Log(value?=?"查詢用戶數(shù)據(jù)",apiType=?LogApiTypeEnum.USER,CURDType=?LogCURDTypeEnum.RETRIEVE)
public?Result?page(@Validated?EntityParam?s)?{
????ResultPage<List<EntityParam>>?resultPage=new?ResultPage<>();
????List?a=new?ArrayList();
????a.add(s);
????resultPage.setPageData(a);
????return?ResultPage.buildSuccess(resultPage);
}

?

系統(tǒng)默認(rèn)日志記錄數(shù)據(jù)源為日志文件。如

?

2023-07-09?03:00:32?INFO??http-nio-8000-exec-2?cn.soboys.restapispringbootstarter.log.LogFileDefaultDataSource?{
????"description":?"查詢用戶數(shù)據(jù)",
????"method":?"cn.soboys.restapispringbootstarter.controller.ApiRestController.page()",
????"logType":?"INFO",
????"time":?3,
????"result":?{
????????"success":?true,
????????"code":?"OK",
????????"msg":?"操作成功",
????????"requestId":?"udYNdbbMFE45R84OPu9m",
????????"timestamp":?"2023-07-09?03:00:27",
????????"data":?{
????????????"previousPage":?1,
????????????"nextPage":?1,
????????????"pageSize":?1,
????????????"totalPageSize":?1,
????????????"hasNext":?"false",
????????????"pageData":?[
????????????????{
????????????????????"name":?"judy",
????????????????????"hobby":?"swing",
????????????????????"age":?18
????????????????}
????????????],
????????????"requestId":?"qJTOejQmY-OOf7fagegB",
????????????"timestamp":?"2023-07-09?03:00:27"
????????}
????},
????"apiType":?"USER"
}
2023-07-09?03:08:03?INFO??http-nio-8000-exec-4?cn.soboys.restapispringbootstarter.log.LogFileDefaultDataSource?{
????"description":?"查詢用戶數(shù)據(jù)",
????"method":?"cn.soboys.restapispringbootstarter.controller.ApiRestController.page()",
????"logType":?"INFO",
????"time":?1,
????"result":?{
????????"success":?true,
????????"code":?"OK",
????????"msg":?"操作成功",
????????"requestId":?"kP3yPP-H7wI2x1ak6YFA",
????????"timestamp":?"2023-07-09?03:00:27",
????????"data":?{
????????????"previousPage":?1,
????????????"nextPage":?1,
????????????"pageSize":?1,
????????????"totalPageSize":?1,
????????????"hasNext":?"false",
????????????"pageData":?[
????????????????{
????????????????????"name":?"judy",
????????????????????"hobby":?"swing",
????????????????????"age":?18
????????????????}
????????????],
????????????"requestId":?"pGbbiEj8GQ1eTxQpF2Jr",
????????????"timestamp":?"2023-07-09?03:00:27"
????????}
????},
????"apiType":?"USER"
}

你可以自定義自己的日志數(shù)據(jù)源實(shí)現(xiàn)LogDataSource接口 日志操作支持異步。需要在配置類。或者啟動類加上@EnableAsync注解

package?cn.soboys.restapispringbootstarter.log;

import?org.springframework.scheduling.annotation.Async;

import?java.util.Map;

/**
?*?@Author:?kenx
?*?@Since:?2021/6/23?13:55
?*?@Description:
?*/

public?interface?LogDataSource?{

????/**
?????*?獲取拓展數(shù)據(jù)
?????*?@return
?????*?@param?logEntry
?????*/

????@Async
????void??save(LogEntry?logEntry);
}

或者你可以繼承我默認(rèn)的日志數(shù)據(jù)源實(shí)現(xiàn)類LogFileDefaultDataSource 重寫save(LogEntry logEntry)方法。

@Slf4j
public?class?LogFileDefaultDataSource?implements?LogDataSource?{

????/**
?????*?自定義保存數(shù)據(jù)源
?????*
?????*?@param
?????*?@return?LogEntry
?????*/

????@Override
????public?void?save(LogEntry?logEntry)?{
????????log.info(JSONUtil.toJsonPrettyStr(logEntry));
????}
}

?

如果是自定義日志數(shù)據(jù)源實(shí)現(xiàn)需要再配置文件,配置日志數(shù)據(jù)源。如:

?

logging:
????path:?./logs???#日志存儲路徑(服務(wù)器上絕對)
????max-history:?90?#?保存多少天
????max-file-size:?3MB??#?每個(gè)文件大小
????max-total-size-cap:?1GB??#總文件大小超過多少壓縮
????level-root:?INFO????#?這里的INFO可以替換為其他日志等級,如DEBUG,?WARN,?ERROR,?TRACE,?FATAL,?OFF等。?日志等級由低到高分別是debugger-info-warn-error
????logDataSourceClass:?cn.soboys.restapispringbootstarter.log.LogFileDefaultDataSource?#?日志數(shù)據(jù)源

緩存和redis

項(xiàng)目中緩存使用是非常常見的。用的最多的是基于Redis緩存。于是我封裝了對于RedisKey和Value常用操作。

::: tip 默認(rèn)不引入Redis依賴,如果要使用Redis需要自己單獨(dú)引入 :::

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

項(xiàng)目使用

注入redisTempUtil

@Autowired
private?RedisTempUtil?redisTempUtil;

如示列

@Autowired
private?RedisTempUtil?redisTempUtil;

@GetMapping("/redis")
public?Result?chatDialogue(?)?{
????redisTempUtil.set("test","111");
????redisTempUtil.get("test");
????redisTempUtil.set("user","userObj",7200l);
????redisTempUtil.getAllKey("xx");??//*表達(dá)式
????redisTempUtil.clean();
????redisTempUtil.deleteObject("test");
????redisTempUtil.hasKey("");
????return?Result.buildSuccess();
}

統(tǒng)一緩存管理

上面我們是直接通過工具類redisTempUtil直接自己定義key然后去存儲,這種方式是不可取的如果key很多隨意定義就會很混亂。我提供了統(tǒng)一緩存key管理接口CacheTmp 參考實(shí)現(xiàn)CacheKey 基于枚舉形式,把所有key集中管理

package?cn.soboys.restapispringbootstarter.cache;

import?lombok.Getter;

/**
?*?@author?公眾號?程序員三時(shí)
?*?@version?1.0
?*?@date?2023/7/2?11:04
?*?@webSite?https://github.com/coder-amiao
?*?緩存枚舉
?*/

@Getter
public?enum?CacheKey?implements?CacheTmp?{


????//?密碼的重置碼
????PWD_RESET_CODE("reset:code:",?true),
????;

????private?String?key;

????/**
?????*?Key是否是Key前綴,?true時(shí)直接取key=key,如果false時(shí)key=key+suffix
?????*/

????private?boolean?hasPrefix;

????CacheKey(String?key,?boolean?hasPrefix)?{
????????this.key?=?key;
????????this.hasPrefix?=?hasPrefix;
????}


????@Override
????public?Boolean?getHasPrefix()?{
????????return?this.hasPrefix;
????}

????@Override
????public?String?getKey()?{
????????return?this.key;
????}

}

使用

  1. 存儲對于key

@GetMapping("/redis")
public?Result?chatDialogue()?{
????CacheKey.PWD_RESET_CODE.valueSetAndExpire("test",?60l,?TimeUnit.SECONDS,?"judy");
????return?Result.buildSuccess();
}

  1. 獲取對應(yīng)的key

@GetMapping("/redis/get")
public?Result?redisGet()?{
????String?a?=?CacheKey.PWD_RESET_CODE.valueGet("judy");
????return?Result.buildSuccess(a);
}

spring Cache實(shí)現(xiàn)

封裝了spring Cache進(jìn)一步使用 項(xiàng)目中在配置類或者啟動類通過注解@EnableCaching開啟直接使用即可

@Cacheable(cacheNames?=?"testCache",?keyGenerator?=?"keyGeneratorStrategy")
@GetMapping("/redis/springCache")
public?Result?springCache()?{
????String?a?=?"test?cache";
????return?Result.buildSuccess(a);
}

工具類使用springCacheUtil 支持提供不是基于注解的使用方式

@GetMapping("/redis/springCache")
public?Result?redisSpringCache()?{
????String?a?=?"111344";
????springCacheUtil.putCache("test","key","121e1");
????return?Result.buildSuccess(a);
}

::: tip 默認(rèn)不引入Redis依賴,緩存基于內(nèi)存實(shí)現(xiàn)(你項(xiàng)目引入redis依賴后會自定切換數(shù)據(jù)源為Redis緩存) :::

redis配置

多個(gè)項(xiàng)目或者模塊使用一個(gè)key可能會造成混亂,于是提供了一個(gè)全局配置key。

??redis:
????key-prefix:?rest?

代碼中添加一個(gè) String 類型的 key:testKey,其實(shí)際在 redis 中存儲的 key name 為 rest:testKey

全局 key 前綴的配置,并不影響對 key 的其他操作,例如獲取對應(yīng)的 value 時(shí),依然是傳入 testKey,而不是 rest:testKey

String?key?=?"testKey";
String?value?=?redisTempUtil.get(key);
String?value1?=?CacheKey.PWD_RESET_CODE.valueGet(key);

OpenApi文檔生成

已經(jīng)內(nèi)置自動支持。swagger文檔。和最新的OpenApi3 文檔。項(xiàng)目啟動后即可訪問。

  1. swagger-ui.html 文檔。路徑/swagger-ui.html

  2. 基于spring-doc 文檔UI增強(qiáng) 路徑/doc.html

  3. 接口文檔屬性信息

??openapi:
????description:
????title:
????version:
????license:?
????contact:
??????name:
??????email:
??????url:?

  • 啟動項(xiàng)目后,訪問 http://server:port/context-path/swagger-ui.html 即可進(jìn)入 Swagger UI 頁面,OpenAPI 描述將在以下 json 格式的 url 中 提供:http://server:port/context-path/v3/api-docs

  • server:域名 或 IP

  • port:服務(wù)器端口

  • context-path:應(yīng)用程序的上下文路徑,springboot 默認(rèn)為空

  • 文檔也可以 yaml 格式提供,位于以下路徑:/v3/api-docs.yaml

如果嫌棄官方提供的 swagger-ui 不美觀,或者使用不順手,可以選擇關(guān)閉 ui,還可以剔除掉 ui 相關(guān)的 webjar 的引入。

springdoc:
??swagger-ui:
????enabled:?false

OpenAPI 文檔信息,默認(rèn)可在此 url 中獲取: http://server:port/context-path/v3/api-docs。 可以利用其他支持 OpenAPI 協(xié)議的工具,通過此地址,進(jìn)行 API 展示,如 Apifox。 ( Postman 的 api 測試也可以利用此地址進(jìn)行導(dǎo)入生成 )

Knife4j (原 swagger-bootstrap-ui) 3.x 版本提供了對于 OpenAPI 協(xié)議的部分支持。

::: tip Knife4j 很多地方?jīng)]有按照協(xié)議規(guī)范實(shí)現(xiàn),所以使用起來會有很多問題,另外項(xiàng)目也很久沒有維護(hù)了,不推薦使用。 :::

?

由于 knife4j 對于規(guī)范支持的不全面,無法直接使用單文檔源數(shù)據(jù),所以必須進(jìn)行分組或者 urls 的指定。

?

#?urls
springdoc:
??swagger-ui:
????urls:
??????-?{?name:?'sample',?url:?'/v3/api-docs'?}

或者

#分組
springdoc:
??group-configs:
????-?{?group:?'sample',?packages-to-scan:?'com.example'?}

Knife4j 的 UI 訪問地址有所不同,頁面映射在 doc.html 路徑下,啟動項(xiàng)目后,訪問 http://server:port/context-path/doc.html

即可進(jìn)入 Knife4j 的 Swagger UI 頁面。

代碼自動生成

項(xiàng)目中我們使用mybatis 或者mybatisPlus 一些簡單的單表業(yè)務(wù)代碼,增刪改成。我們可以一鍵生成。不需要重復(fù)寫。 我封裝了mybatisPlus 代碼生成工具

::: tip 默認(rèn)不引入mybatisPlus代碼生成依賴,如果要使用mybatisPlus代碼生成需自行單獨(dú)引入 :::

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

項(xiàng)目使用

  1. 代碼生成配置類

package?cn.soboys.restapispringbootstarter.config;

import?lombok.Data;

/**
?*?@author?公眾號?程序員三時(shí)
?*?@version?1.0
?*?@date?2023/7/5?00:05
?*?@webSite?https://github.com/coder-amiao
?*/

@Data
public?class?GenerateCodeConfig?{
????/**
?????*?數(shù)據(jù)庫驅(qū)動
?????*/

????private?String?driverName;
????/**
?????*?數(shù)據(jù)庫連接用戶名
?????*/

????private?String?username;
????/**
?????*?數(shù)據(jù)庫連接密碼
?????*/

????private?String?password;
????/**
?????*?數(shù)據(jù)庫連接url
?????*/

????private?String?url;
????/**
?????*?生成代碼?保存路徑。默認(rèn)當(dāng)前項(xiàng)目下。
?????*?如需修改,使用絕對路徑
?????*/

????private?String?projectPath;
????/**
?????*?代碼生成包位置
?????*/

????private?String?packages;
}

示列如:

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);
????}
}

常見問題

在使用過程中盡量使用最新版本。我會持續(xù)更新更多的內(nèi)容。 會第一時(shí)間發(fā)布在我的公眾號 程序員三時(shí)。全網(wǎng)同名

可以關(guān)注 公眾號 「程序員三時(shí)」。用心分享持續(xù)輸出優(yōu)質(zhì)內(nèi)容。希望可以給你帶來一點(diǎn)幫助


我開源了團(tuán)隊(duì)內(nèi)部基于SpringBoot Web快速開發(fā)的API腳手架stater的評論 (共 條)

分享到微博請遵守國家法律
木兰县| 龙川县| 扶沟县| 阿拉善右旗| 凌海市| 宜宾县| 潍坊市| 定结县| 万安县| 楚雄市| 大城县| 武邑县| 通渭县| 嵊泗县| 安义县| 星子县| 宜都市| 垦利县| 贵德县| 雷山县| 连江县| 延长县| 炎陵县| 泰和县| 怀远县| 会东县| 张家界市| 南充市| 孝义市| 赤壁市| 建德市| 昂仁县| 北辰区| 响水县| 始兴县| 澎湖县| 康保县| 正镶白旗| 民勤县| 延边| 收藏|