springboot微服務整合swagger3方法很簡單,下文會演示。但是在分散式項目中如果每個微服務都需要單獨的分開訪問獲取介面文檔就不方便了,本文將詳細講解springcloud gateway網關如何聚合統一管理swagger介面文檔。 先貼張整合後的效果圖(通過切換左上角的下拉視窗獲取每個微 ...
springboot微服務整合swagger3方法很簡單,下文會演示。但是在分散式項目中如果每個微服務都需要單獨的分開訪問獲取介面文檔就不方便了,本文將詳細講解springcloud gateway網關如何聚合統一管理swagger介面文檔。
先貼張整合後的效果圖(通過切換左上角的下拉視窗獲取每個微服務的介面文檔):
一、swagger簡介
- 基於 OpenAPI 規範(OpenAPI Specification,OAS)構建的開源介面文檔自動生成工具,可以讓開發人員快速設計、構建、記錄以及使用 Rest API。
- 目前的版本有swagger2.0和3.0,swagger2於17年停止維護,現在最新的版本為17年發佈的 Swagger3(Open Api3)。
- Swagger 主要包含了以下三個部分:
-
- Swagger Editor:基於瀏覽器的編輯器,我們可以使用它編寫我們 OpenAPI 規範。
- Swagger UI:它會將我們編寫的 OpenAPI 規範呈現為互動式的 API 文檔,後文我將使用瀏覽器來查看並且操作我們的 Rest API。
- Swagger Codegen:它可以通過為 OpenAPI(以前稱為 Swagger)規範定義的任何 API 生成伺服器存根和客戶端 SDK 來簡化構建過程。
- SpringFox介紹(是 spring 社區維護的一個非官方項目)
-
- 是一個開源的API Doc的框架,Marty Pitt編寫了一個基於Spring的組件swagger-springmvc,用於將swagger集成到springmvc中來, 它的前身是swagger-springmvc,可以將我們的Controller中的方法以文檔的形式展現。官方定義為: Automated JSON API documentation for API's built with Spring。
二、Springboot2.x整合Swagger3.x
首先看下單體微服務是如何整合swagger3的,事實上這也是後面gateway網關聚合統一文檔的步驟之一。
步驟一:
SpringBoot添加pom文件依賴
<dependency> <groupId>io.springfox</groupId> <artifactId>springfox-boot-starter</artifactId> <version>3.0.0</version> </dependency>
如果想讓瀏覽器展示的UI效果更好看一點,需要引入最新的下麵的依賴
<!--swagger UI--> <dependency> <groupId>com.github.xiaoymin</groupId> <artifactId>knife4j-spring-ui</artifactId> <version>3.0.3</version> </dependency>
步驟二:
配置文件增加配置
swagger: enable: true application-name: 鑒權配置中心介面 application-version: 1.0 application-description: 鑒權配置中心
步驟三:
創建配置類
import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.stereotype.Component; import io.swagger.annotations.ApiOperation; import lombok.Data; import springfox.documentation.builders.ApiInfoBuilder; import springfox.documentation.builders.PathSelectors; import springfox.documentation.builders.RequestHandlerSelectors; import springfox.documentation.oas.annotations.EnableOpenApi; import springfox.documentation.service.ApiInfo; import springfox.documentation.service.Contact; import springfox.documentation.spi.DocumentationType; import springfox.documentation.spring.web.plugins.Docket; /** * @author: shf description: date: 2022/3/28 11:35 */ @Component @EnableOpenApi @ConfigurationProperties(prefix = "swagger") @Data public class SwaggerConfig { /** * 是否開啟swagger,生產環境一般關閉,所以這裡定義一個變數 */ private Boolean enable; /** * 項目應用名 */ private String applicationName; /** * 項目版本信息 */ private String applicationVersion; /** * 項目描述信息 */ private String applicationDescription; @Bean public Docket docket() { return new Docket(DocumentationType.OAS_30) .pathMapping("/") // 定義是否開啟swagger,false為關閉,可以通過變數控制,線上關閉 .enable(enable) //配置api文檔元信息 .apiInfo(apiInfo()) // 選擇哪些介面作為swagger的doc發佈 .select() //apis() 控制哪些介面暴露給swagger, // RequestHandlerSelectors.any() 所有都暴露 // RequestHandlerSelectors.basePackage("net.xdclass.*") 指定包位置 // withMethodAnnotation(ApiOperation.class)標記有這個註解 ApiOperation .apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class)) .paths(PathSelectors.any()) .build(); } private ApiInfo apiInfo() { return new ApiInfoBuilder() .title(applicationName) .description(applicationDescription) .contact(new Contact("鑒權中心平臺介面文檔", "www.yifeng.com", "[email protected]")) .version(applicationVersion) .build(); } }
啟動服務看下效果:
瀏覽器訪問http://localhost:9799/doc.html
埠號是你服務配置指定的
三、gateway統一聚合
成功完成上面微服務整合swagger的步驟後,還需要在網關中增加配置
步驟一:
同樣的引入依賴:
<dependency> <groupId>io.springfox</groupId> <artifactId>springfox-boot-starter</artifactId> <version>3.0.0</version> </dependency> <dependency> <groupId>com.github.xiaoymin</groupId> <artifactId>knife4j-spring-ui</artifactId> <version>3.0.3</version> </dependency>
步驟二:
配置文件:
spring: cloud: gateway: globalcors: cors-configurations: '[/**]': allowCredentials: true allowedOrigins: "*" allowedMethods: "*" allowedHeaders: "*" routes: - filters: - RequestTime=true - StripPrefix=1 id: core-route predicates: - Path=/core/** uri: xxxxxxxx gateway-config: uriWhitelist: - /v3/api-docs
在網關的全局過濾器中要將配置的白名單放行。
步驟三:
添加路由枚舉類,將上面配置文件中的每個微服務的路由ID替換為中文,即在UI頁面的左上角顯示的微服務文檔名稱。
/** * 服務路由枚舉 * * @author shf * @date Created in 2022-03-28 16:28 */ public enum ServerRouteEnum { /** * 路由信息 */ CORE_ROUTE("core-route", "開放平臺鑒權配置介面"); private String routeId; private String swaggerInfo; ServerRouteEnum(String routeId, String swaggerInfo) { this.routeId = routeId; this.swaggerInfo = swaggerInfo; } /** * 根據路由id獲取swagger信息 * * @param routId 路由id * @return swagger信息 */ public static String getSwaggerInfoByRoutId(String routId) { for (ServerRouteEnum routeEnum : ServerRouteEnum.values()) { if (routId.equals(routeEnum.getRouteId())) { return routeEnum.getSwaggerInfo(); } } return null; } /** * @return the routeId */ public String getRouteId() { return routeId; } /** * @param routeId : the routeId to set */ public void setRouteId(String routeId) { this.routeId = routeId; } /** * @return the swaggerInfo */ public String getSwaggerInfo() { return swaggerInfo; } /** * @param swaggerInfo : the swaggerInfo to set */ public void setSwaggerInfo(String swaggerInfo) { this.swaggerInfo = swaggerInfo; } }
最後一步:
新增配置類:
部分說明:
①SwaggerResource:處理的是UI頁面中頂部的選擇框以及拉取到每個微服務上swagger介面文檔的json數據。
②RouteLocator:獲取spring cloud gateway中註冊的路由
import org.apache.commons.lang3.StringUtils; import org.springframework.cloud.gateway.config.GatewayProperties; import org.springframework.cloud.gateway.route.RouteLocator; import org.springframework.cloud.gateway.support.NameUtils; import org.springframework.context.annotation.Primary; import org.springframework.stereotype.Component; import java.util.ArrayList; import java.util.List; import springfox.documentation.swagger.web.SwaggerResource; import springfox.documentation.swagger.web.SwaggerResourcesProvider; /** * @author: shf description: date: 2022/3/28 14:16 */ @Component @Primary public class SwaggerProvider implements SwaggerResourcesProvider { public static final String API_URI = "/v3/api-docs"; private final RouteLocator routeLocator; private final GatewayProperties gatewayProperties; public SwaggerProvider(RouteLocator routeLocator, GatewayProperties gatewayProperties) { this.routeLocator = routeLocator; this.gatewayProperties = gatewayProperties; } @Override public List<SwaggerResource> get() { List<SwaggerResource> resources = new ArrayList<>(); List<String> routes = new ArrayList<>(); // 取出gateway的route routeLocator.getRoutes().subscribe(route -> routes.add(route.getId())); // 結合配置的route-路徑(Path),和route過濾,只獲取在枚舉中說明的route節點 gatewayProperties.getRoutes().stream().filter(routeDefinition -> routes.contains(routeDefinition.getId())) .forEach(routeDefinition -> routeDefinition.getPredicates().stream() // 目前只處理Path斷言 Header或其他路由需要另行擴展 .filter(predicateDefinition -> ("Path").equalsIgnoreCase(predicateDefinition.getName())) .forEach(predicateDefinition -> { String routeId = routeDefinition.getId(); String swaggerInfo = ServerRouteEnum.getSwaggerInfoByRoutId(routeId); if (StringUtils.isNotEmpty(swaggerInfo)) { resources.add(swaggerResource(swaggerInfo, predicateDefinition.getArgs().get(NameUtils.GENERATED_NAME_PREFIX + "0").replace("/**", API_URI))); } } )); return resources; } private SwaggerResource swaggerResource(String name, String location) { SwaggerResource swaggerResource = new SwaggerResource(); swaggerResource.setName(name); swaggerResource.setLocation(location); swaggerResource.setSwaggerVersion("3.0"); return swaggerResource; } }
瀏覽器訪問:
舊版UI:http://localhost:9999/swagger-ui/index.html
新版UI:http://localhost:9999/doc.html