【问题标题】:Prevent Swagger from automatically adding some models防止 Swagger 自动添加某些模型
【发布时间】:2019-03-14 16:41:02
【问题描述】:

我使用 Spring Boot 框架构建了一个 REST 接口。然后,我使用 Swagger 2.9.2 版来生成文档。从下图可以看出,Swagger 自动检测了很多模型。

但是,它们中的大多数都是多余的。其中,只有ResponseMessage是必须的,其余的都是标准的Java类。

所以,我的问题是:我如何告诉 Swagger 要公开哪些模型

这是我的 Swagger 配置和我的控制器的代码 sn-p。

@Bean
public Docket api() {
    return new Docket(DocumentationType.SWAGGER_2)
            .select()
            .apis(RequestHandlerSelectors.basePackage("my.package"))
            .paths(PathSelectors.any())
            .build()
            .apiInfo(API_INFO)
            .useDefaultResponseMessages(false);
}

控制器:

@PostMapping(value = "/import", produces = MediaType.APPLICATION_JSON_VALUE, consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public ResponseEntity<?> importData(HttpServletRequest request) {

    // processing...

    return ResponseEntity.created(uri)
        .body(new ResponseMessage(HttpStatus.CREATED, "Your data is being processed"));
}

【问题讨论】:

标签: java spring-boot swagger swagger-ui


【解决方案1】:

你可以使用:

@Bean
public Docket api() {
    return new Docket(DocumentationType.SWAGGER_2).select()
            .apis(RequestHandlerSelectors.basePackage("com.package"))
            .paths(PathSelectors.regex("/api.*")).build().apiInfo(apiInfo())
            .ignoredParameterTypes(Timestamp.class);
}

这对我有用。在ignoredParameterTypes中指定类名后,swagger ui中不再存在。

【讨论】:

    【解决方案2】:

    您可以使用@ApiModelPropertyhidden 属性来隐藏模型的任何特定属性。它没有全局设置。

    一旦您声明了用于 swagger 扫描的基本包,swagger 就会为您开箱即用地生成包中所有组件的定义。但是,通过正确使用一组 swagger annotations,您可以覆盖/自定义您的 swagger 文档。

    请按照这些很棒的教程(12)来熟悉最有用的注释和用法。

    @Api、@ApiOperation、@ApiResponses、@ApiParam、@ApiIgnore、@ApiModel、@ApiModelProperty 等

    【讨论】:

    • 这不是我的问题。我想隐藏整个自动检测到的模型,而不是我模型的某些属性。
    • 您是否尝试过使用带有response 属性的@ApiOperation(value = "Some definition", response = MyModel.class) 来指向给定模型而不进行猜测?我知道这不是您的问题,但您要问的是,没有全局设置,您必须使用注释来自定义您的文档。
    • 我做到了。但我想知道如何隐藏或阻止 Swagger 自动检测一些不必要的类,例如FileInputStream,如您在屏幕截图中看到的那样。
    • 我需要更多关于你的包结构的信息,然后是更多在控制器和模型类上显示 swagger 注释的代码,以便能够提供帮助。
    • 嗨,Triet,你能找到问题的答案吗??
    【解决方案3】:

    Springfox Swagger2 通过 GET /v2/api-docs 获取 UI 数据,它会映射到 springfox.documentation.swagger2.web.Sw​​agger2Controller.getDocumentation()。所以你可以创建一个 bean 来代替 'ServiceModelToSwagger2Mapper':

    @Primary
    @Component
    class CustomServiceModelToSwagger2Mapper : ServiceModelToSwagger2MapperImpl() {
        @Autowired
        private lateinit var modelMapper: ModelMapper
        @Autowired
        private lateinit var parameterMapper: ParameterMapper
        @Autowired
        private lateinit var securityMapper: SecurityMapper
        @Autowired
        private lateinit var licenseMapper: LicenseMapper
        @Autowired
        private lateinit var vendorExtensionsMapper: VendorExtensionsMapper
    
        override fun mapDocumentation(from: Documentation?): Swagger? {
            if (from == null) {
                return null
            }
    
            val swagger = Swagger()
    
            swagger.vendorExtensions = vendorExtensionsMapper.mapExtensions(from.vendorExtensions)
            swagger.schemes = mapSchemes(from.schemes)
            swagger.paths = mapApiListings(from.apiListings)
            swagger.host = from.host
    // ➡➡➡➡➡➡➡➡➡➡➡➡➡➡➡➡ here
            swagger.definitions = this.modelsFromApiListings(from.apiListings)
            swagger.securityDefinitions = securityMapper.toSecuritySchemeDefinitions(from.resourceListing)
            val info = fromResourceListingInfo(from)
            if (info != null) {
                swagger.info = mapApiInfo(info)
            }
            swagger.basePath = from.basePath
            swagger.tags = tagSetToTagList(from.tags)
            val list2 = from.consumes
            if (list2 != null) {
                swagger.consumes = ArrayList(list2)
            } else {
                swagger.consumes = null
            }
            val list3 = from.produces
            if (list3 != null) {
                swagger.produces = ArrayList(list3)
            } else {
                swagger.produces = null
            }
    
            return swagger
        }
    
        private fun fromResourceListingInfo(documentation: Documentation?): ApiInfo? {
            if (documentation == null) {
                return null
            }
            val resourceListing = documentation.resourceListing ?: return null
            return resourceListing.info ?: return null
        }
    
    
        /**
         * @see ModelMapper
         */
        internal fun modelsFromApiListings(apiListings: Multimap<String, ApiListing>): Map<String, Model>? {
            val definitions = newTreeMap<String, springfox.documentation.schema.Model>()
            for (each in apiListings.values()) {
    // ➡➡➡➡➡➡➡➡➡➡➡➡➡➡➡➡ here
                // definitions.putAll(each.models)
                definitions.putAll(each.models.filter {
                    it.value.qualifiedType.startsWith("com.cpvsn")
                            && it.value.type.typeBindings.isEmpty    
                })
            }
            return modelMapper.mapModels(definitions)
        }
    }
    

    【讨论】:

      【解决方案4】:

      我可以通过在Docket() 中添加genericModuleSubstitutes() 来实现这一点。

      例子:

      .genericModelSubstitutes(ResponseEntity.class) 将用 MyModel 替换 ResponseEntity &lt;MyModel&gt;

      Reference

      【讨论】:

        【解决方案5】:
        @Bean
        UiConfiguration uiConfig() {
            return UiConfigurationBuilder.builder()
                    .defaultModelsExpandDepth(-1)
                    .build();
        }
        

        这对我有用。

        【讨论】:

          猜你喜欢
          • 2018-03-15
          • 2023-03-08
          • 2012-12-30
          • 2021-10-22
          • 2015-03-28
          • 1970-01-01
          • 2011-01-30
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多