​Springfox swagger2 源码解析

​Springfox swagger2 源码解析

doc访问页面 http://localhost:8080/doc.html

api-json访问页面 http://localhost:8080/v2/api-docs

 

pom依赖

<!-- https://mvnrepository.com/artifact/com.github.xiaoymin/knife4j-spring-boot-starter --><dependency>  <groupId>com.github.xiaoymin</groupId>  <artifactId>knife4j-spring-boot-starter</artifactId>  <version>3.0.2</version></dependency>

根据路径/v2/api-docs顺藤摸瓜 找到 Swagger2ControllerWebMvc

@RequestMapping(      method = RequestMethod.GET,      produces = {APPLICATION_JSON_VALUE, HAL_MEDIA_TYPE})  public ResponseEntity<Json> getDocumentation(      @RequestParam(value = "group", required = false) String swaggerGroup,      HttpServletRequest servletRequest) {    String groupName = ofNullable(swaggerGroup).orElse(Docket.DEFAULT_GROUP_NAME);    Documentation documentation = documentationCache.documentationByGroup(groupName);    if (documentation == null) {      LOGGER.warn("Unable to find specification for group {}", groupName);      return new ResponseEntity<>(HttpStatus.NOT_FOUND);    }    Swagger swagger = mapper.mapDocumentation(documentation);    SwaggerTransformationContext<HttpServletRequest> context        = new SwaggerTransformationContext<>(swagger, servletRequest);    List<WebMvcSwaggerTransformationFilter> filters = transformations.getPluginsFor(DocumentationType.SWAGGER_2);    for (WebMvcSwaggerTransformationFilter each : filters) {      context = context.next(each.transform(context));    }    return new ResponseEntity<>(jsonSerializer.toJson(context.getSpecification()), HttpStatus.OK);  }}

从缓存中获取文档

Documentation documentation = documentationCache.documentationByGroup(groupName);

 

何时加载缓存文档呢?

由文档加载器DocumentationPluginsBootstrapper进行加载,类实现了SmartLifecycle接口,当spring加载完bean后,调用start()方法进行加载。

public class DocumentationPluginsBootstrapper    extends AbstractDocumentationPluginsBootstrapper    implements SmartLifecycle{                public DocumentationPluginsBootstrapper(            DocumentationPluginsManager documentationPluginsManager,            List<RequestHandlerProvider> handlerProviders,            DocumentationCache scanned,            ApiDocumentationScanner resourceListing,            TypeResolver typeResolver,            Defaults defaults,            PathProvider pathProvider,            Environment environment) {          super(              documentationPluginsManager,              handlerProviders,              scanned,              resourceListing,              defaults,              typeResolver,              pathProvider);                  this.environment = environment;        }        // bean 加载完成后调用        public void start() {          if (initialized.compareAndSet(false, true)) {            LOGGER.debug("Documentation plugins bootstrapped");            super.bootstrapDocumentationPlugins();          }        }    }

 


Spring SmartLifecycle 在容器所有bean加载和初始化完毕执行

在使用Spring开发时,我们都知道,所有bean都交给Spring容器来统一管理,其中包括每一个bean的加载和初始化。

有时候我们需要在Spring加载和初始化所有bean后,接着执行一些任务或者启动需要的异步服务,这样我们可以使用 SmartLifecycle 来做到。

这个和 @PostConstruct、@PreDestroy 的bean的初始化和销毁方法不同,Bean生命周期级别和容器生命周期级别在应用场景上是有区别的。

SmartLifecycle 是一个接口。当Spring容器加载所有bean并完成初始化之后,会接着回调实现该接口的类中对应的方法(start()方法)。


 

 

文档插件管理器 DocumentationPluginsManager

此类以PluginRegistry的方式注入了一系列插件

documentationPlugins()方法调用了DocumentationPlugin 文档插件,若没有则生成一个默认的插件Docket,通常在Swagger2Configuration配置文件会注入一个Docket。

@Componentpublic class DocumentationPluginsManager {  @Autowired  @Qualifier("documentationPluginRegistry")  private PluginRegistry<DocumentationPlugin, DocumentationType> documentationPlugins;  @Autowired  @Qualifier("apiListingBuilderPluginRegistry")  private PluginRegistry<ApiListingBuilderPlugin, DocumentationType> apiListingPlugins;  @Autowired  @Qualifier("parameterBuilderPluginRegistry")  private PluginRegistry<ParameterBuilderPlugin, DocumentationType> parameterPlugins;  @Autowired  @Qualifier("expandedParameterBuilderPluginRegistry")  private PluginRegistry<ExpandedParameterBuilderPlugin, DocumentationType> parameterExpanderPlugins;  @Autowired  @Qualifier("operationBuilderPluginRegistry")  private PluginRegistry<OperationBuilderPlugin, DocumentationType> operationBuilderPlugins;  @Autowired  @Qualifier("operationModelsProviderPluginRegistry")  private PluginRegistry<OperationModelsProviderPlugin, DocumentationType> operationModelsProviders;  @Autowired  @Qualifier("defaultsProviderPluginRegistry")  private PluginRegistry<DefaultsProviderPlugin, DocumentationType> defaultsProviders;  @Autowired  @Qualifier("pathDecoratorRegistry")  private PluginRegistry<PathDecorator, DocumentationContext> pathDecorators;  @Autowired  @Qualifier("apiListingScannerPluginRegistry")  private PluginRegistry<ApiListingScannerPlugin, DocumentationType> apiListingScanners;  @Autowired  @Qualifier("responseBuilderPluginRegistry")  private PluginRegistry<ResponseBuilderPlugin, DocumentationType> responsePlugins;  @Autowired  @Qualifier("modelNamesRegistryFactoryPluginRegistry")  private PluginRegistry<ModelNamesRegistryFactoryPlugin, DocumentationType> modelNameRegistryFactoryPlugins;  public Collection<DocumentationPlugin> documentationPlugins() throws IllegalStateException {    List<DocumentationPlugin> plugins = documentationPlugins.getPlugins();    ensureNoDuplicateGroups(plugins);    if (plugins.isEmpty()) {      return singleton(defaultDocumentationPlugin());    }    return plugins;  }

例如 OperationBuilderPlugin

PluginRegistry<OperationBuilderPlugin,DocumentationType> operationBuilderPlugins

 

Control + H 查看其继承结构

 

栗子:

SwaggerResponseMessageReader实现了ResponseMessage的读取。read()方法从OperationContext上下文中获取ApiOperation、ResponseHeader、ApiResponse注解信息。

public class SwaggerResponseMessageReader implements OperationBuilderPlugin {    protected Compatibility<Set<ResponseMessage>, Set<Response>> read(OperationContext context) {}}

 


PluginRegistry

Spring Plugin提供一个标准的Plugin<S>接口供开发人员继承使用声明自己的插件机制,然后通过@EnablePluginRegistries注解依赖注入到Spring的容器中,Spring容器会为我们自动匹配到插件的所有实现子对象,最终我们在代码中使用时,通过依赖注入注解,注入PluginRegistry<T extends Plugin<S>, S>对象拿到插件实例进行操作。


 

项目中自定义swagger2Config配置文件,注入Docket对象,即一个DocumentationPlugin插件。

public class Docket implements DocumentationPlugin@Configurationpublic class Swagger2Config {  @Bean  public Docket createRestApi() {    List<Response> globalResponses = new ArrayList<>();    // 根据Enum构建了全局的Response    for (ResponseCodeEnums item : ResponseCodeEnums.values()) {      globalResponses.add(new ResponseBuilder()        .code(String.valueOf(item.getCode()))        .description(item.getDesc())        .build());    }    return  new Docket(DocumentationType.OAS_30)        .useDefaultResponseMessages(true)        .globalResponses(HttpMethod.GET, globalResponses)        .globalResponses(HttpMethod.POST, globalResponses)        .apiInfo(apiInfo())        .select()        .apis(RequestHandlerSelectors.basePackage("com.dogs.doc.controller"))        .apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))        .paths(PathSelectors.any())        .build();  }  private ApiInfo apiInfo() {    return new ApiInfoBuilder()        .title("Dogs APIs")        .description("knife4j")        .termsOfServiceUrl("")        .version("3.0")        .build();  }

 

springfox的配置文件SpringfoxWebConfiguration

EnablePluginRegistries启用插件

Defaults组件实现了一些默认的设置,如全局Response 200、401、403的返回信息。

@Configuration@Import({ ModelsConfiguration.class })@ComponentScan(basePackages = {    "springfox.documentation.spring.web.scanners",    "springfox.documentation.spring.web.readers.operation",    "springfox.documentation.spring.web.readers.parameter",    "springfox.documentation.spring.web.plugins",    "springfox.documentation.spring.web.paths"})@EnablePluginRegistries({ DocumentationPlugin.class,    ApiListingBuilderPlugin.class,    OperationBuilderPlugin.class,    ParameterBuilderPlugin.class,    ResponseBuilderPlugin.class,    ExpandedParameterBuilderPlugin.class,    OperationModelsProviderPlugin.class,    DefaultsProviderPlugin.class,    PathDecorator.class,    ApiListingScannerPlugin.class,    ModelNamesRegistryFactoryPlugin.class})public class SpringfoxWebConfiguration {  @Bean  public Defaults defaults() {    return new Defaults();  }  @Bean  public DocumentationCache resourceGroupCache() {    return new DocumentationCache();  }  @Bean  public JsonSerializer jsonSerializer(List<JacksonModuleRegistrar> moduleRegistrars) {    return new JsonSerializer(moduleRegistrars);  }  @Bean  public DescriptionResolver descriptionResolver(Environment environment) {    return new DescriptionResolver(environment);  }  @Bean  public HandlerMethodResolver methodResolver(TypeResolver resolver) {    return new HandlerMethodResolver(resolver);  }  @Bean  public PathProvider pathProvider() {    return new DefaultPathProvider();  }}

 

 

 

其他文章:Swagger2 Response统一默认返回信息

 

 

 

喜欢就关注下吧

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值