SpringOpenApi Swagger UI本地正常K8s部署访问返回404问题咨询
Kubernetes部署Swagger UI返回404问题排查与路径打印方案
一、Kubernetes部署场景排查方向
按优先级从高到低排查:
- 首先做基础连通性校验:执行
kubectl port-forward <pod名> 8091:8091,本地直接访问http://localhost:8091/swagger-ui-myname.html,如果能正常打开,说明应用本身配置无问题,故障点在Service上层的Ingress/API网关转发规则。 - 核对转发规则的路径重写配置:如果访问地址带
/service-name前缀,Ingress/网关若未配置路径剥离(转发前将/service-name前缀从请求路径中删除),后端Pod收到的请求路径为/service-name/swagger-ui-myname.html,但当前Swagger UI配置的映射路径是根路径下的/swagger-ui-myname.html,路径不匹配自然返回404。/service-name/api-docs能访问通常是因为项目中自定义的Controller路径或者api-docs的路径映射做了通配匹配,不代表转发规则正确。 - 修正子路径部署下的Springdoc配置:如果网关/Ingress不做路径剥离,服务实际部署在
/service-name子路径下,必须修改以下配置:
如果配置了Springboot全局上下文路径springdoc: swagger-ui: use-root-path: false # 原配置为true会强制将Swagger UI重定向到域名根路径,子路径部署必须关闭 config-url: /service-name/api-docs/swagger-config # 指定Swagger UI拉取配置的地址,和自定义api-docs路径对齐 url: /service-name/api-docs # 指定Swagger UI拉取接口文档的地址,和自定义api-docs路径对齐server.servlet.context-path=/service-name,上述路径可以不用手动写全,Springdoc会自动拼接上下文路径。 - 检查环境差异化的拦截配置:核对K8s环境激活的配置文件中,自定义的Web拦截器、Spring Security安全配置、网关层鉴权规则,是否将
/swagger-ui/**、/swagger-ui-myname.html路径加入放行列表,部分拦截逻辑会将未授权的静态资源请求直接返回404而非401,容易误导排查方向。 - 修正非法配置项:当前配置中
supportedSubmitMethods: nomethod**为非法值,该配置合法值为HTTP方法数组(如["get", "post"]),不需要限制方法可设为空数组[],非法值可能导致Swagger配置接口返回异常,触发页面加载失败。
二、启动时输出Swagger可访问路径、接口返回地址的实现方案
- 启动日志打印路径:实现Web服务启动事件监听器,服务启动完成后自动拼接地址打印日志,代码如下:
import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.web.servlet.context.WebServerInitializedEvent; import org.springframework.context.ApplicationListener; import org.springframework.stereotype.Component; @Component public class SwaggerPathPrinter implements ApplicationListener<WebServerInitializedEvent> { @Value("${server.servlet.context-path:}") private String contextPath; @Value("${springdoc.swagger-ui.path:/swagger-ui.html}") private String swaggerUiPath; @Value("${springdoc.api-docs.path:/api-docs}") private String apiDocsPath; // 可通过配置项注入K8s环境的外部访问前缀,如https://server:port/service-name @Value("${swagger.external-base-url:http://localhost:${server.port:8090}${server.servlet.context-path:}}") private String externalBaseUrl; @Override public void onApplicationEvent(WebServerInitializedEvent event) { System.out.println("========== Swagger 访问地址 =========="); System.out.printf("Swagger UI: %s%s%n", externalBaseUrl, swaggerUiPath); System.out.printf("API Docs: %s%s%n", externalBaseUrl, apiDocsPath); System.out.println("======================================"); } } - 在/api-docs返回结果中携带Swagger UI地址:在现有自定义OpenAPI的Bean中,将地址写入文档描述或扩展字段即可,示例:
K8s部署时只需在配置文件中给@Bean public OpenAPI myOpenApi(@Value("${swagger.external-base-url:}") String externalBaseUrl, @Value("${springdoc.swagger-ui.path:/swagger-ui.html}") String swaggerUiPath) { String uiUrl = externalBaseUrl + swaggerUiPath; return new OpenAPI().info(new Info() .title("XXXXX") .description("XXXXX\n\nSwagger UI访问地址:" + uiUrl) .addExtension("x-swagger-ui-url", uiUrl)); }swagger.external-base-url赋值为实际的服务外部访问前缀(如https://server:port/service-name),即可在api-docs返回结果中拿到正确的UI访问地址。
内容的提问来源于stack exchange,提问作者Venkat Bontha
相关产品推荐
相关产品推荐

