You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Cloud网关场景下能否直接向Swagger UI提供OpenAPI JSON文档?

问题背景

我有一个带动态路由的Gateway服务,希望通过Swagger UI暴露所有端点。由于路由会随Eureka中服务的注册/注销动态变化,无法使用静态YAML配置的方案。我已经完成了以下步骤:

步骤1:指定Swagger配置端点

springdoc:
  api-docs:
    enabled: false
  swagger-ui:
    enabled: true
    path: /swagger-ui.html
    config-url: /swagger-ui-config

步骤2:实现配置端点接口

package by.afinny.apigateway.controller;

import by.afinny.apigateway.model.uiConfig.SwaggerUiConfig;
import by.afinny.apigateway.service.SwaggerUiConfigProvider;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Mono;

@RestController
@RequiredArgsConstructor
public class SwaggerUiConfigController {
    private final SwaggerUiConfigProvider configProvider;
    @GetMapping("/swagger-ui-config")
    public Mono<SwaggerUiConfig> getConfig() {
        return configProvider.getSwaggerUiConfig();
    }
}

步骤3:封装Swagger UI配置实体

package by.afinny.apigateway.model.uiConfig;

import by.afinny.apigateway.model.documentedApplication.SwaggerApplication;
import by.afinny.apigateway.service.SwaggerUiConfigSerializer;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import lombok.Getter;
import lombok.NoArgsConstructor;

import java.util.Collection;

@NoArgsConstructor
@Getter
public class SwaggerUiConfig {
    @JsonProperty("urls")
    @JsonSerialize(contentUsing = SwaggerUiConfigSerializer.class)
    private Collection<SwaggerApplication> swaggerApplications;

    public SwaggerUiConfig(Collection<SwaggerApplication> swaggerApplications) {
        this.swaggerApplications = swaggerApplications;
    }

    public static SwaggerUiConfig from(Collection<SwaggerApplication> swaggerApplications) {
        return new SwaggerUiConfig(swaggerApplications);
    }
}
package by.afinny.apigateway.service;

import by.afinny.apigateway.model.documentedApplication.SwaggerApplication;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import lombok.SneakyThrows;

import java.io.IOException;
import java.text.MessageFormat;

public class SwaggerUiConfigSerializer extends JsonSerializer<SwaggerApplication> {
    @Override
    @SneakyThrows
    public void serialize(SwaggerApplication swaggerApplication, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
        jsonGenerator.writeStartObject();
        jsonGenerator.writeStringField("url", MessageFormat.format("/{0}{1}", swaggerApplication.getName(), SwaggerApplication.SWAGGER_DOC_PATH));
        jsonGenerator.writeStringField("name", swaggerApplication.getName());
        jsonGenerator.writeEndObject();
    }
}

步骤4:配置文档转发路由

路由逻辑会将/{服务名}/v3/api-docs转发至lb://SERVICE-NAME/v3/api-docs(代码省略)


核心疑问

我在构建业务路由时已经获取并缓存了这些OpenAPI JSON文档(会实时更新),不想让Swagger UI重复执行拉取操作,能否直接向Swagger UI提供缓存的文档,而非仅告知文档地址?


可行解决方案

完全可以实现,核心思路是绕过Swagger UI默认的远程文档拉取逻辑,直接将缓存的OpenAPI JSON数据注入到Swagger UI的配置中,具体有两种实现方式:

方式一:修改后端配置端点,返回内联文档

1. 更新序列化器,直接输出缓存的文档

修改SwaggerUiConfigSerializer,不再返回url字段,而是直接返回spec字段(Swagger UI支持加载内联的OpenAPI规范):

package by.afinny.apigateway.service;

import by.afinny.apigateway.model.documentedApplication.SwaggerApplication;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import lombok.SneakyThrows;

import java.io.IOException;

public class SwaggerUiConfigSerializer extends JsonSerializer<SwaggerApplication> {
    @Override
    @SneakyThrows
    public void serialize(SwaggerApplication swaggerApplication, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
        jsonGenerator.writeStartObject();
        jsonGenerator.writeStringField("name", swaggerApplication.getName());
        // 直接写入缓存的OpenAPI JSON字符串,无需远程拉取
        jsonGenerator.writeFieldName("spec");
        jsonGenerator.writeRawValue(swaggerApplication.getCachedOpenApiJson());
        jsonGenerator.writeEndObject();
    }
}

2. 扩展SwaggerApplication实体

在SwaggerApplication中新增字段存储缓存的文档:

package by.afinny.apigateway.model.documentedApplication;

import lombok.Getter;
import lombok.Setter;

@Getter
@Setter
public class SwaggerApplication {
    public static final String SWAGGER_DOC_PATH = "/v3/api-docs";
    private String name;
    // 新增:存储缓存的OpenAPI JSON文档
    private String cachedOpenApiJson;
}

方式二:自定义Swagger UI静态页面,直接注入文档

如果不想修改后端逻辑,可以自定义Swagger UI页面:

  1. 复制官方Swagger UI静态文件到项目resources/static目录
  2. 修改页面初始化代码,直接传入缓存的文档数据:
const ui = SwaggerUIBundle({
  urls: [
    {
      name: "用户服务",
      spec: /* 直接填入缓存的用户服务OpenAPI JSON */
    },
    {
      name: "订单服务",
      spec: /* 直接填入缓存的订单服务OpenAPI JSON */
    }
  ],
  dom_id: '#swagger-ui',
  deepLinking: true,
  // 其他Swagger UI配置
});

注意事项

  • 服务注册/注销时,需同步更新缓存的OpenAPI文档,并确保Swagger UI能获取最新配置(可通过WebSocket推送或定期刷新配置端点实现)
  • 直接注入spec时需保证JSON格式正确,避免转义错误
  • 若文档体积较大,建议使用方式一,避免前端页面体积过大

内容的提问来源于stack exchange,提问作者Sergey Zolotarev

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 06:11:18