:::info 这里暂不记录入门配置,只记录一些相对有需求的针对性配置 :::
Model 名称生成
@ApiModelpublic class AccountSearchReq extends PageQuery {@ApiModelProperty("邮箱")@Size(max = 50)private String email;
使用 @ApiModel 作用的类的相关信息会出现在 Swagger 对应的接口上
但是当你有相同的 类名 时(不同包,都被 @ApiModel 作用时),对应接口里面的信息就不一定是实际接口上匹配的了。
上图实际接口对应的类,属性没有这么多,这个多属性的实际上是另一个接口的
造成这个的问题原因是:Swagger 的默认起名策略是类名(Class.getSimpleName()),我们有三种办法解决这个问题:
- 手动命名成不同名的类
- 在
@ApiModel中自定义名称:这种方式很简单,@ApiModel的 value 就是自定义名称,如@ApiModel("A 模块 - 搜索请求") - 使用插件功能
TypeNameProviderPlugin自定义名称
这里主要讲解第三种,配置一次,所有的类都走这个策略,其实也很简单,步骤如下:
- 实现
springfox.documentation.spi.schema.TypeNameProviderPlugin接口 - 交给 Spring 容器
实现 TypeNameProviderPlugin
package cn.mrcode.autoconfig;import org.springframework.core.annotation.Order;import springfox.documentation.spi.DocumentationType;import springfox.documentation.spi.schema.TypeNameProviderPlugin;import springfox.documentation.swagger.common.SwaggerPluginSupport;/*** @author mrcode* @date 2022/11/2 17:50*/@Order(SwaggerPluginSupport.SWAGGER_PLUGIN_ORDER - 100)public class MyTypeNameProviderPlugin implements TypeNameProviderPlugin {@Overridepublic String nameFor(Class<?> type) {// 这里是 model 的类的 class// 直接返回全路径的限定类名称return type.getName();}@Overridepublic boolean supports(DocumentationType delimiter) {// 说一些条件判定,是否支持这个文档(文档概念可以参考官方文档,一般项目是用不上的)return true;}}
交给 Spring 容器
package cn.mrcode.autoconfig;import org.springframework.context.annotation.Bean;import org.springframework.stereotype.Component;import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;import springfox.documentation.builders.ApiInfoBuilder;import springfox.documentation.builders.RequestHandlerSelectors;import springfox.documentation.service.ApiInfo;import springfox.documentation.spi.DocumentationType;import springfox.documentation.spi.schema.TypeNameProviderPlugin;import springfox.documentation.spring.web.plugins.Docket;import springfox.documentation.swagger2.annotations.EnableSwagger2;@EnableSwagger2 // http://localhost:11000/swagger-ui/index.html@Componentpublic class SwaggerUiWebMvcConfigurer implements WebMvcConfigurer {@Overridepublic void addResourceHandlers(ResourceHandlerRegistry registry) {registry.addResourceHandler("/swagger-ui/**").addResourceLocations("classpath:/META-INF/resources/webjars/springfox-swagger-ui/").resourceChain(false);}@Overridepublic void addViewControllers(ViewControllerRegistry registry) {registry.addViewController("/swagger-ui/").setViewName("forward:/swagger-ui/index.html");}@Beanpublic Docket customDocket() {return new Docket(DocumentationType.SWAGGER_2)// 修正 Byte 类型被识别为 string 类型的问题.directModelSubstitute(Byte.class, Integer.class).select().apis(RequestHandlerSelectors.basePackage("cn.mrcode.web.controller")).build().apiInfo(apiInfo());}ApiInfo apiInfo() {return new ApiInfoBuilder().title("系统名称").description("" +"<h4>携带 accessToken 的两种方式:</h4>" +"\n 1. 在 url 中使用参数形式 access_token" +"\n 2. 在请求头中使 Authorization: bearer {{access_token}} 形式").version("1.0.0").build();}@Beanpublic TypeNameProviderPlugin typeNameProviderPlugin() {return new MyTypeNameProviderPlugin();}}
方案原理
官方文档的插件中有提到过这个插件,它的作用就是 用于覆盖 Model 的名称
在源码中是在 springfox.documentation.schema.TypeNameExtractor 被处理收集的。springfox.documentation.swagger.schema.ApiModelTypeNameProvider 是 Swagger 提供生成 Model 默认的名称生成类,也会被注册到 extractor 中去,但是它使用了 @Order 来排序,数字越小的会先执行,执行之后,后续的插件不会走了。所以我们在实现自己的插件的时候,需要设置比框架默认的插件数字要小,比如前面就设置的是 @Order(SwaggerPluginSupport.SWAGGER_PLUGIN_ORDER - 100)
