写点什么

Springfox swagger2 API 文档

作者:Rubble
  • 2022 年 4 月 08 日
  • 本文字数:4797 字

    阅读完需:约 16 分钟

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


pom 依赖


<dependency>  <groupId>com.github.xiaoymin</groupId>  <artifactId>knife4j-spring-boot-starter</artifactId>  <version>3.0.2</version></dependency>
复制代码


找 starter 的启动配置文件 spring.factories 文件找到启动类,做了一些 bean 的配置。


# Auto Configureorg.springframework.boot.autoconfigure.EnableAutoConfiguration=\com.github.xiaoymin.knife4j.spring.configuration.Knife4jAutoConfiguration
复制代码


根据路径/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; }
复制代码


例如 OperationBuilderPluginPluginRegistry<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) {}}




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




项目中自定义 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(); }}
复制代码


总结:swagger 基于 PluginRegistry 的方式注册插件。 默认提供了配置类 ApiInfo,用户可以自定义配置类,可配置的内容可以参考 ApiInfo 的属性。

用户头像

Rubble

关注

还未添加个人签名 2021.06.01 加入

还未添加个人简介

评论

发布
暂无评论
Springfox swagger2 API文档_4月日更_Rubble_InfoQ写作平台