Springfox swagger2 源碼解析

      網(wǎng)友投稿 1062 2025-03-31

      Springfox swagger2 源碼解析

      doc訪問頁面 http://localhost:8080/doc.html

      api-json訪問頁面 http://localhost:8080/v2/api-docs

      pom依賴

      com.github.xiaoymin knife4j-spring-boot-starter 3.0.2

      找starter的啟動配置文件spring.factories文件找到啟動類,做了一些bean的配置。

      # Auto Configure org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ com.github.xiaoymin.knife4j.spring.configuration.Knife4jAutoConfiguration

      根據(jù)路徑/v2/api-docs順藤摸瓜 找到 Swagger2ControllerWebMvc

      @RequestMapping( method = RequestMethod.GET, produces = {APPLICATION_JSON_VALUE, HAL_MEDIA_TYPE}) public ResponseEntity 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 context = new SwaggerTransformationContext<>(swagger, servletRequest); List 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進行加載,類實現(xiàn)了SmartLifecycle接口,當spring加載完bean后,調(diào)用start()方法進行加載。

      public class DocumentationPluginsbootstrapper extends AbstractDocumentationPluginsBootstrapper implements SmartLifecycle{ public DocumentationPluginsBootstrapper( DocumentationPluginsManager documentationPluginsManager, List 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 加載完成后調(diào)用 public void start() { if (initialized.compareAndSet(false, true)) { LOGGER.debug("Documentation plugins bootstrapped"); super.bootstrapDocumentationPlugins(); } } }

      Spring SmartLifecycle 在容器所有bean加載和初始化完畢執(zhí)行

      在使用Spring開發(fā)時,我們都知道,所有bean都交給Spring容器來統(tǒng)一管理,其中包括每一個bean的加載和初始化。

      有時候我們需要在Spring加載和初始化所有bean后,接著執(zhí)行一些任務(wù)或者啟動需要的異步服務(wù),這樣我們可以使用 SmartLifecycle 來做到。

      這個和 @PostConstruct、@PreDestroy 的bean的初始化和銷毀方法不同,Bean生命周期級別和容器生命周期級別在應(yīng)用場景上是有區(qū)別的。

      SmartLifecycle 是一個接口。當Spring容器加載所有bean并完成初始化之后,會接著回調(diào)實現(xiàn)該接口的類中對應(yīng)的方法(start()方法)。

      文檔插件管理器 DocumentationPluginsManager

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

      documentationPlugins()方法調(diào)用了DocumentationPlugin 文檔插件,若沒有則生成一個默認的插件Docket,通常在Swagger2Configuration配置文件會注入一個Docket。

      @Component public class DocumentationPluginsManager { @Autowired @Qualifier("documentationPluginRegistry") private PluginRegistry documentationPlugins; @Autowired @Qualifier("apiListingBuilderPluginRegistry") private PluginRegistry apiListingPlugins; @Autowired @Qualifier("parameterBuilderPluginRegistry") private PluginRegistry parameterPlugins; @Autowired @Qualifier("expandedParameterBuilderPluginRegistry") private PluginRegistry parameterExpanderPlugins; @Autowired @Qualifier("operationBuilderPluginRegistry") private PluginRegistry operationBuilderPlugins; @Autowired @Qualifier("operationModelsProviderPluginRegistry") private PluginRegistry operationModelsProviders; @Autowired @Qualifier("defaultsProviderPluginRegistry") private PluginRegistry defaultsProviders; @Autowired @Qualifier("pathDecoratorRegistry") private PluginRegistry pathDecorators; @Autowired @Qualifier("apiListingScannerPluginRegistry") private PluginRegistry apiListingScanners; @Autowired @Qualifier("responseBuilderPluginRegistry") private PluginRegistry responsePlugins; @Autowired @Qualifier("modelNamesRegistryFactoryPluginRegistry") private PluginRegistry modelNameRegistryFactoryPlugins; public Collection documentationPlugins() throws IllegalStateException { List plugins = documentationPlugins.getPlugins(); ensureNoDuplicateGroups(plugins); if (plugins.isEmpty()) { return singleton(defaultDocumentationPlugin()); } return plugins; }

      例如 OperationBuilderPlugin

      PluginRegistry operationBuilderPlugins

      Control + H 查看其繼承結(jié)構(gòu)

      栗子:

      SwaggerResponseMessageReader實現(xiàn)了ResponseMessage的讀取。read()方法從OperationContext上下文中獲取ApiOperation、ResponseHeader、ApiResponse注解信息。

      public class SwaggerResponseMessageReader implements OperationBuilderPlugin {

      protected Compatibility, Set> read(OperationContext context) {}

      }

      PluginRegistry

      Spring Plugin提供一個標準的Plugin接口供開發(fā)人員繼承使用聲明自己的插件機制,然后通過@EnablePluginRegistries注解依賴注入到Spring的容器中,Spring容器會為我們自動匹配到插件的所有實現(xiàn)子對象,最終我們在代碼中使用時,通過依賴注入注解,注入PluginRegistry extends Plugin對象拿到插件實例進行操作。

      項目中自定義swagger2Config配置文件,注入Docket對象,即一個DocumentationPlugin插件。

      public class Docket implements DocumentationPlugin

      Springfox swagger2 源碼解析

      @Configuration public class Swagger2Config { @Bean public Docket createRestApi() { List globalResponses = new ArrayList<>(); // 根據(jù)Enum構(gòu)建了全局的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組件實現(xiàn)了一些默認的設(shè)置,如全局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 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(); } }

      總結(jié):

      swagger基于PluginRegistry的方式注冊插件。 默認提供了配置類ApiInfo,用戶可以自定義配置類,可配置的內(nèi)容可以參考ApiInfo的屬性。

      Spring 容器

      版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔相應(yīng)法律責任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實的內(nèi)容,請聯(lián)系我們jiasou666@gmail.com 處理,核實后本網(wǎng)站將在24小時內(nèi)刪除侵權(quán)內(nèi)容。

      版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔相應(yīng)法律責任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實的內(nèi)容,請聯(lián)系我們jiasou666@gmail.com 處理,核實后本網(wǎng)站將在24小時內(nèi)刪除侵權(quán)內(nèi)容。

      上一篇:項目任務(wù)分解與進度安排(項目任務(wù)分解與進度安排方案)
      下一篇:excel的int函數(shù)是什么意思(在excel中int什么意思)
      相關(guān)文章
      亚洲成A人片在线观看无码3D| 亚洲精品国产日韩| 亚洲日韩亚洲另类激情文学| 亚洲蜜芽在线精品一区| 亚洲AV本道一区二区三区四区| 人人狠狠综合久久亚洲婷婷| 国产亚洲精品岁国产微拍精品| 亚洲色成人网站WWW永久| 亚洲欧洲日产国码无码网站| 国产成人A亚洲精V品无码 | 精品国产人成亚洲区| 亚洲视频人成在线播放| 亚洲精品无码日韩国产不卡?V| 国产亚洲Av综合人人澡精品| mm1313亚洲国产精品美女| 无码天堂va亚洲va在线va| 国产亚洲精品仙踪林在线播放| 五月天婷亚洲天综合网精品偷| 亚洲成a人片在线观看久| 亚洲毛片av日韩av无码| 国产亚洲欧洲Aⅴ综合一区| 自拍偷自拍亚洲精品被多人伦好爽| 久久亚洲欧洲国产综合| 亚洲精品无码永久在线观看你懂的| 亚洲第一AAAAA片| 亚洲午夜视频在线观看| 中文字幕亚洲第一在线| 亚洲成av人片在线看片| 91丁香亚洲综合社区| 亚洲精品久久久久无码AV片软件| 亚洲av成人一区二区三区观看在线| 国产AV无码专区亚洲AV琪琪| 亚洲午夜精品一级在线播放放| 亚洲色成人中文字幕网站 | 亚洲另类自拍丝袜第五页| 久久精品国产亚洲AV| 亚洲精品无码久久不卡| 国产亚洲一区二区手机在线观看| 西西人体44rt高清亚洲 | 亚洲精品成人网久久久久久| 日韩亚洲变态另类中文|