Java - 如何直接从 openapi 3.0 规范生成 Swagger UI

Posted

技术标签:

【中文标题】Java - 如何直接从 openapi 3.0 规范生成 Swagger UI【英文标题】:Java - how to generate Swagger UI directly from openapi 3.0 specification 【发布时间】:2019-09-07 18:30:02 【问题描述】:

我有 yaml 格式的 openapi 3.0 规范和从中生成代码的应用程序。除了生成 swagger ui 外,一切正常。我使用 spring-fox 来生成它,但它似乎从控制器生成 swagger ui 2.0 版本,这些控制器是从 openapi 规范生成的。

如何直接从我的 3.0 规范而不是从控制器生成 swagger ui,这些控制器是从 3.0 openapi 规范生成的?

【问题讨论】:

好像 springfox 不支持 OAS 3.0 - github.com/springfox/springfox/issues/2022。你能推荐任何其他从规范中产生招摇的库吗? Where the Swagger pretty html code?, How to embed Swagger UI to a webpage?的可能重复 Swagger UI 在github.com/swagger-api/swagger-ui 独立提供,您可以将其与应用程序代码分开托管。您不会从 OpenAPI 规范生成它,而是使用 Swagger UI 并将其连接到您的规范。请参阅 ^^ 链接的问题。 【参考方案1】:

好吧,我已经解决了这个问题(虽然解决方案很麻烦)。

首先我添加了swagger ui webjar -

        <plugin>
            <!-- Download Swagger UI webjar. -->
            <artifactId>maven-dependency-plugin</artifactId>
            <version>$maven-dependency-plugin.version</version>
            <executions>
                <execution>
                    <phase>prepare-package</phase>
                    <goals>
                        <goal>unpack</goal>
                    </goals>
                    <configuration>
                        <artifactItems>
                            <artifactItem>
                                <groupId>org.webjars</groupId>
                                <artifactId>swagger-ui</artifactId>
                                <version>$swagger-ui.version</version>
                            </artifactItem>
                        </artifactItems>
                        <outputDirectory>$project.build.directory/classes</outputDirectory>
                    </configuration>
                </execution>
            </executions>
        </plugin>

然后我将我的 yaml 规范转换为 json 格式并复制到 swagger-ui webjar 目录:

            <plugin>
                <groupId>org.openapitools</groupId>
                <artifactId>openapi-generator-maven-plugin</artifactId>
                <version>4.0.0-beta3</version>
                <executions>                    
                    <execution>
                        <id>generate-spec</id>
                        <goals>
                            <goal>generate</goal>
                        </goals>
                        <configuration>
                            <inputSpec>$openapi-spec-file-location</inputSpec>
                            <validateSpec>true</validateSpec>
                            <generatorName>openapi</generatorName>
                            <output>$project.build.directory/classes/META-INF/resources/webjars/swagger-ui/$swagger-ui.version</output>
                        </configuration>
                    </execution>
                </executions>
            </plugin>

接下来我们需要在 swagger-ui 中设置规范路径。根据swagger-ui API,我们可以传递spec JSON 变量而不是url。所以要初始化这个spec变量并编辑swagger ui渲染我在maven中使用replacer插件:

            <plugin>
                <!-- Replace the OpenAPI specification example URL with the local one. -->
                <groupId>com.google.code.maven-replacer-plugin</groupId>
                <artifactId>replacer</artifactId>
                <version>1.5.3</version>
                <executions>
                    <execution>
                        <phase>prepare-package</phase>
                        <goals>
                            <goal>replace</goal>
                        </goals>
                    </execution>
                </executions>
                <configuration>
                    <includes>
                        <!-- Static index html with swagger UI rendering and OAS in JSON format. -->
                        <include>$project.build.directory/classes/META-INF/resources/webjars/swagger-ui/$swagger-ui.version/index.html</include>
                        <include>$project.build.directory/classes/META-INF/resources/webjars/swagger-ui/$swagger-ui.version/openapi.json</include>
                    </includes>
                    <regexFlags>
                        <regexFlag>CASE_INSENSITIVE</regexFlag>
                        <regexFlag>MULTILINE</regexFlag>
                    </regexFlags>
                    <replacements>
                        <!-- This replacement imports spec json variable into static html page. -->
                        <replacement>
                            <token>&lt;script&gt;</token>
                            <value>&lt;script src="./openapi.json"&gt; &lt;/script&gt;&lt;script&gt;</value>
                        </replacement>
                        <!-- This part replaces url input variable with spec variable. -->
                        <replacement>
                            <token>url:\s"https:\/\/petstore\.swagger\.io\/v2\/swagger\.json"</token>
                            <value>spec: spec</value>
                        </replacement>
                        <replacement>
                        <!-- This replacement initializes spec variable, that will be passed to swagger ui index.html. -->
                            <token>^\</token>
                            <value>spec = </value>
                        </replacement>
                    </replacements>
                </configuration>
            </plugin>

所以在构建后的这一步,我们得到了带有 swagger ui 的静态资源。最后要做的就是用 Spring 来服务它。

@Configuration
@EnableWebMvc
public class SwaggerConfiguration implements WebMvcConfigurer 

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) 
        registry.addResourceHandler("/**")
                .addResourceLocations("classpath:/META-INF/resources/webjars/swagger-ui/3.22.0/");
    

    //this method was introduced just for convenient swagger ui access. Without it swagger ui can be accessed with /index.html GET call   
    @Override
    public void addViewControllers(ViewControllerRegistry registry) 
        registry.addViewController("/swagger-ui.html").setViewName("forward:/index.html");
    

原来如此。如果您对此答案发表评论并指出如何简化此过程,那就太好了。

【讨论】:

谢谢谢尔盖,这也帮助我解决了我的问题。为什么 sou 选择导致 3 次替换的“spec”变量?用本地 openapi.json 替换 petstore.json url 对我来说效果很好:&lt;replacement&gt;&lt;token&gt;https:\/\/petstore\.swagger\.io\/v2\/swagger\.json&lt;/token&lt;value&gt;openapi.json&lt;/value&gt;&lt;/replacement&gt; 我将输出用于 gitlab pages doc。在这种情况下,我不得不删除 index.html.gz,所以实际上我修改后的 index.html 被拾取了。 @mineralf thx,我会检查一下。我还计划检查如何从多个规范文件构建 swagger UI。找到解决办法后会在这里贴出来

以上是关于Java - 如何直接从 openapi 3.0 规范生成 Swagger UI的主要内容,如果未能解决你的问题,请参考以下文章

如何从 OpenAPI 3.0 yaml 文件生成 JSON 示例?

如何在 Gradle 中为 OpenAPI 3.0 使用 Swagger Codegen?

如何使用 Springdoc 在 OpenAPI 3.0 中创建链接?

如何在OpenAPI 3.0中用两个可选参数定义路径?

Java Enum 上的 OpenAPI 和 @Schema 注释

使用 Spring Security 启用 Swagger springdoc-openapi-ui (OpenAPI 3.0) - 无法访问 swagger-ui.html (401)