spring-mvc - 将 Swagger 服务器 stub 添加到现有 Spring 应用程序中

标签 spring-mvc swagger springfox

插入Swagger Codegen 生成的服务器 stub 的最佳方法是什么?到现有的 Spring MVC 应用程序中?

我开始尝试使用 petstore stubs样本。

我的 Spring 配置使用 Java,如下所示:

public class SpringConfigurationInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {

    @Override
    protected Class<?>[] getRootConfigClasses() {
        return new Class[] { ApplicationContext.class };
    }

    @Override
    protected Class<?>[] getServletConfigClasses() {
        return new Class[] { WebMvcContext.class };
    }

    @Override
    protected String[] getServletMappings() {
        return new String[] { "/" };
    }

    // ... onStartup etc.

}

WebMvcConfiguration 支持:
@Configuration
@EnableTransactionManagement(mode = AdviceMode.ASPECTJ)
@PropertySource({ "classpath:config.properties", "file:${CONFIGDIR}/config.properties" })
@ComponentScan(useDefaultFilters = false, basePackages = { "com.yyy", "com.xxx" }, includeFilters = { @Filter(type = FilterType.ANNOTATION, value = Controller.class) })
public class WebMvcContext extends WebMvcConfigurationSupport {

    // ... beans etc.
}

应用上下文:
@Configuration
@EnableAsync
@EnableScheduling
@EnableMBeanExport
@Import({SecurityConfig.class, GeneralDBConfiguration.class})
@ComponentScan(useDefaultFilters = true, basePackages = { "com.yyy", "com.xxx" }, excludeFilters = { @Filter(type = FilterType.ANNOTATION, value = {Controller.class, Configuration.class/*, Aspect.class*/}) })
public class ApplicationContext implements AsyncConfigurer {

    // beans etc.

}

如何在 io.swagger.configuration 中包含配置类部分?打包到我现有的应用程序中?

更多细节:

我遇到的问题之一是,如果我指定了对 petshop stub 的 maven 依赖项(通过从 mvn install:install-file ... 目录运行 spring-mvc-j8-async 在本地安装):
    <dependency>
        <groupId>io.swagger</groupId>
        <artifactId>swagger-spring-mvc-server</artifactId>
        <version>1.0.0</version>
    </dependency>

然后我的spring应用找到两个AbstractAnnotationConfigDispatcherServletInitializer s (一个来自我的应用程序,而 io.swagger.configuration.WebApplication 一个来自 swagger-spring-mvc-server )并且无法加载 - 出现以下异常:

Failed to register servlet with name 'dispatcher'.Check if there is another servlet registered under the same name.



我想另一种表达我的问题的方式是,你如何使用 swagger-codegen 生成的服务器 stub ? ?看起来我不能只依赖开箱即用的 Maven 包......

最佳答案

我可以看到这是一个相当古老的问题,但我为此付出了很多努力,我收集的信息可能对其他人有用,直到生成器文档得到改进。

此描述用于使用 openapi-generator-maven-plugin 从 OpenApi 3.0.0 规范生成和使用 spring-mvc 服务器 stub 。

  • 不要使用 swagger-codegen,而是使用 openapi 生成器:https://github.com/OpenAPITools/openapi-generator ( fork 的推理在这里:https://github.com/OpenAPITools/openapi-generator/blob/master/docs/qna.md)
  • 为服务器内容创建一个单独的项目/模块并配置 Maven 插件。
  • <build>
        <plugins>
            <plugin>
                <groupId>org.openapitools</groupId>
                <artifactId>openapi-generator-maven-plugin</artifactId>
                <version>3.3.4</version>
                <executions>
                    <execution>
                        <goals>
                            <goal>generate</goal>
                        </goals>
                        <configuration>
                            <skipIfSpecIsUnchanged>true</skipIfSpecIsUnchanged>
                            <inputSpec>${engine-openapi-spec.location}</inputSpec>
                            <output>${project.build.directory}/generated-sources/openapi</output>
                            <generatorName>spring</generatorName>
                            <library>spring-mvc</library>
                            <apiPackage>eu.dorsum.swift.engine.service.api</apiPackage>
                            <modelPackage>eu.dorsum.swift.engine.service.model</modelPackage>
                            <generateApis>true</generateApis>
                            <generateApiDocumentation>false</generateApiDocumentation>
                            <generateApiTests>false</generateApiTests>
                            <generateModels>true</generateModels>
                            <generateModelDocumentation>false</generateModelDocumentation>
                            <generateModelTests>false</generateModelTests>
                            <generateSupportingFiles>true</generateSupportingFiles>
                            <configOptions>
                                <sourceFolder>src/main/java</sourceFolder>
                                <java8>true</java8>
                                <dateLibrary>java8</dateLibrary>
                                <useTags>true</useTags>
                                <configPackage>eu.dorsum.swift.engine.appconfig</configPackage>
                                <interfaceOnly>false</interfaceOnly>
                                <delegatePattern>true</delegatePattern>
                            </configOptions>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
    

    有两种配置很难弄清楚。

    2.a:设置configOptions/configPackage到您的应用程序的根配置所在的包。此选项会将您的配置包作为附加 basePackage 添加到 OpenAPIUiConfiguration.java 中的组件扫描:@ComponentScan(basePackages = {"eu.dorsum.swift.engine.service.api", "eu.dorsum.swift.engine.appconfig"}) .这是您最初可能会想到的一种反向方法,即让生成的 mvc 配置启动您现有的东西,但这是我发现不需要修改生成的代码的唯一方法。

    2.b:设置configOptions/delegatePattern为真。这个我非常喜欢!这将生成一个额外的委托(delegate)接口(interface),您的服务器 Controller 可以实现该接口(interface)。生成的 ApiController 会将所有服务调用委托(delegate)给该接口(interface),因此您可以非常优雅地插入您的实现。在我的设置中,我有这个链:MessageApi(生成的接口(interface))-> MessageApiController 实现 MessageApi(生成的 mvc Controller )-> MessageApiDelegate(生成的接口(interface))-> MessageService 实现 MessageApiDelegate(我的服务方法的实现)。

    有了这两个配置,就无需修改生成的源。如果 api 规范更改了委托(delegate)接口(interface)更改,您必须在 MessageService 中实现这些更改。

    下面是对我的原始帖子的更新,以更详细地解释服务实现如何绑定(bind)到委托(delegate)接口(interface)。

    openapi-gen 生成的源代码位于一个单独的 jar 模块中,其中仅包含 swagger.yaml 和 pom.xml 作为 checkin 的“源代码”。使用生成代码的模块是直接依赖于生成的 jar 的 war 。服务实现在 war 中,并实现了生成源中的 MessageApiDelegate 接口(interface)。
    从生成的代码中提取 Spring 上下文,您在 openapi-gen config 中定义为 apiPackage 和 configPackage 的包将在生成的 OpenAPIUiConfiguration.java 中作为 @ComponentScan 的 basePackages 添加,因此您的服务实现必须放在 apiPackages 中或之下。

    这是将各个部分组合在一起的简化结构。
    parent/
      swift-engin-service/ (generated jar module)
        swagger.yaml
        pom.xml
        target/generated-sources/openapi/src/main/java/eu/dorsum/swift/engine/
          appconfig/ (generated spring webmvc config)
            OpenAPIUiConfiguration.java
            WebApplication.java (brings up spring context by extending AbstractAnnotationConfigDispatcherServletInitializer)
          service/
            MessageApiController.java (@Controller, @RequestMapping etc.)
            MessageApiDelegate.java (implement this to get your service implementation plugged in the controller)
      swift-engine/ (war module, your code)
        pom.xml
        src/main/java/eu/dorsum/swift/engine/
          appconfig/
            EngineConfig.java (my spring config)
          service/api/ (must be the same as apiPackages property)
            MessageService.java (service implementation)
    

    swift-engine/pom.xml 的相关部分
    <project>
        <packaging>war</packaging>
    
        <dependencies>
            <dependency>
                <groupId>eu.dorsum.core.java.swift-engine</groupId>
                <artifactId>swift-engine-service</artifactId>
            </dependency>
        </dependencies>
    </project>
    

    eu.dorsum.swift.engine.service.api.MessageService 的相关部分
    @Service
    public class MessageService implements MessageApiDelegate {
        @Override
        public ResponseEntity<List<SwiftMessage>> listMessages(List<String> sorting, Integer pageStart, Integer pageSize, String filter) {
            // implementation
        }
    
        @Override
        public ResponseEntity<Void> updateMessage(SwiftMessage message) {
            // implementation
        }
    }
    

    eu.dorsum.swift.engine.appconfig.OpenAPIUiConfiguration 的相关部分(生成)
    @Configuration
    @ComponentScan(basePackages = {"eu.dorsum.swift.engine.service.api", "eu.dorsum.swift.engine.appconfig"})
    @EnableWebMvc
    public class OpenAPIUiConfiguration extends WebMvcConfigurerAdapter {
        ...
    }
    

    关于spring-mvc - 将 Swagger 服务器 stub 添加到现有 Spring 应用程序中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36742362/

    相关文章:

    java - Swagger core v3的java实现

    java - 使用 @ModelAttribute 时未显示自定义域对象

    spring-boot - 从SpringFox2.x升级到SpringFox3.0开放API

    java.lang.NoClassDefFoundError : Could not initialize class org. springframework.web.servlet.tags.form.FormTag

    java - Spring MVC + JQuery + Ajax 问题

    java - Spring MVC 测试

    java - 在 Spring MVC 中映射/(root URL)

    spring - 如何从现有的 Spring REST API 生成 OpenAPI 3.0 YAML 文件?

    spring - 如何用 Swagger 描述 "ModelAttribute"的最佳方法

    Spring Boot Rest - 如何接受多个 header