偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

實(shí)戰(zhàn)!魔改 Swagger,Knife4j的另外一種打開(kāi)方式

開(kāi)發(fā) 前端
swagger-spring-boot-starter是客戶端組件,微服務(wù)客戶端使用封裝好的該組件掃描項(xiàng)目中的swagger信息并上傳到swagger注冊(cè)中心。

哈嘍大家好,我是阿Q!

之前公司使用了swagger作為文檔管理工具,原生的swagger-ui非常丑,后來(lái)改用了開(kāi)源項(xiàng)目 蕭明 / knife4j 的swagger組件進(jìn)行了swagger渲染,改造之后界面漂亮多了,操作也方便了很多。

當(dāng)然這不是重點(diǎn),重點(diǎn)是我們項(xiàng)目引用了knife4j之后出現(xiàn)的一些問(wèn)題:

  • 由于項(xiàng)目中使用了spring security,使用了knife4j之后,需要對(duì)knife4j單獨(dú)做規(guī)則過(guò)濾,否則無(wú)法訪問(wèn)knife4j的靜態(tài)資源
  • 無(wú)論是knife4j還是原來(lái)的swagger-ui,只要服務(wù)一停止,swagger文檔就打不開(kāi)了
  • 同一個(gè)項(xiàng)目下不同的人想要展示不同的文檔,特別是在開(kāi)發(fā)階段,前端同學(xué)需要保存多個(gè)swagger地址查看不同的文檔
  • 集成knife4j實(shí)際上對(duì)于項(xiàng)目來(lái)說(shuō)是比較重的,每個(gè)微服務(wù)都搞一遍也增加了工作量
  • ......

兩種文檔聚合模式

gateway 文檔聚合模式

有人在gateway處做了文檔聚合,它的聚合模式如下圖所示

它的原理很簡(jiǎn)單,就是將請(qǐng)求轉(zhuǎn)發(fā)到微服務(wù),從微服務(wù)的restful接口中獲取swagger的json信息,然后通過(guò)前端將swagger信息渲染出來(lái)。

這樣做的好處就是只需要在網(wǎng)關(guān)處集成swagger-ui,其它微服務(wù)不需要再單獨(dú)集成,只需要收集swagger信息然后暴露接口給gateway,等著gateway來(lái)取信息即可。但是它沒(méi)有完全解決上面提到的問(wèn)題,而且還引入了新的問(wèn)題

  • 網(wǎng)關(guān)做文檔聚合到底合不合理?本身來(lái)說(shuō)網(wǎng)關(guān)是對(duì)外暴露的,這種接口文檔有可能會(huì)被泄露給普通用戶,而且個(gè)人認(rèn)為在網(wǎng)關(guān)處做這個(gè)不符合網(wǎng)關(guān)的定位
  • 這種模式無(wú)法解決開(kāi)發(fā)階段文檔問(wèn)題,開(kāi)發(fā)階段文檔是會(huì)隨時(shí)更新的,這種模式需要將其發(fā)布到正式環(huán)境才能查看文檔
  • 還是要在spring security加白名單,放開(kāi)swagger對(duì)外的restful接口
  • 無(wú)法解決同一個(gè)項(xiàng)目不同文檔的問(wèn)題

針對(duì)這個(gè)問(wèn)題,我想了想,使用另外一種方式嘗試著進(jìn)行改造。

集中注冊(cè)模式

好吧,這個(gè)名字我瞎起的。具體技術(shù)架構(gòu)如下圖所示

系統(tǒng)流程如下:

  • 每個(gè)微服務(wù)啟動(dòng)的時(shí)候從nacos、eureka等注冊(cè)中心獲取swagger注冊(cè)中心服務(wù)的注冊(cè)信息,然后調(diào)用swagger注冊(cè)中心的接口,將swagger信息保存到數(shù)據(jù)庫(kù)
  • swagger注冊(cè)中心集成knife4j,本身也是一個(gè)單獨(dú)的微服務(wù),其連接數(shù)據(jù)庫(kù)并管理swagger文檔
  • 用戶只能內(nèi)網(wǎng)訪問(wèn)swagger注冊(cè)中心,swagger注冊(cè)中心從數(shù)據(jù)庫(kù)取出swagger文檔信息并通過(guò)knife4j渲染

需要注意的是swagger注冊(cè)中心只部署開(kāi)發(fā)環(huán)境或者公司局域網(wǎng)環(huán)境,我們公司局域網(wǎng)能直接訪問(wèn)開(kāi)發(fā)環(huán)境。

集中注冊(cè)模式的代碼設(shè)計(jì)如下,這里搞兩個(gè)單獨(dú)的項(xiàng)目

項(xiàng)目名

功能

swagger-spring-boot-starter

客戶端組件,微服務(wù)客戶端使用封裝好的該組件掃描項(xiàng)目中的??swagger??信息并上傳到??swagger??注冊(cè)中心

swagger-register-server

??swagger??注冊(cè)中心,它接收微服務(wù)客戶端上傳的??swagger??信息并保存到數(shù)據(jù)庫(kù)。用戶請(qǐng)求查看文檔的時(shí)候直接從數(shù)據(jù)庫(kù)中取??swagger??文檔

在一切開(kāi)始之前,需要了解下swagger-ui的實(shí)現(xiàn)原理

swagger-ui 實(shí)現(xiàn)原理

/v2/api-docs 接口

正如之前所說(shuō),swagger-spring-boot-starter是客戶端組件,微服務(wù)客戶端使用封裝好的該組件掃描項(xiàng)目中的swagger信息并上傳到swagger注冊(cè)中心。

關(guān)鍵的技術(shù)點(diǎn)是如何手動(dòng)掃描項(xiàng)目的swagger信息。只要能拿到swagger信息,無(wú)論使用什么方式上傳到swagger注冊(cè)中心都很簡(jiǎn)單了。

關(guān)于這個(gè)技術(shù)點(diǎn)想了一會(huì)兒沒(méi)想到好辦法,只能去看源代碼,看了一會(huì)兒覺(jué)得云里霧里的,最終突然靈光一閃,swagger-ui的實(shí)現(xiàn)給了我靈感。

swagger-ui會(huì)請(qǐng)求后端一個(gè)接口獲取swagger文檔:/v2/api-docs,然后根據(jù)拿到的swagger文檔渲染前端頁(yè)面。在intelij下ctrl+shift+f組合鍵搜索該關(guān)鍵字很容易能夠找到相關(guān)代碼(springfox 2.9.2):

springfox.documentation.swagger2.web.Swagger2Controller#getDocumentation

這段代碼詳細(xì)講解了如何獲取Swagger對(duì)象,這給我的實(shí)現(xiàn)提供了很大的參考依據(jù)。

/swagger-resources接口

源碼解析

在通過(guò)網(wǎng)關(guān)聚合模式下查看swagger文檔的時(shí)候,會(huì)發(fā)現(xiàn)前端會(huì)請(qǐng)求后端一個(gè)接口獲取所有的group信息:/swagger-resources,老規(guī)矩,還是ctrl+shift+f快捷鍵全局查詢,可以看到相關(guān)代碼的實(shí)現(xiàn)

springfox.documentation.swagger.web.ApiResourceController#swaggerResources

可以看到,該接口僅僅是調(diào)用了swaggerResource的get方法,然后就直接返回了,那就再看看swaggerResource是什么東西

它只是個(gè)接口,那它的實(shí)現(xiàn)類(lèi)呢,它的實(shí)現(xiàn)類(lèi)只有一個(gè),就是InMemorySwaggerResourcesProvider類(lèi)

它的GET方法是這樣子的

看到這里我不禁陷入了思考,難道要給documentationCache手動(dòng)填充文檔?但是看這個(gè)名字就知道是基于內(nèi)存的東西,要維護(hù)CRUD狀態(tài)似乎有點(diǎn)麻煩,看看這個(gè)代碼是咋寫(xiě)的

確實(shí)是基于內(nèi)存的東西,但是只提供了add方法,沒(méi)提供remove方法,那獲取到documentionLookup對(duì)象之后手動(dòng)移除呢?仔細(xì)看看all()方法

它被Collections工具類(lèi)包裝成了不可修改的了,那手動(dòng)移除的方式就沒(méi)戲了......

換一種思路,其實(shí)還有另外一種方法,重新實(shí)現(xiàn)SwaggerResourcesProvider接口,并將實(shí)現(xiàn)類(lèi)使用@Primary注解修飾,覆蓋默認(rèn)的InMemorySwaggerResourcesProvider實(shí)現(xiàn)類(lèi),重寫(xiě)get()方法即可。

那這時(shí)候的自由度就大了去了,這里可以直接使用從數(shù)據(jù)庫(kù)讀的方式獲取所有的group。

返回值解析

/swagger-resources接口的返回值是List類(lèi)型,SwaggerResource類(lèi)的定義如下

  • name:顯示的名字
  • url:前端根據(jù)該url獲取swagger文檔詳情(默認(rèn)是/v2/api-docs,其實(shí)可以修改該值讓swagger-ui請(qǐng)求自定義的接口獲取swagger文檔)
  • swaggerVersion:就是swagger版本,一般就是2.0

在繼續(xù)往下學(xué)習(xí)之前先來(lái)張圖感受下,便于大家的理解:

注冊(cè)中心

項(xiàng)目源代碼:https://gitee.com/kdyzm/swagger-register-server

它是一個(gè)swagger注冊(cè)中心,對(duì)swagger文檔進(jìn)行持久化并進(jìn)行CRUD操作,最終在knife4j中展示。它應(yīng)當(dāng)包含如下功能

  • 接收客戶端傳來(lái)的swagger文檔信息并保存到數(shù)據(jù)庫(kù)
  • 集成knife4j并展示文檔
  • 提供knife4j前端頁(yè)面/swagger-resources接口邏輯實(shí)現(xiàn)
  • 提供knife4j前端頁(yè)面獲取文檔詳情接口
  • 能夠動(dòng)態(tài)更新文檔

表結(jié)構(gòu)設(shè)計(jì)

設(shè)計(jì)上,用兩張表分別存儲(chǔ)group信息和文檔詳情信息

CREATE TABLE `group_info` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '自增主鍵',
`name` varchar(64) NOT NULL COMMENT 'groupName',
`location` varchar(128) NOT NULL COMMENT 'location',
`version` varchar(16) NOT NULL COMMENT 'version',
`url` varchar(128) NOT NULL COMMENT 'url',
`app_name` varchar(64) DEFAULT NULL COMMENT '服務(wù)名(spring.application.name)',
`gateway` varchar(64) DEFAULT NULL COMMENT '網(wǎng)關(guān),無(wú)則不填',
PRIMARY KEY (`id`),
UNIQUE KEY `group_info_name` (`name`) COMMENT 'group name唯一',
UNIQUE KEY `group_info_app_name` (`app_name`) COMMENT 'appname唯一'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE `swagger_json` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`group_name` varchar(64) NOT NULL,
`content` longtext NOT NULL COMMENT 'swagger具體信息',
PRIMARY KEY (`id`),
UNIQUE KEY `swagger_json_groupname` (`group_name`) COMMENT 'groupName唯一'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

group_info表用于存儲(chǔ)swagger的group信息,/swagger-resources接口將會(huì)從該表中取group數(shù)據(jù)

swagger_json表用于存儲(chǔ)swagger的原始信息,用于文檔渲染。

接收注冊(cè)接口

swagger-register-server中SwaggerRegisterController的regist()方法

對(duì)應(yīng)以上兩個(gè)表,注冊(cè)接口有兩個(gè)實(shí)體類(lèi)。注冊(cè)邏輯是:存在則更新,不存在就新增,groupName和appName都要保持唯一。

獲取swagger詳情接口

swagger-register-server中SwaggerRegisterController的getSwaggerDetail()方法

默認(rèn)值是/v2/api-docs,但是可以自定義,這里要求客戶端在注冊(cè)的時(shí)候就約定好接口路徑是/swagger/detail。

該接口從數(shù)據(jù)庫(kù)中獲取swagger信息。

獲取resources列表接口

從之前的/swagger-resources源碼分析過(guò),想要從數(shù)據(jù)庫(kù)自定義獲取group列表,就需要重新實(shí)現(xiàn)SwaggerResourcesProvider接口并且標(biāo)記為@Primary

swagger-register-server中DocumentationConfig

創(chuàng)建 starter

項(xiàng)目源代碼:https://gitee.com/kdyzm/swagger-spring-boot-starter

設(shè)計(jì)上,要求做到微服務(wù)客戶端只需要引入組件jar包,然后配置文件配置一些swagger的基本信息,服務(wù)啟動(dòng)之后就能自動(dòng)上傳swagger文檔到swagger注冊(cè)中心,具體技術(shù)細(xì)節(jié),應(yīng)當(dāng)包含如下功能

  • 能夠?qū)崿F(xiàn)swagger文檔的完整上傳,其效果和直接請(qǐng)求本地的/v2/api-docs一樣
  • 支持服務(wù)發(fā)現(xiàn)swagger注冊(cè)中心以及swagger注冊(cè)中心url配置兩種方式
  • 客戶端能夠以springboot starter方式自動(dòng)配置實(shí)現(xiàn)無(wú)代碼侵入式生效
  • swagger-spring-boot-starter客戶端組件同時(shí)兼容eureka和nacos

swagger文檔的掃描和上傳

上面分析過(guò)/v2/api-docs的實(shí)現(xiàn)原理,利用它的實(shí)現(xiàn)原理,可以輕松獲取到Swagger對(duì)象

swagger-spring-boot-starter中SwaggerMvcGenerator的getSwagger()方法

上傳的話,根據(jù)配置文件中是否配置serverUrl決定采用服務(wù)發(fā)現(xiàn)方式還是直接請(qǐng)求方式上傳Swagger信息

swagger-spring-boot-starter中SwaggerRegistryService的registry()方法

springboot starter支持

這個(gè)非常簡(jiǎn)單,在resources/META-INF目錄下新建文件并配置好即可。

兼容注冊(cè)中心

swagger-spring-boot-starter不依賴(lài)nacos client或者eurka client,而是依賴(lài)了它們的公共接口模塊spring-cloud-commons。

實(shí)際上nacos client或者eureka client均是該模塊的具體實(shí)現(xiàn),所以swagger-spring-boot-starter可以兼容兩種客戶端服務(wù)發(fā)現(xiàn)組件的實(shí)現(xiàn),但是服務(wù)端因?yàn)榫唧w依賴(lài)了某種服務(wù)發(fā)現(xiàn)組件,在我這里默認(rèn)使用nacos,如果要用eureka需要自行改造。

實(shí)戰(zhàn)

這篇文章介紹的兩個(gè)項(xiàng)目的源代碼地址:

項(xiàng)目名稱(chēng)

項(xiàng)目地址

??swagger-register-server??

https://gitee.com/kdyzm/swagger-register-server

??swagger-spring-boot-starter??

https://gitee.com/kdyzm/swagger-spring-boot-starter

啟動(dòng)swagger注冊(cè)中心

該項(xiàng)目啟動(dòng)需要連接mysql數(shù)據(jù)庫(kù)以及nacos

  • nacos我搭建了一個(gè)在線版本,可以直接使用(這里不提供管理端的賬號(hào)密碼),nacos在線地址:nacos.kdyzm.cn
  • mysql需要自己創(chuàng)建數(shù)據(jù)庫(kù),運(yùn)行腳本創(chuàng)建相關(guān)的數(shù)據(jù)庫(kù)和表結(jié)構(gòu)以及初始化部分?jǐn)?shù)據(jù)。

腳本地址:https://gitee.com/kdyzm/swagger-register-server/blob/master/sql/init.sql

準(zhǔn)備好外部依賴(lài)之后,執(zhí)行sql文件夾中的sql文件,最后啟動(dòng)項(xiàng)目即可,啟動(dòng)成功之后,訪問(wèn)項(xiàng)目的/doc.html,即可看到knife4j的文檔頁(yè)面。

這里我提供了線上部署好的版本:http://swagger.kdyzm.cn

編譯打包 starter

上一步啟動(dòng)好了swagger-register-server,接下來(lái)需要打包swagger-spring-boot-starter以供微服務(wù)客戶端使用。

因?yàn)檫@里并沒(méi)有上傳maven中央倉(cāng)庫(kù),所以有條件的可以上傳nexus私服,沒(méi)條件的可以直接運(yùn)行命令mvn clean install將jar包安裝到本地maven倉(cāng)庫(kù)以便使用。

創(chuàng)建測(cè)試項(xiàng)目

可以使用intelij自帶的工具初始化一個(gè)spring boot的項(xiàng)目,這里使用了2.3.4.REALEASE版本的springboot版本號(hào)(經(jīng)過(guò)測(cè)試發(fā)現(xiàn),nacos版本號(hào)過(guò)高會(huì)導(dǎo)致服務(wù)發(fā)現(xiàn)功能故障,版本號(hào)低一些程序功能會(huì)更穩(wěn)定)。

利用intilij自帶的spring initiallizer工具可以很方便的快速搭建起來(lái)web開(kāi)發(fā)框架。寫(xiě)完Controller接口之后,開(kāi)始整合swagger-spring-boot-starter。

測(cè)試項(xiàng)目地址源代碼:https://gitee.com/kdyzm/swagger-spring-boot-starter-test

第一步:引入依賴(lài)

<!-- swagger功能組件 -->
<dependency>
<groupid>com.kdyzm</groupid>
<artifactid>swagger-spring-boot-starter</artifactid>
<version>1.0-SNAPSHOT</version>
</dependency>

第二步:配置swagger信息

在配置文件中新增配置

swagger:
config:
#每個(gè)人只關(guān)心自己的包名,方便和前端文檔對(duì)接
base-package: com.kdyzm.swagger.test
description: swagger測(cè)試項(xiàng)目
group:
#swagger注冊(cè)唯一標(biāo)識(shí),每個(gè)人都要不一樣
appName: ${spring.application.name}
name: swagger測(cè)試項(xiàng)目
api:
title: swagger測(cè)試項(xiàng)目
contactName: kdyzm@foxmail.com
#swagger注冊(cè)中心地址,指定了server-url就優(yōu)先使用該地址注冊(cè)swagger文檔信息;未指定則順延使用服務(wù)發(fā)現(xiàn)模式
server-url: http://swagger.kdyzm.cn
#swgger注冊(cè)中心serviceId,即servername,用于服務(wù)發(fā)現(xiàn)模式
service-id: swagger-register-server

第三步:激活

只是做了前兩步,不會(huì)對(duì)項(xiàng)目產(chǎn)生任何影響,也不會(huì)產(chǎn)生swagger文檔,必須激活swagger profile才會(huì)生效。

項(xiàng)目啟動(dòng)之后如果沒(méi)有任何報(bào)錯(cuò),打開(kāi)文檔地址:http://swagger.kdyzm.cn/doc.html查看文檔上傳效果。

其它問(wèn)題

公益地址問(wèn)題

還有swagger注冊(cè)中心地址

服務(wù)名字

域名

訪問(wèn)地址

nacos地址

nacos.kdyzm.cn

http://nacos.kdyzm.cn/nacos (不提供管理端賬號(hào)密碼)

eureka地址

eureka.kdyzm.cn

http://eureka.kdyzm.cn (無(wú)需賬號(hào)密碼訪問(wèn))

swagger注冊(cè)中心地址

swagger.kdyzm.cn

http://swagger.kdyzm.cn/doc.html (無(wú)需賬號(hào)密碼訪問(wèn))

由于受限于資源和網(wǎng)絡(luò)帶寬,訪問(wèn)速度會(huì)比較慢;請(qǐng)善待公共資源,不要對(duì)它們進(jìn)行壓測(cè)和其它非正常操作。

模式切換

配置文件中有個(gè)配置項(xiàng):swagger.config.server-url ,若該配置項(xiàng)不為空,則走直連模式,即不通過(guò)服務(wù)發(fā)現(xiàn)直接請(qǐng)求該server-url上傳swagger文檔;

如果未配置該配置項(xiàng),則檢查swagger.config.service-id字段,如果該字段也沒(méi)有配置值,則報(bào)錯(cuò)并跳過(guò)swagger文檔上傳。

配置唯一性

為了能在分組里唯一區(qū)分,必須要將appName和name保持唯一,而且現(xiàn)在上傳文檔之后不支持刪除,如果誤上傳到了swagger.kdyzm.cn,發(fā)郵件給我我來(lái)刪除,我的郵箱地址:kdyzm@foxmail.com

源代碼

原本分了兩個(gè)單獨(dú)的項(xiàng)目,維護(hù)起來(lái)不是很方便

項(xiàng)目名稱(chēng)

項(xiàng)目地址

swagger-register-server

https://gitee.com/kdyzm/swagger-register-server

swagger-spring-boot-starter

https://gitee.com/kdyzm/swagger-spring-boot-starter

所以現(xiàn)在再加上實(shí)戰(zhàn)案例放到同一個(gè)項(xiàng)目中進(jìn)行管理。

三合一項(xiàng)目地址:

項(xiàng)目

地址

gitee地址

https://gitee.com/kdyzm/swagger-knife4j-spring-boot-starter

github地址

https://github.com/kdyzm/swagger-knife4j-spring-boot-starter

以后的更新均會(huì)放到該項(xiàng)目中進(jìn)行。


責(zé)任編輯:武曉燕 來(lái)源: 阿Q說(shuō)代碼
相關(guān)推薦

2021-03-22 08:02:16

WordKnife4jSwagger

2016-03-01 14:51:18

云計(jì)算DevOps

2019-02-20 14:35:57

區(qū)塊鏈數(shù)字貨幣比特幣

2016-01-08 11:00:14

OpenStack云計(jì)算

2022-03-22 07:37:04

FeignSpringRibbon

2023-06-28 13:44:31

企業(yè)AI

2023-07-10 09:38:06

兼容性測(cè)試方案

2017-08-02 10:43:39

深度學(xué)習(xí)TensorFlowRNN

2021-11-05 12:46:47

定位技術(shù)藍(lán)牙無(wú)線技術(shù)

2021-11-25 07:43:56

CIOIT董事會(huì)

2021-10-22 09:25:55

AndroidWindows 11瀏覽器

2017-12-25 10:40:01

Python單例字典模塊

2021-06-15 11:44:01

芯片

2025-04-30 08:20:58

2021-11-10 16:03:42

Pyecharts Python可視化

2011-07-28 15:47:18

組策略

2021-10-26 16:18:03

網(wǎng)絡(luò)安全/智能邊緣安全

2021-10-09 15:49:00

5G網(wǎng)絡(luò)技術(shù)

2018-10-29 15:20:03

點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)