没有做 API 文档聚合,访问每个服务的 API 文档都需要访问单独的 swagger-ui.html
页面,既然我们使用了微服务,就应该有统一的 API 文档入口,而 knife4j
有这方面的支持,本文将详细介绍其实现,希望对大家有所帮助!
我们将采用 Nacos 作为注册中心,Gateway 作为网关,使用 knife4j
来生成 API 文档。
应用架构
我们理想的解决方案应该是这样的,网关作为 API 文档的统一入口,网关聚合所有微服务的文档,通过在网关进行切换来实现对其他服务 API 文档的访问。
相关服务划分:
- knife4j-gateway:网关服务,作为微服务 API 文档的访问入口,聚合所有 API 文档,需要引入文档前端 UI 包;
- knife4j-user:用户服务,普通 API 服务,不需要引入文档前端 UI 包;
- knife4j-order:订单服务,普通 API 服务,不需要引入文档前端 UI 包。
具体实现
下面详细介绍下 Spring Cloud Gateway + knife4j 聚合 API 文档的具体实现,依次搭建用户服务、订单服务和网关服务。
创建 knife4j-user 项目模块
我们首先来搭建用户服务,一个普通的 API 服务,很简单,仅需三步即可集成 knife4j。
在 pom.xml 中添加相关依赖,一个 Spring Boot 的 web 功能依赖,knife4j 的微服务依赖(不包含 API 文档的前端 UI 包):
1 2 3 4 5 6 7 8 9 10
| <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>com.github.xiaoymin</groupId> <artifactId>knife4j-micro-spring-boot-starter</artifactId> </dependency> </dependencies>
|
在 application.yml
中添加相关配置,配置一下 Nacos 注册中心即可:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| server: port: 9501 spring: profiles: active: dev application: name: knife4j-user cloud: nacos: discovery: server-addr: localhost:8848 management: endpoints: web: exposure: include: "*"
|
添加 Swagger 相关配置,非常常规的配置,添加 @EnableKnife4j
注解开启 knife4j 的增强功能:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| @Configuration @EnableSwagger2 @EnableKnife4j public class Swagger2Config { @Bean public Docket createRestApi(){ return new Docket(DocumentationType.SWAGGER_2) .apiInfo(apiInfo()) .select() .apis(RequestHandlerSelectors.basePackage("com.macro.cloud.controller")) .paths(PathSelectors.any()) .build(); }
private ApiInfo apiInfo() { return new ApiInfoBuilder() .title("knife4j-user") .description("用户服务API文档") .contact("antonio") .version("1.0") .build(); } }
|
创建 knife4j-order 项目模块
我们接下来搭建订单服务,一个普通的 API 服务,直接参考上面用户服务的搭建即可。
创建 knife4j-gateway 项目模块
最后我们搭建网关服务,作为微服务 API 文档的的统一入口,聚合所有微服务的 API 文档。
在 pom.xml 中添加相关依赖,Gateway 相关依赖和 knife4 j的 Starter(包含 API 文档的前端 UI 包):
1 2 3 4 5 6 7 8 9 10
| <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-gateway</artifactId> </dependency> <dependency> <groupId>com.github.xiaoymin</groupId> <artifactId>knife4j-spring-boot-starter</artifactId> </dependency> </dependencies>
|
在 application.yml
这添加相关配置,配置一下 Nacos 注册中心,用户服务和订单服务的路由即可:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| server: port: 9201 spring: profiles: active: dev application: name: knife4j-gateway cloud: nacos: discovery: server-addr: localhost:8848 gateway: routes: - id: user-service uri: lb://knife4j-user predicates: - Path=/user-service/** filters: - StripPrefix=1 - id: order-service uri: lb://knife4j-order predicates: - Path=/order-service/** filters: - StripPrefix=1 discovery: locator: enabled: true lower-case-service-id: true
|
在网关上添加 Swagger 资源配置,用于聚合其他微服务中 Swagger 的 api-docs
访问路径:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| @Slf4j @Component @Primary @AllArgsConstructor public class SwaggerResourceConfig implements SwaggerResourcesProvider {
private final RouteLocator routeLocator; private final GatewayProperties gatewayProperties;
@Override public List<SwaggerResource> get() { List<SwaggerResource> resources = new ArrayList<>(); List<String> routes = new ArrayList<>(); routeLocator.getRoutes().subscribe(route -> routes.add(route.getId())); gatewayProperties.getRoutes().stream().filter(routeDefinition -> routes.contains(routeDefinition.getId())).forEach(route -> { route.getPredicates().stream() .filter(predicateDefinition -> ("Path").equalsIgnoreCase(predicateDefinition.getName())) .forEach(predicateDefinition -> resources.add(swaggerResource(route.getId(), predicateDefinition.getArgs().get(NameUtils.GENERATED_NAME_PREFIX + "0") .replace("**", "v2/api-docs")))); });
return resources; }
private SwaggerResource swaggerResource(String name, String location) { log.info("name:{},location:{}", name, location); SwaggerResource swaggerResource = new SwaggerResource(); swaggerResource.setName(name); swaggerResource.setLocation(location); swaggerResource.setSwaggerVersion("2.0"); return swaggerResource; } }
|
什么是 Swagger 的 api-docs
访问路径?该路径会返回 JSON 格式数据,Swagger 渲染 API 文档页面的所有数据就是来源于此,比如我们的用户服务会返回如下信息,访问地址:http://localhost:9201/user-service/v2/api-docs

接下来我们需要自定义 Swagger 各个配置的节点,简单来说就是自定义 Swagger 内部的各个获取数据的接口:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
|
@RestController public class SwaggerHandler {
@Autowired(required = false) private SecurityConfiguration securityConfiguration;
@Autowired(required = false) private UiConfiguration uiConfiguration;
private final SwaggerResourcesProvider swaggerResources;
@Autowired public SwaggerHandler(SwaggerResourcesProvider swaggerResources) { this.swaggerResources = swaggerResources; }
@GetMapping("/swagger-resources/configuration/security") public Mono<ResponseEntity<SecurityConfiguration>> securityConfiguration() { return Mono.just(new ResponseEntity<>( Optional.ofNullable(securityConfiguration).orElse(SecurityConfigurationBuilder.builder().build()), HttpStatus.OK)); }
@GetMapping("/swagger-resources/configuration/ui") public Mono<ResponseEntity<UiConfiguration>> uiConfiguration() { return Mono.just(new ResponseEntity<>( Optional.ofNullable(uiConfiguration).orElse(UiConfigurationBuilder.builder().build()), HttpStatus.OK)); }
@GetMapping("/swagger-resources") public Mono<ResponseEntity> swaggerResources() { return Mono.just((new ResponseEntity<>(swaggerResources.get(), HttpStatus.OK))); } }
|
比如说 swagger-resources
这个接口,可用于获取所有微服务的 api-docs
访问路径,获取信息如下,访问地址:http://localhost:9201/swagger-resources

功能演示
接下来我们来演示下微服务 API 文档聚合的功能,仅需要访问网关的 API 文档页面即可,可自行切换到相关服务的 API 文档。
在此之前先启动我们的 Nacos 注册中心,然后依次启动 knife4j-user
、knife4j-order
及 knife4j-gateway
服务:

从网关访问 API 文档,访问地址:http://localhost:9201/doc.html

我们通过左上角的切换组件即可切换到对应服务的API文档:

查看 API 文档,我们可以发现所有接口都已经添加了对应的访问前缀,可以正常访问。

切换回 Swagger UI
如果你不想使用 knife4j 的界面,想用原来的 Swagger 界面,也是可以支持的,切换方法非常简单,下面我们来讲讲。
首先我们需要在 pom.xml
中去除 knife4j 的相关依赖,主要就是下面两个依赖:
1 2 3 4 5 6 7 8
| <dependency> <groupId>com.github.xiaoymin</groupId> <artifactId>knife4j-micro-spring-boot-starter</artifactId> </dependency> <dependency> <groupId>com.github.xiaoymin</groupId> <artifactId>knife4j-spring-boot-starter</artifactId> </dependency>
|
在 pom.xml
中添加 Swagger 相关依赖,并去除原来使用的 @EnableKnife4j
注解:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| <dependencies> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> <version>2.9.2</version> </dependency> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger-ui</artifactId> <version>2.9.2</version> </dependency> <dependency> <groupId>io.swagger</groupId> <artifactId>swagger-models</artifactId> <version>1.6.0</version> </dependency> <dependency> <groupId>io.swagger</groupId> <artifactId>swagger-annotations</artifactId> <version>1.6.0</version> </dependency> </dependencies>
|
重新启动所有服务,访问网关的 API 文档路径即可查看:http://localhost:9201/swagger-ui.html

更多干货请移步:https://antoniopeng.com
如果你喜欢这个博客或发现它对你有用,欢迎你点击右下角 “OPEN CHAT” 进行评论。也欢迎你分享这个博客,让更多的人参与进来。如果在博客中的内容侵犯了您的版权,请联系博主删除它们。谢谢你!