在 Spring Boot 2.x + Spring Cloud Gateway(基于 WebFlux) 的项目中集成 Knife4j,由于 Spring Boot 2 使用的是 Servlet API(javax) 而不是 Jakarta,且 Gateway 是响应式(WebFlux)架构,不能直接使用传统的 Swagger2(Springfox),推荐使用 Springdoc OpenAPI v1.x + Knife4j 3.x 的组合。
✅ 注意:Spring Boot 2.x 不兼容 Knife4j 4.x(Jakarta 版本),必须使用 Knife4j 3.x。
🧩 一、整体思路
- 各微服务(如 user-service)使用
springdoc-openapi-webmvc-core暴露/v3/api-docs; - 网关(Gateway)通过路由转发访问各服务的 OpenAPI 文档;
- 网关自身集成
springdoc-openapi-webflux+knife4j-spring-boot-starter(3.x)提供统一 UI; - 使用
GroupedOpenApi聚合多个服务的文档。
🔧 二、微服务端配置(以 user-service 为例)
1. 添加依赖(Spring Boot 2.x)
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-webmvc-core</artifactId>
<version>1.7.0</version>
</dependency>
<!-- 可选:如果需要 Swagger UI(微服务单独访问) -->
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-ui</artifactId>
<version>1.7.0</version>
</dependency>
2. 配置(application.yml)
springdoc:
api-docs:
path: /v3/api-docs
swagger-ui:
path: /swagger-ui.html
启动后可通过 http://user-service:port/v3/api-docs 获取 JSON 文档。
🔧 三、网关(Gateway)端集成 Knife4j
1. 添加依赖(关键!使用 Knife4j 3.x)
<!-- Springdoc WebFlux 支持(用于 Gateway) -->
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-webflux-core</artifactId>
<version>1.7.0</version>
</dependency>
<!-- Knife4j 增强 UI(Spring Boot 2 兼容版) -->
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-spring-boot-starter</artifactId>
<version>3.0.3</version> <!-- 最高支持到 3.x -->
</dependency>
⚠️ 切勿使用
knife4j-openapi3-jakarta-spring-boot-starter(这是给 Spring Boot 3 用的)!
2. 配置 Gateway 路由(application.yml)
确保能访问下游服务的 OpenAPI 文档:
spring:
cloud:
gateway:
routes:
# 用户服务
- id: user-service
uri: lb://user-service
predicates:
- Path=/user-service/**
filters:
- StripPrefix=1
# 订单服务
- id: order-service
uri: lb://order-service
predicates:
- Path=/order-service/**
filters:
- StripPrefix=1
# 转发 Swagger 文档(关键!)
- id: user-service-api-docs
uri: lb://user-service
predicates:
- Path=/user-service/v3/api-docs
- id: order-service-api-docs
uri: lb://order-service
predicates:
- Path=/order-service/v3/api-docs
这样可以通过:
- http://gateway:port/user-service/v3/api-docs
- http://gateway:port/order-service/v3/api-docs
访问各服务的 OpenAPI 文档。
3. 创建聚合配置类(SwaggerResourceConfig)
在网关项目中创建如下配置类:
@Configuration
public class SwaggerResourceConfig {
// 手动定义需要聚合的服务列表
private static final List<String> SERVICES = Arrays.asList("user-service", "order-service");
@Bean
public RouteLocator routeLocator(RouteLocatorBuilder builder) {
return builder.routes().build(); // 仅用于注入 RouteLocator
}
/**
* 提供聚合后的 OpenAPI 资源(用于 Knife4j 分组)
*/
@Bean
public List<GroupedOpenApi> groupedOpenApis() {
return SERVICES.stream()
.map(serviceName -> GroupedOpenApi.builder()
.group(serviceName)
.pathsToMatch("/" + serviceName + "/**")
.build())
.collect(Collectors.toList());
}
}
说明:
GroupedOpenApi会自动为每个 group 生成对应的/v3/api-docs/{groupName},但实际文档仍需通过路由转发到下游服务。因此更推荐使用 自定义 OpenAPI 聚合方式(见下文进阶方案)。
🔄 四、【推荐】进阶方案:自定义聚合 OpenAPI 文档(解决 GroupedOpenApi 无法拉取远程文档的问题)
⚠️ 注意:GroupedOpenApi 在 Gateway 中 不会自动拉取远程服务的 OpenAPI 内容,它只适用于本地 Controller。
因此,要真正聚合多个微服务的文档,需要 手动拉取远程 /v3/api-docs 并合并。
方案:使用 SwaggerResourcesProvider(兼容 Springdoc)
但由于 Springdoc 已取代 Swagger2,更推荐使用 knife4j-gateway 官方提供的聚合方式。
✅ 推荐做法:使用 knife4j 提供的 OpenApiAggregator
- 添加工具类(用于拉取远程 OpenAPI):
@Component
@RequiredArgsConstructor
public class OpenApiAggregator {
private final WebClient.Builder webClientBuilder;
public Map<String, Object> getOpenApiFromService(String serviceUrl) {
WebClient client = webClientBuilder.build();
try {
return client.get()
.uri(serviceUrl + "/v3/api-docs")
.retrieve()
.bodyToMono(new ParameterizedTypeReference<Map<String, Object>>() {})
.block(Duration.ofSeconds(5));
} catch (Exception e) {
log.warn("Failed to fetch OpenAPI from {}", serviceUrl, e);
return Collections.emptyMap();
}
}
}
- 创建一个 Controller 暴露聚合接口(可选,用于调试)
但更简单的方式是:**直接让 Knife4j UI 通过网关路由访问各服务的 /v3/api-docs**,并在前端选择不同服务。
🌐 五、启用 Knife4j UI 并访问
1. 配置 Knife4j(application.yml)
knife4j:
enable: true
production: false
basic:
enable: true
username: admin
password: 123456
2. 访问地址
启动网关后,访问:
http://localhost:8080/doc.html
在 Knife4j 页面顶部的 “分组”下拉框 中,会显示 user-service、order-service 等分组(前提是配置了 GroupedOpenApi)。
💡 但注意:此时点击分组,Knife4j 会请求
/v3/api-docs/user-service,而该路径在网关本地并不存在!
✅ 正确做法:**不依赖 GroupedOpenApi 聚合,而是直接在 doc.html 中配置多个文档地址**
替代方案:使用 Knife4j 的 多实例文档 功能
在 doc.html 页面中,Knife4j 支持手动添加多个 OpenAPI 地址:
- 访问
http://gateway:8080/doc.html - 点击右上角 “文档管理”(或“离线文档”图标)
- 添加多个 URL:
- 名称:用户服务,URL:
/user-service/v3/api-docs - 名称:订单服务,URL:
/order-service/v3/api-docs
即可切换查看不同服务的 API。
这是最简单、最可靠的方式,无需复杂聚合逻辑。
✅ 六、最终建议配置总结
| 组件 | 依赖版本 |
|---|---|
| Spring Boot | 2.7.x |
| Spring Cloud | 2021.0.x |
| springdoc-openapi | 1.7.0 |
| knife4j-spring-boot-starter | 3.0.3 |
网关核心依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-webflux-core</artifactId>
<version>1.7.0</version>
</dependency>
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-spring-boot-starter</artifactId>
<version>3.0.3</version>
</dependency>
路由配置确保 /xxx/v3/api-docs 可访问;
直接通过 doc.html 手动添加多个文档地址,实现聚合效果。
📚 参考资料
- Knife4j 官方文档(Spring Boot 2 示例):https://doc.xiaominfo.com/knife4j/documentation/
- Springdoc OpenAPI for WebFlux:https://springdoc.org/
如有需要,也可考虑使用 smart-doc + [smart-doc-maven-plugin] 自动生成静态文档,避免运行时聚合问题。