2025年swagger2注解(swagger注解大全)

swagger2注解(swagger注解大全)先说一说 Springfox 和 Swagger 的关系 Swagger 是一种规范 springfox swagger 是基于 Spring 生态系统的该规范的实现 springfox swagger ui 是对 swagger ui 的封装 使得其可以使用 Spring 的服务 由于工作中遇到需要基于 Swagger Json 做一些处理 但 Swagger Json

大家好,我是讯享网,很高兴认识大家。






讯享网


先说一说Springfox和Swagger的关系

Swagger 是一种规范。

springfox-swagger 是基于 Spring 生态系统的该规范的实现。

springfox-swagger-ui 是对 swagger-ui 的封装,使得其可以使用 Spring 的服务。

由于工作中遇到需要基于 Swagger Json 做一些处理,但 Swagger Json 的格式不是那么满足需求。

本文springfox-swagger版本号:2.6.0

本文从问题出发,探索涉及的源码。

1. GET 方法的参数对象

第一个问题,当方法是GET请求,但参数是一个自定义 Object,在展示时(生成的JSON)是不包括本 Object 描述的。所以,就要看看什么时候会生成这些 Model 的描述。

万事有始有终,SpringFox始就在:springfox.documentation.spring.web.plugins下的 DocumentationPluginsBootstrapper

该类实现了 SmartLifecycle 接口,实现此接口且通过@Component注入到容器的bean, 容器初始化后会执行start()方法.

@Component
public class DocumentationPluginsBootstrapper implements SmartLifecycle {

讯享网

接着看 start 方法

讯享网@Override
public void start() {
    if (initialized.compareAndSet(false, true)) {
        // 拿到 DocumentationPlugin 插件
        List<DocumentationPlugin> plugins = pluginOrdering()
            .sortedCopy(documentationPluginsManager.documentationPlugins());
        for (DocumentationPlugin each : plugins) {
            //获取文档类型
            DocumentationType documentationType = each.getDocumentationType();
            if (each.isEnabled()) {
                // 启用则扫描生成文档
                scanDocumentation(buildContext(each));
            } 
        }
    }
}

调用了 buildContext 方法, 通过 Docket 对象创建 DocumentaionContext 对象

private DocumentationContext buildContext(DocumentationPlugin each) {
    return each.configure(this.defaultContextBuilder(each));
}

再往下走

讯享网private DocumentationContextBuilder defaultContextBuilder(DocumentationPlugin each) {
    DocumentationType documentationType = each.getDocumentationType();
    // 获取所有的RequestHnadler
    List<RequestHandler> requestHandlers = FluentIterable.from(this.handlerProviders).transformAndConcat(this.handlers()).toList();
    return this.documentationPluginsManager.createContextBuilder(documentationType, this.defaultConfiguration).requestHandlers(requestHandlers);
}

handlerProviders  RequestHandlerProvider 接口,实现类是 WebMvcRequestHandlerProvider,其中 requestHandlers 方法会接收Spring中的所有请求映射。

接着看 DocumentationContextBuilder的构造过程:documentationPluginsManager.createContextBuilder

public DocumentationContextBuilder createContextBuilder(DocumentationType documentationType,
                                                        DefaultConfiguration defaultConfiguration)
 
{
  return defaultsProviders.getPluginFor(documentationType, defaultConfiguration)
      .create(documentationType)
      .withResourceGroupingStrategy(resourceGroupingStrategy(documentationType));
}

defaultsProviders 是也是一个插件接口 DefaultsProviderPlugin,只有一个实现类DefaultConfiguration,不过该类未使用@Compoent注解,所以需要给一个替换值defaultConfiguration,也就是DefaultConfiguration。在看DefaultConfigurationcreate方法:

讯享网@Override
public DocumentationContextBuilder create(DocumentationType documentationType) {
  return new DocumentationContextBuilder(documentationType)
          .operationOrdering(defaults.operationOrdering())
          .apiDescriptionOrdering(defaults.apiDescriptionOrdering())
          .apiListingReferenceOrdering(defaults.apiListingReferenceOrdering())
          .additionalIgnorableTypes(defaults.defaultIgnorableParameterTypes())
          .rules(defaults.defaultRules(typeResolver))
          .defaultResponseMessages(defaults.defaultResponseMessages())
          .pathProvider(new RelativePathProvider(servletContext))
          .typeResolver(typeResolver)
          .enableUrlTemplating(false)
          .selector(ApiSelector.DEFAULT);
}

这里在给DocumentationContextBuilder设置相关参数,至此拿到了 DocumentationContextBuilder

回到上面提到的buildContext方法,defaultContextBuilder方法执行完毕,接下来是 configure

return each.configure(this.defaultContextBuilder(each));

DocumentationPlugin只有一个实现类Docket,到这里就有点熟悉了。Docket对象是我们开发人员在外部通过@Bean来创建的,而外部赋值的对象值,最终都会整合到DocumentationContext。这里的config就是在二次赋值。可以看一下一般自己定义的Docket对象。

讯享网public class SwaggerConfig {
    …
    @Bean
    public Docket docket() {
        …
        return new Docket(DocumentationType.SWAGGER_2)
                .groupName(SWAGGER_GROUP)
                .apiInfo(new ApiInfoBuilder().title(“xx”).version(“1.0.0”).build())
                ……
                .select()
                .apis(basePackage(“xxx”))
                .paths(PathSelectors.any())
                .build();
    }
}

到这里实际只设置了默认的参数。但接口,定义,模型等关键信息等都未初始化。

回到最初start(), 看看scanDocumentation(buildContext(each))scanDocumentation

private void scanDocumentation(DocumentationContext context) {
  scanned.addDocumentation(resourceListing.scan(context));
}

其中 scan 位于 ApiDocumentationScanner

讯享网public Documentation scan(DocumentationContext context) {
  ApiListingReferenceScanResult result = apiListingReferenceScanner.scan(context);
  …
  Multimap<String, ApiListing> apiListings = apiListingScanner.scan(listingContext);
  …

apiListingReferenceScanner.scan位于 ApiListingReferenceScanner

public ApiListingReferenceScanResult scan(DocumentationContext context) {
  …
  // 接口选择器 在构建Docket时通过.select()默认配置 
  ApiSelector selector = context.getApiSelector();
  // 根据package路径(一般)或注解区分, 过滤筛选掉不符规则的 RequestHandler 接口
  Iterable<RequestHandler> matchingHandlers = from(context.getRequestHandlers())
      .filter(selector.getRequestHandlerSelector());
  for (RequestHandler handler : matchingHandlers) {
    // 接口分组 resourceGroup = Controller,RequestMapping = method
    ResourceGroup resourceGroup = new ResourceGroup(handler.groupName(),
        handler.declaringClass(), 0);
    RequestMappingContext requestMappingContext
        = new RequestMappingContext(context, handler);
    resourceGroupRequestMappings.put(resourceGroup, requestMappingContext);
  }
  return new ApiListingReferenceScanResult(asMap(resourceGroupRequestMappings));
}

到这已经拿到了所有接口并进行了分组,其中ArrayListMultimap是guava的方法。

再回到 ApiDocumentationScanner scan方法,看 apiListingScanner.scan

讯享网public Multimap<String, ApiListing> scan(ApiListingScanningContext context) {
  …
  for (ResourceGroup resourceGroup : sortedByName(requestMappingsByResourceGroup.keySet())) {
    …
    for (RequestMappingContext each : sortedByMethods(requestMappingsByResourceGroup.get(resourceGroup))) {
      // 循环Controller下的所有接口的实例对象, 拿到该接口的所有Model
      models.putAll(apiModelReader.read(each.withKnownModels(models)));
      apiDescriptions.addAll(apiDescriptionReader.read(each));
    }

each.withKnownModels 是复制对象,主要看apiModelReader.read,读取该接口的 Model 信息。

public Map<String, Model> read(RequestMappingContext context) {
 // 忽略的class
  Set<Class> ignorableTypes = newHashSet(context.getIgnorableParameterTypes());
  Set<ModelContext> modelContexts = pluginsManager.modelContexts(context);
  Map<String, Model> modelMap = newHashMap(context.getModelMap());
  for (ModelContext each : modelContexts) {
    markIgnorablesAsHasSeen(typeResolver, ignorableTypes, each);
    Optional<Model> pModel = modelProvider.modelFor(each);
    if (pModel.isPresent()) {
      mergeModelMap(modelMap, pModel.get());
    } else {
    }
    populateDependencies(each, modelMap);
  }
  return modelMap;
}

就是从 modelContexts转化为 Model,看看pluginsManager.modelContexts,怎么取modelContexts

讯享网public Set<ModelContext> modelContexts(RequestMappingContext context) {
  DocumentationType documentationType = context.getDocumentationContext().getDocumentationType();
  // 构建接口的ModelContext集合
  for (OperationModelsProviderPlugin each : operationModelsProviders.getPluginsFor(documentationType)) {
    each.apply(context);
  }
  return context.operationModelsBuilder().build();
}

OperationModelsProviderPlugin有两个实现类,通过文档类型来获取。

  • OperationModelsProviderPlugin:处理返回类型,参数类型等
  • SwaggerOperationModelsProvider:swagger注解提供的值类型, @ApiResponse@ApiOperation

先看OperationModelsProviderPlugin

@Override
public void apply(RequestMappingContext context) {
  // 收集返回类型
  collectFromReturnType(context);
  // 收集参数类型
  collectParameters(context);
  // 收集接口型号
  collectGlobalModels(context);
}

到了这,本问题( GET 方法的请求Object不描述)的答案就要呼之欲出了。来看 collectParameters

讯享网private void collectParameters(RequestMappingContext context) {
  // 获取所有类型
  List<ResolvedMethodParameter> parameterTypes = context.getParameters();
  for (ResolvedMethodParameter parameterType : parameterTypes) {
    // 过滤  
    if (parameterType.hasParameterAnnotation(RequestBody.class)
          || parameterType.hasParameterAnnotation(RequestPart.class)) 
{
        ResolvedType modelType = context.alternateFor(parameterType.getParameterType());
        context.operationModelsBuilder().addInputParam(modelType);
      }
  }
}

破案了,可以看到过滤时只会处理两种:通过@RequestBody@ReuqestPart注解标注的, 而GET方法的参数是不可以使用这两个注解的。(当然从规范来说,GET方法也不应该这种参数)。

至于OperationModelsProviderPlugin的另一个实现类SwaggerOperationModelsProvider主要是收集使用@ApiOperation时主句属性值和@ApiResponse响应状态码涉及到的型号,不再详细列出。

apiModelReader.read中的 modelContexts转化为 ModelmodelProvider.modelFor()是通过ModelProvider实现,下一个问题会详细阐述。

那么,如何解决这个问题:

  1. 使用   DocketadditionalModels方法,在配置类中注入   TypeResolver
return new Docket(DocumentationType.SWAGGER_2)
.additionalModels(typeResolver.resolve(xxx))

  1. 借助第三方类库 如swagger-bootstrap-ui的工具类(我没接,但可以..)
  2. 重写

重写OperationModelsProviderPluginapply方法,添加自定义收集器。或者直接重写 collectParameters也行。比如

讯享网private void collectGetParameters(RequestMappingContext context) {
       …
       for (ResolvedMethodParameter parameterType : parameterTypes) {
           // 不存在@RequestBody注解
           if (!parameterType.hasParameterAnnotation(RequestBody.class)…) {
           …
               if (xxx) {
                   ResolvedType modelType = context.alternateFor(parameterType.getParameterType());
                   context.operationModelsBuilder().addInputParam(modelType);
               }
           } …
       }}

问题解决。

2. Enum的描述格式

问题是对于枚举类,在生成的JSON文件中描述是在原参数对象中的如下格式:

“xxx”: {…}
   “periodUnit”:{
      “type”:“string”,
      “enum”:[
               “MINUTE”,
               “HOUR”
               …
         ]}

一般枚举使用会如MINUTE(1,“分钟”),也就是包括了codename描述。

但实际enum的值会是二者之一。且不会生成如下的可重用的外部引用。

讯享网“schema”:{
          $ref:”#/definitions/xxxForm”
}

注意:可重用的问题在3.0+可以通过配置处理。

如果需要强制将enum的值设为codename,或拓展更多的内容,就需要来看看,enum类何时会被处理。

上一个问题的结尾说到apiModelReader.read&nbsp;modelContexts转化为&nbsp;ModelmodelProvider.modelFor()方法是通过ModelProvider实现,其实 ModelProvider是接口,有两个实现类:</p><ul data-tool="mdnice编辑器" class="list-paddingleft-2" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;"><li><section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);">DefaultModelProvider:默认,每次都会将modelContext转换为model</section></li><li><section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);">CachingModelProvider:声明了guava缓存池,先从缓存池取,没有则调用初始化处理器,转换为模型,再放入缓存池。</section></li></ul><p data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;padding-top: 8px;padding-bottom: 8px;line-height: 1.6;color: rgb(63, 63, 63);">在<code style="margin-right: 2px;margin-left: 2px;padding: 3px 5px;font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;background: rgb(248, 245, 236);color: rgb(255, 53, 2);line-height: 1.5;font-size: 14.4px;border-radius: 2px;">ApiModelReader</code>的构造方法里指定了使用<code style="margin-right: 2px;margin-left: 2px;padding: 3px 5px;font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;background: rgb(248, 245, 236);color: rgb(255, 53, 2);line-height: 1.5;font-size: 14.4px;border-radius: 2px;">CachingModelProvider</code>,不过第一次调用缓存里是没有的,所以往下走到<code style="margin-right: 2px;margin-left: 2px;padding: 3px 5px;font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;background: rgb(248, 245, 236);color: rgb(255, 53, 2);line-height: 1.5;font-size: 14.4px;border-radius: 2px;">populateDependencies</code></p><pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="margin-bottom: -7px;display: block;background: url(&quot;https://mmbiz.qpic.cn/mmbiz_png/N34tfh8WYkiaLFs2KuooHic09reYSOGCYN938V141MicAnZKbxKiaBibICHbtDaSlSpGgicp15VH7LxEEV02ywPiaoLsQ/640?wx_fmt=png&quot;) 10px 10px / 40px no-repeat rgb(250, 250, 250);height: 30px;width: 524px;border-radius: 5px;"></span><code style="padding: 15px 16px 16px;overflow-x: auto;color: rgb(56, 58, 66);display: -webkit-box;font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;font-size: 12px;background: rgb(250, 250, 250);border-radius: 5px;"><span style="line-height: 26px;"><span style="color: rgb(166, 38, 164);line-height: 26px;">private</span>&nbsp;<span style="color: rgb(166, 38, 164);line-height: 26px;">void</span>&nbsp;<span style="color: rgb(64, 120, 242);line-height: 26px;">populateDependencies</span><span style="line-height: 26px;">(ModelContext&nbsp;modelContext,&nbsp;Map&lt;String,&nbsp;Model&gt;&nbsp;modelMap)</span>&nbsp;</span>{<br />&nbsp;&nbsp;Map&lt;String,&nbsp;Model&gt;&nbsp;dependencies&nbsp;=&nbsp;modelProvider.dependencies(modelContext);<br />&nbsp;&nbsp;<span style="color: rgb(166, 38, 164);line-height: 26px;">for</span>&nbsp;(Model&nbsp;each&nbsp;:&nbsp;dependencies.values())&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;mergeModelMap(modelMap,&nbsp;each);<br />&nbsp;&nbsp;}<br />}<br /></code></pre><p data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;padding-top: 8px;padding-bottom: 8px;line-height: 1.6;color: rgb(63, 63, 63);"><code style="margin-right: 2px;margin-left: 2px;padding: 3px 5px;font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;background: rgb(248, 245, 236);color: rgb(255, 53, 2);line-height: 1.5;font-size: 14.4px;border-radius: 2px;">CachingModelProvider</code>的<code style="margin-right: 2px;margin-left: 2px;padding: 3px 5px;font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;background: rgb(248, 245, 236);color: rgb(255, 53, 2);line-height: 1.5;font-size: 14.4px;border-radius: 2px;">dependencies</code>依赖的是<code style="margin-right: 2px;margin-left: 2px;padding: 3px 5px;font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;background: rgb(248, 245, 236);color: rgb(255, 53, 2);line-height: 1.5;font-size: 14.4px;border-radius: 2px;">DefaultModelProvider</code>的</p><pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="margin-bottom: -7px;display: block;background: url(&quot;https://mmbiz.qpic.cn/mmbiz_png/N34tfh8WYkiaLFs2KuooHic09reYSOGCYN938V141MicAnZKbxKiaBibICHbtDaSlSpGgicp15VH7LxEEV02ywPiaoLsQ/640?wx_fmt=png&quot;) 10px 10px / 40px no-repeat rgb(250, 250, 250);height: 30px;width: 524px;border-radius: 5px;"></span><code style="padding: 15px 16px 16px;overflow-x: auto;color: rgb(56, 58, 66);display: -webkit-box;font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;font-size: 12px;background: rgb(250, 250, 250);border-radius: 5px;"><span style="line-height: 26px;"><span style="color: rgb(166, 38, 164);line-height: 26px;">public</span>&nbsp;Map&lt;String,&nbsp;Model&gt;&nbsp;<span style="color: rgb(64, 120, 242);line-height: 26px;">dependencies</span><span style="line-height: 26px;">(ModelContext&nbsp;modelContext)</span>&nbsp;</span>{<br />&nbsp;&nbsp;<span style="color: rgb(166, 38, 164);line-height: 26px;">return</span>&nbsp;delegate.dependencies(modelContext);<br />}<br /></code></pre><p data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;padding-top: 8px;padding-bottom: 8px;line-height: 1.6;color: rgb(63, 63, 63);">所以看<code style="margin-right: 2px;margin-left: 2px;padding: 3px 5px;font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;background: rgb(248, 245, 236);color: rgb(255, 53, 2);line-height: 1.5;font-size: 14.4px;border-radius: 2px;">DefaultModelProvider</code>中的实现</p><pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="margin-bottom: -7px;display: block;background: url(&quot;https://mmbiz.qpic.cn/mmbiz_png/N34tfh8WYkiaLFs2KuooHic09reYSOGCYN938V141MicAnZKbxKiaBibICHbtDaSlSpGgicp15VH7LxEEV02ywPiaoLsQ/640?wx_fmt=png&quot;) 10px 10px / 40px no-repeat rgb(250, 250, 250);height: 30px;width: 524px;border-radius: 5px;"></span><code style="padding: 15px 16px 16px;overflow-x: auto;color: rgb(56, 58, 66);display: -webkit-box;font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;font-size: 12px;background: rgb(250, 250, 250);border-radius: 5px;"><span style="line-height: 26px;"><span style="color: rgb(166, 38, 164);line-height: 26px;">public</span>&nbsp;Map&lt;String,&nbsp;Model&gt;&nbsp;<span style="color: rgb(64, 120, 242);line-height: 26px;">dependencies</span><span style="line-height: 26px;">(ModelContext&nbsp;modelContext)</span>&nbsp;</span>{<br />&nbsp;&nbsp;Map&lt;String,&nbsp;Model&gt;&nbsp;models&nbsp;=&nbsp;newHashMap();<br />&nbsp;&nbsp;<span style="color: rgb(166, 38, 164);line-height: 26px;">for</span>&nbsp;(ResolvedType&nbsp;resolvedType&nbsp;:&nbsp;dependencyProvider.dependentModels(modelContext))&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;ModelContext&nbsp;parentContext&nbsp;=&nbsp;ModelContext.fromParent(modelContext,&nbsp;resolvedType);<br />&nbsp;&nbsp;&nbsp;&nbsp;Optional&lt;Model&gt;&nbsp;model&nbsp;=&nbsp;modelFor(parentContext).or(mapModel(parentContext,&nbsp;resolvedType));<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: rgb(166, 38, 164);line-height: 26px;">if</span>&nbsp;(model.isPresent())&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;models.put(model.get().getName(),&nbsp;model.get());<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;}<br />&nbsp;&nbsp;<span style="color: rgb(166, 38, 164);line-height: 26px;">return</span>&nbsp;models;<br />}<br /></code></pre><p data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;padding-top: 8px;padding-bottom: 8px;line-height: 1.6;color: rgb(63, 63, 63);"><code style="margin-right: 2px;margin-left: 2px;padding: 3px 5px;font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;background: rgb(248, 245, 236);color: rgb(255, 53, 2);line-height: 1.5;font-size: 14.4px;border-radius: 2px;">dependencyProvider.dependentModels</code>和上面一个路子,一默认一缓存,交替接口。</p><pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="margin-bottom: -7px;display: block;background: url(&quot;https://mmbiz.qpic.cn/mmbiz_png/N34tfh8WYkiaLFs2KuooHic09reYSOGCYN938V141MicAnZKbxKiaBibICHbtDaSlSpGgicp15VH7LxEEV02ywPiaoLsQ/640?wx_fmt=png&quot;) 10px 10px / 40px no-repeat rgb(250, 250, 250);height: 30px;width: 524px;border-radius: 5px;"></span><code style="padding: 15px 16px 16px;overflow-x: auto;color: rgb(56, 58, 66);display: -webkit-box;font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;font-size: 12px;background: rgb(250, 250, 250);border-radius: 5px;"><span style="line-height: 26px;"><span style="color: rgb(166, 38, 164);line-height: 26px;">public</span>&nbsp;Set&lt;ResolvedType&gt;&nbsp;<span style="color: rgb(64, 120, 242);line-height: 26px;">dependentModels</span><span style="line-height: 26px;">(ModelContext&nbsp;modelContext)</span>&nbsp;</span>{<br />&nbsp;&nbsp;<span style="color: rgb(166, 38, 164);line-height: 26px;">return</span>&nbsp;from(resolvedDependencies(modelContext))<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.filter(ignorableTypes(modelContext))<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.filter(not(baseTypes(modelContext)))<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.toSet();<br />}<br /></code></pre><p data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;padding-top: 8px;padding-bottom: 8px;line-height: 1.6;color: rgb(63, 63, 63);">后面是两个过滤,暂且不提。看<code style="margin-right: 2px;margin-left: 2px;padding: 3px 5px;font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;background: rgb(248, 245, 236);color: rgb(255, 53, 2);line-height: 1.5;font-size: 14.4px;border-radius: 2px;">resolvedDependencies</code></p><pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="margin-bottom: -7px;display: block;background: url(&quot;https://mmbiz.qpic.cn/mmbiz_png/N34tfh8WYkiaLFs2KuooHic09reYSOGCYN938V141MicAnZKbxKiaBibICHbtDaSlSpGgicp15VH7LxEEV02ywPiaoLsQ/640?wx_fmt=png&quot;) 10px 10px / 40px no-repeat rgb(250, 250, 250);height: 30px;width: 524px;border-radius: 5px;"></span><code style="padding: 15px 16px 16px;overflow-x: auto;color: rgb(56, 58, 66);display: -webkit-box;font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;font-size: 12px;background: rgb(250, 250, 250);border-radius: 5px;"><span style="line-height: 26px;"><span style="color: rgb(166, 38, 164);line-height: 26px;">private</span>&nbsp;List&lt;ResolvedType&gt;&nbsp;<span style="color: rgb(64, 120, 242);line-height: 26px;">resolvedDependencies</span><span style="line-height: 26px;">(ModelContext&nbsp;modelContext)</span>&nbsp;</span>{<br />&nbsp;&nbsp;...<br />&nbsp;&nbsp;List&lt;ResolvedType&gt;&nbsp;dependencies&nbsp;=&nbsp;newArrayList(resolvedTypeParameters(modelContext,&nbsp;resolvedType));<br />&nbsp;&nbsp;dependencies.addAll(resolvedArrayElementType(modelContext,&nbsp;resolvedType));<br />&nbsp;&nbsp;dependencies.addAll(resolvedPropertiesAndFields(modelContext,&nbsp;resolvedType));<br />&nbsp;&nbsp;...<br />}<br /></code></pre><p data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;padding-top: 8px;padding-bottom: 8px;line-height: 1.6;color: rgb(63, 63, 63);">这里都是在构造拓展类型<span>&nbsp;</span><code style="margin-right: 2px;margin-left: 2px;padding: 3px 5px;font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;background: rgb(248, 245, 236);color: rgb(255, 53, 2);line-height: 1.5;font-size: 14.4px;border-radius: 2px;">ResolvedType</code>,有一个叫<code style="margin-right: 2px;margin-left: 2px;padding: 3px 5px;font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;background: rgb(248, 245, 236);color: rgb(255, 53, 2);line-height: 1.5;font-size: 14.4px;border-radius: 2px;">resolvedPropertiesAndFields</code>,看名字就是它了,进去</p><pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="margin-bottom: -7px;display: block;background: url(&quot;https://mmbiz.qpic.cn/mmbiz_png/N34tfh8WYkiaLFs2KuooHic09reYSOGCYN938V141MicAnZKbxKiaBibICHbtDaSlSpGgicp15VH7LxEEV02ywPiaoLsQ/640?wx_fmt=png&quot;) 10px 10px / 40px no-repeat rgb(250, 250, 250);height: 30px;width: 524px;border-radius: 5px;"></span><code style="padding: 15px 16px 16px;overflow-x: auto;color: rgb(56, 58, 66);display: -webkit-box;font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;font-size: 12px;background: rgb(250, 250, 250);border-radius: 5px;"><span style="line-height: 26px;"><span style="color: rgb(166, 38, 164);line-height: 26px;">private</span>&nbsp;List&lt;ResolvedType&gt;&nbsp;<span style="color: rgb(64, 120, 242);line-height: 26px;">resolvedPropertiesAndFields</span><span style="line-height: 26px;">(ModelContext&nbsp;modelContext,&nbsp;ResolvedType&nbsp;resolvedType)</span>&nbsp;</span>{<br />&nbsp;&nbsp;...<br />&nbsp;&nbsp;List&lt;ResolvedType&gt;&nbsp;properties&nbsp;=&nbsp;newArrayList();<br />&nbsp;&nbsp;<span style="color: rgb(166, 38, 164);line-height: 26px;">for</span>&nbsp;(ModelProperty&nbsp;property&nbsp;:&nbsp;nonTrivialProperties(modelContext,&nbsp;resolvedType))&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;...<br />&nbsp;&nbsp;&nbsp;&nbsp;properties.addAll(maybeFromCollectionElementType(modelContext,&nbsp;property));<br />&nbsp;&nbsp;&nbsp;&nbsp;properties.addAll(maybeFromMapValueType(modelContext,&nbsp;property));<br />&nbsp;&nbsp;&nbsp;&nbsp;properties.addAll(maybeFromRegularType(modelContext,&nbsp;property));<br />&nbsp;&nbsp;}}<br /></code></pre><p data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;padding-top: 8px;padding-bottom: 8px;line-height: 1.6;color: rgb(63, 63, 63);">看到<code style="margin-right: 2px;margin-left: 2px;padding: 3px 5px;font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;background: rgb(248, 245, 236);color: rgb(255, 53, 2);line-height: 1.5;font-size: 14.4px;border-radius: 2px;">ModelProperty</code>,也就是对象内部属性代表的Model了,那就看<code style="margin-right: 2px;margin-left: 2px;padding: 3px 5px;font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;background: rgb(248, 245, 236);color: rgb(255, 53, 2);line-height: 1.5;font-size: 14.4px;border-radius: 2px;">nonTrivialProperties</code>方法</p><pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="margin-bottom: -7px;display: block;background: url(&quot;https://mmbiz.qpic.cn/mmbiz_png/N34tfh8WYkiaLFs2KuooHic09reYSOGCYN938V141MicAnZKbxKiaBibICHbtDaSlSpGgicp15VH7LxEEV02ywPiaoLsQ/640?wx_fmt=png&quot;) 10px 10px / 40px no-repeat rgb(250, 250, 250);height: 30px;width: 524px;border-radius: 5px;"></span><code style="padding: 15px 16px 16px;overflow-x: auto;color: rgb(56, 58, 66);display: -webkit-box;font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;font-size: 12px;background: rgb(250, 250, 250);border-radius: 5px;"><span style="line-height: 26px;"><span style="color: rgb(166, 38, 164);line-height: 26px;">private</span>&nbsp;FluentIterable&lt;ModelProperty&gt;&nbsp;<span style="color: rgb(64, 120, 242);line-height: 26px;">nonTrivialProperties</span><span style="line-height: 26px;">(ModelContext&nbsp;modelContext,&nbsp;ResolvedType&nbsp;resolvedType)</span>&nbsp;</span>{<br />&nbsp;&nbsp;<span style="color: rgb(166, 38, 164);line-height: 26px;">return</span>&nbsp;from(propertiesFor(modelContext,&nbsp;resolvedType))<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.filter(not(baseProperty(modelContext)));<br />}<br /></code></pre><p data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;padding-top: 8px;padding-bottom: 8px;line-height: 1.6;color: rgb(63, 63, 63);">之后是<code style="margin-right: 2px;margin-left: 2px;padding: 3px 5px;font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;background: rgb(248, 245, 236);color: rgb(255, 53, 2);line-height: 1.5;font-size: 14.4px;border-radius: 2px;">propertiesFor</code></p><pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="margin-bottom: -7px;display: block;background: url(&quot;https://mmbiz.qpic.cn/mmbiz_png/N34tfh8WYkiaLFs2KuooHic09reYSOGCYN938V141MicAnZKbxKiaBibICHbtDaSlSpGgicp15VH7LxEEV02ywPiaoLsQ/640?wx_fmt=png&quot;) 10px 10px / 40px no-repeat rgb(250, 250, 250);height: 30px;width: 524px;border-radius: 5px;"></span><code style="padding: 15px 16px 16px;overflow-x: auto;color: rgb(56, 58, 66);display: -webkit-box;font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;font-size: 12px;background: rgb(250, 250, 250);border-radius: 5px;"><span style="line-height: 26px;"><span style="color: rgb(166, 38, 164);line-height: 26px;">private</span>&nbsp;List&lt;ModelProperty&gt;&nbsp;<span style="color: rgb(64, 120, 242);line-height: 26px;">propertiesFor</span><span style="line-height: 26px;">(ModelContext&nbsp;modelContext,&nbsp;ResolvedType&nbsp;resolvedType)</span>&nbsp;</span>{<br />&nbsp;&nbsp;<span style="color: rgb(166, 38, 164);line-height: 26px;">return</span>&nbsp;propertiesProvider.propertiesFor(resolvedType,&nbsp;modelContext);<br />}<br /></code></pre><p data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;padding-top: 8px;padding-bottom: 8px;line-height: 1.6;color: rgb(63, 63, 63);">这个<code style="margin-right: 2px;margin-left: 2px;padding: 3px 5px;font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;background: rgb(248, 245, 236);color: rgb(255, 53, 2);line-height: 1.5;font-size: 14.4px;border-radius: 2px;">propertiesProvider.propertiesFor</code>仍是一cache一default的策略,直接看实现</p><pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="margin-bottom: -7px;display: block;background: url(&quot;https://mmbiz.qpic.cn/mmbiz_png/N34tfh8WYkiaLFs2KuooHic09reYSOGCYN938V141MicAnZKbxKiaBibICHbtDaSlSpGgicp15VH7LxEEV02ywPiaoLsQ/640?wx_fmt=png&quot;) 10px 10px / 40px no-repeat rgb(250, 250, 250);height: 30px;width: 524px;border-radius: 5px;"></span><code style="padding: 15px 16px 16px;overflow-x: auto;color: rgb(56, 58, 66);display: -webkit-box;font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;font-size: 12px;background: rgb(250, 250, 250);border-radius: 5px;"><span style="line-height: 26px;"><span style="color: rgb(166, 38, 164);line-height: 26px;">public</span>&nbsp;List&lt;ModelProperty&gt;&nbsp;<span style="color: rgb(64, 120, 242);line-height: 26px;">propertiesFor</span><span style="line-height: 26px;">(ResolvedType&nbsp;type,&nbsp;ModelContext&nbsp;givenContext)</span>&nbsp;</span>{<br />&nbsp;&nbsp;...<br />&nbsp;&nbsp;<span style="color: rgb(166, 38, 164);line-height: 26px;">for</span>&nbsp;(Map.Entry&lt;String,&nbsp;BeanPropertyDefinition&gt;&nbsp;each&nbsp;:&nbsp;propertyLookup.entrySet())&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;BeanPropertyDefinition&nbsp;jacksonProperty&nbsp;=&nbsp;each.getValue();<br />&nbsp;&nbsp;&nbsp;&nbsp;Optional&lt;AnnotatedMember&gt;&nbsp;annotatedMember<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;=&nbsp;Optional.fromNullable(safeGetPrimaryMember(jacksonProperty));<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: rgb(166, 38, 164);line-height: 26px;">if</span>&nbsp;(annotatedMember.isPresent())&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;properties.addAll(candidateProperties(type,&nbsp;annotatedMember.get(),&nbsp;jacksonProperty,&nbsp;givenContext));<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;}...<br />}<br /></code></pre><p data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;padding-top: 8px;padding-bottom: 8px;line-height: 1.6;color: rgb(63, 63, 63);">可以看到<span>&nbsp;</span><code style="margin-right: 2px;margin-left: 2px;padding: 3px 5px;font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;background: rgb(248, 245, 236);color: rgb(255, 53, 2);line-height: 1.5;font-size: 14.4px;border-radius: 2px;">List&lt;ModelProperty&gt;</code>通过<span>&nbsp;</span><code style="margin-right: 2px;margin-left: 2px;padding: 3px 5px;font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;background: rgb(248, 245, 236);color: rgb(255, 53, 2);line-height: 1.5;font-size: 14.4px;border-radius: 2px;">candidateProperties</code>方法获取</p><pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="margin-bottom: -7px;display: block;background: url(&quot;https://mmbiz.qpic.cn/mmbiz_png/N34tfh8WYkiaLFs2KuooHic09reYSOGCYN938V141MicAnZKbxKiaBibICHbtDaSlSpGgicp15VH7LxEEV02ywPiaoLsQ/640?wx_fmt=png&quot;) 10px 10px / 40px no-repeat rgb(250, 250, 250);height: 30px;width: 524px;border-radius: 5px;"></span><code style="padding: 15px 16px 16px;overflow-x: auto;color: rgb(56, 58, 66);display: -webkit-box;font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;font-size: 12px;background: rgb(250, 250, 250);border-radius: 5px;"><span style="color: rgb(64, 120, 242);line-height: 26px;">@VisibleForTesting</span><br /><span style="line-height: 26px;">List&lt;ModelProperty&gt;&nbsp;<span style="color: rgb(64, 120, 242);line-height: 26px;">candidateProperties</span><span style="line-height: 26px;">(<br />&nbsp;&nbsp;&nbsp;&nbsp;ResolvedType&nbsp;type,<br />&nbsp;&nbsp;&nbsp;&nbsp;AnnotatedMember&nbsp;member,<br />&nbsp;&nbsp;&nbsp;&nbsp;BeanPropertyDefinition&nbsp;jacksonProperty,<br />&nbsp;&nbsp;&nbsp;&nbsp;ModelContext&nbsp;givenContext)</span>&nbsp;</span>{<br />&nbsp;&nbsp;List&lt;ModelProperty&gt;&nbsp;properties&nbsp;=&nbsp;newArrayList();<br />&nbsp;&nbsp;<span style="color: rgb(166, 38, 164);line-height: 26px;">if</span>&nbsp;(member&nbsp;<span style="color: rgb(166, 38, 164);line-height: 26px;">instanceof</span>&nbsp;AnnotatedMethod)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;properties.addAll(findAccessorMethod(type,&nbsp;member)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.transform(propertyFromBean(givenContext,&nbsp;jacksonProperty))<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.or(<span style="color: rgb(166, 38, 164);line-height: 26px;">new</span>&nbsp;ArrayList&lt;ModelProperty&gt;()));<br />&nbsp;&nbsp;}&nbsp;<span style="color: rgb(166, 38, 164);line-height: 26px;">else</span>&nbsp;<span style="color: rgb(166, 38, 164);line-height: 26px;">if</span>&nbsp;(member&nbsp;<span style="color: rgb(166, 38, 164);line-height: 26px;">instanceof</span>&nbsp;AnnotatedField)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;properties.addAll(findField(type,&nbsp;jacksonProperty.getInternalName())<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.transform(propertyFromField(givenContext,&nbsp;jacksonProperty))<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.or(<span style="color: rgb(166, 38, 164);line-height: 26px;">new</span>&nbsp;ArrayList&lt;ModelProperty&gt;()));<br />&nbsp;&nbsp;}&nbsp;<span style="color: rgb(166, 38, 164);line-height: 26px;">else</span>&nbsp;<span style="color: rgb(166, 38, 164);line-height: 26px;">if</span>&nbsp;(member&nbsp;<span style="color: rgb(166, 38, 164);line-height: 26px;">instanceof</span>&nbsp;AnnotatedParameter)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;ModelContext&nbsp;modelContext&nbsp;=&nbsp;ModelContext.fromParent(givenContext,&nbsp;type);<br />&nbsp;&nbsp;&nbsp;&nbsp;properties.addAll(fromFactoryMethod(type,&nbsp;jacksonProperty,&nbsp;(AnnotatedParameter)&nbsp;member,&nbsp;modelContext));<br />&nbsp;&nbsp;}<br />&nbsp;...<br />}<br /></code></pre><p data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;padding-top: 8px;padding-bottom: 8px;line-height: 1.6;color: rgb(63, 63, 63);">这里根据<span>&nbsp;</span><code style="margin-right: 2px;margin-left: 2px;padding: 3px 5px;font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;background: rgb(248, 245, 236);color: rgb(255, 53, 2);line-height: 1.5;font-size: 14.4px;border-radius: 2px;">AnnotatedMember</code>判断类成员的类型,进行不同的处理。enum使用的是<span>&nbsp;</span><code style="margin-right: 2px;margin-left: 2px;padding: 3px 5px;font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;background: rgb(248, 245, 236);color: rgb(255, 53, 2);line-height: 1.5;font-size: 14.4px;border-radius: 2px;">propertyFromBean</code></p><pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="margin-bottom: -7px;display: block;background: url(&quot;https://mmbiz.qpic.cn/mmbiz_png/N34tfh8WYkiaLFs2KuooHic09reYSOGCYN938V141MicAnZKbxKiaBibICHbtDaSlSpGgicp15VH7LxEEV02ywPiaoLsQ/640?wx_fmt=png&quot;) 10px 10px / 40px no-repeat rgb(250, 250, 250);height: 30px;width: 524px;border-radius: 5px;"></span><code style="padding: 15px 16px 16px;overflow-x: auto;color: rgb(56, 58, 66);display: -webkit-box;font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;font-size: 12px;background: rgb(250, 250, 250);border-radius: 5px;">...<br />&nbsp;&nbsp;<span style="line-height: 26px;"><span style="color: rgb(166, 38, 164);line-height: 26px;">public</span>&nbsp;List&lt;ModelProperty&gt;&nbsp;<span style="color: rgb(64, 120, 242);line-height: 26px;">apply</span><span style="line-height: 26px;">(ResolvedMethod&nbsp;input)</span>&nbsp;</span>{<br />&nbsp;&nbsp;&nbsp;&nbsp;ResolvedType&nbsp;type&nbsp;=&nbsp;paramOrReturnType(typeResolver,&nbsp;input);<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: rgb(166, 38, 164);line-height: 26px;">if</span>&nbsp;(!givenContext.canIgnore(type))&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: rgb(166, 38, 164);line-height: 26px;">if</span>&nbsp;(shouldUnwrap(input))&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: rgb(166, 38, 164);line-height: 26px;">return</span>&nbsp;propertiesFor(type,&nbsp;fromParent(givenContext,&nbsp;type));<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: rgb(166, 38, 164);line-height: 26px;">return</span>&nbsp;newArrayList(beanModelProperty(input,&nbsp;jacksonProperty,&nbsp;givenContext));<br />&nbsp;&nbsp;&nbsp;&nbsp;}...<br />&nbsp;&nbsp;&nbsp;&nbsp;}};<br /></code></pre><p data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;padding-top: 8px;padding-bottom: 8px;line-height: 1.6;color: rgb(63, 63, 63);">接着是<span>&nbsp;</span><code style="margin-right: 2px;margin-left: 2px;padding: 3px 5px;font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;background: rgb(248, 245, 236);color: rgb(255, 53, 2);line-height: 1.5;font-size: 14.4px;border-radius: 2px;">beanModelProperty</code></p><pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="margin-bottom: -7px;display: block;background: url(&quot;https://mmbiz.qpic.cn/mmbiz_png/N34tfh8WYkiaLFs2KuooHic09reYSOGCYN938V141MicAnZKbxKiaBibICHbtDaSlSpGgicp15VH7LxEEV02ywPiaoLsQ/640?wx_fmt=png&quot;) 10px 10px / 40px no-repeat rgb(250, 250, 250);height: 30px;width: 524px;border-radius: 5px;"></span><code style="padding: 15px 16px 16px;overflow-x: auto;color: rgb(56, 58, 66);display: -webkit-box;font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;font-size: 12px;background: rgb(250, 250, 250);border-radius: 5px;"><span style="line-height: 26px;"><span style="color: rgb(166, 38, 164);line-height: 26px;">private</span>&nbsp;ModelProperty&nbsp;<span style="color: rgb(64, 120, 242);line-height: 26px;">beanModelProperty</span><span style="line-height: 26px;">(<br />&nbsp;&nbsp;&nbsp;&nbsp;...<br />&nbsp;&nbsp;return&nbsp;schemaPluginsManager.property(<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;new&nbsp;ModelPropertyContext(propertyBuilder,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;jacksonProperty,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;typeResolver,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;...<br /></span></span></code></pre><p data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;padding-top: 8px;padding-bottom: 8px;line-height: 1.6;color: rgb(63, 63, 63);">最后调用了<span>&nbsp;</span><code style="margin-right: 2px;margin-left: 2px;padding: 3px 5px;font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;word-break: break-all;background: rgb(248, 245, 236);color: rgb(255, 53, 2);line-height: 1.5;font-size: 14.4px;border-radius: 2px;">schemaPluginsManager.property</code></p><pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="margin-bottom: -7px;display: block;background: url(&quot;https://mmbiz.qpic.cn/mmbiz_png/N34tfh8WYkiaLFs2KuooHic09reYSOGCYN938V141MicAnZKbxKiaBibICHbtDaSlSpGgicp15VH7LxEEV02ywPiaoLsQ/640?wx_fmt=png&quot;) 10px 10px / 40px no-repeat rgb(250, 250, 250);height: 30px;width: 524px;border-radius: 5px;"></span><code style="padding: 15px 16px 16px;overflow-x: auto;color: rgb(56, 58, 66);display: -webkit-box;font-family: &quot;Operator Mono&quot;, Consolas, Monaco, Menlo, monospace;font-size: 12px;background: rgb(250, 250, 250);border-radius: 5px;"><span style="line-height: 26px;"><span style="color: rgb(166, 38, 164);line-height: 26px;">public</span>&nbsp;ModelProperty&nbsp;<span style="color: rgb(64, 120, 242);line-height: 26px;">property</span><span style="line-height: 26px;">(ModelPropertyContext&nbsp;context)</span>&nbsp;</span>{<br />&nbsp;&nbsp;<span style="color: rgb(160, 161, 167);font-style: italic;line-height: 26px;">//&nbsp;根据文档类型取出&nbsp;ModelPropertyBuilderPlugin</span><br />&nbsp;&nbsp;<span style="color: rgb(166, 38, 164);line-height: 26px;">for</span>&nbsp;(ModelPropertyBuilderPlugin&nbsp;enricher&nbsp;:&nbsp;propertyEnrichers.getPluginsFor(context.getDocumentationType()))&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;enricher.apply(context);<br />&nbsp;&nbsp;}<br />&nbsp;&nbsp;<span style="color: rgb(166, 38, 164);line-height: 26px;">return</span>&nbsp;context.getBuilder().build();<br />}<br />ModelPropertyBuilderPlugin是一个接口,看它的其中一个实现类`ApiModelPropertyPropertyBuilder
public&nbsp;void&nbsp;apply(ModelPropertyContext&nbsp;context)&nbsp;
{
&nbsp;&nbsp;//&nbsp;取出元素的注解
&nbsp;&nbsp;Optional&lt;ApiModelProperty&gt;&nbsp;annotation&nbsp;=&nbsp;Optional.absent();
&nbsp;&nbsp;…
&nbsp;&nbsp;if&nbsp;(annotation.isPresent())&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;context.getBuilder()
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.allowableValues(annotation.transform(toAllowableValues()).orNull())
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.required(annotation.transform(toIsRequired()).or(false))
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.readOnly(annotation.transform(toIsReadOnly()).or(false))
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.description(annotation.transform(toDescription()).orNull())
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.isHidden(annotation.transform(toHidden()).or(false))
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.type(annotation.transform(toType(context.getResolver())).orNull())
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.position(annotation.transform(toPosition()).or(0))
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.example(annotation.transform(toExample()).orNull());
&nbsp;&nbsp;}
}

可以看到通过判断是否存在注解,再设置具体的配置。

其中type就是enum展示的类型了,可以固定。allowableValues就是enumvalue,可以自定义,还可以加入description.

具体实现可以通过重写ApiModelPropertyPropertyBuilderapply实现。

到这里,两个问题都得到解决。Springfox的加载过程也基本介绍了一遍。

Redis面试突击专用

InnoDB中一棵B+树可以存放多少行数据?

你这个数据量多大?分库分表怎么做?用的哪个组件?

关于 TCP/IP,必知必会的十个问题

因为BitMap,白白搭进去8台服务器…

&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Java架构师日记&nbsp;&nbsp; &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; &nbsp;&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;扫描上面二维码发现更多精彩!&nbsp;&nbsp; &nbsp; &nbsp;&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;

小贴士

返回 上一级 输入“基础&nbsp;等关键词获取相关资料推荐。

小讯
上一篇 2025-05-04 16:40
下一篇 2025-05-15 13:11

相关推荐

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/169399.html