文档
- 快速开始
- Knife4j 4.0 迭代计划
- 如何贡献代码
- 序章
- 社区
- 增强特性
- 3.1 增强模式
- 3.2 i18n 国际化
- 3.3 接口添加作者
- 3.4 自定义文档
- 3.5 访问权限控制
- 3.6 接口排序
- 3.7 分组排序
- 3.8 请求参数缓存
- 3.9 动态请求参数
- 3.10 导出离线文档
- 3.11 过滤请求参数
- 3.12 包含请求参数
- 3.13 搜索API接口
- 3.14 清除缓存
- 3.15 动态请求参数添加文档注释
- 3.16 动态响应参数添加文档注释
- 3.17 自定义Host
- 3.18 afterScript
- 3.19 OAuth2
- 3.20 导出 Postman
- 3.21 全局参数
- 3.22 自定义 Swagger Models 名称
- 3.23 自定义主页内容
- 3.24 自定义 Footer
- 3.25 JSR303
- 3.26 禁用调试
- 3.27 禁用搜索框
- 3.28 禁用 OpenApi 结构显示
- 3.29 版本控制
- 生态中间件
- 升级
中间件
- 中间件介绍
- Aggregation 微服务聚合中间件
- Desktop 独立渲染组件
OAS 简介
- OAS 简介
- OpenAPI 规范
- Java 注解
实战指南
- 示例代码
- Spring 单体架构
- Spring 微服务架构
- OAuth 2.0
- 微服务聚合实战
- ASP.NET Core
- Springfox 源码系列
- Springfox 源码系列
- springfox 源码分析(一) 程序入口
- springfox 源码分析(二) 初探 mapstruct
- springfox 源码分析(三) 初探 Spring Plugin 插件系统
- springfox 源码分析(四) 配置类初始化
- springfox 源码分析(五) Web 配置类 Plugin 插件的使用
- springfox 源码分析(六) Web 配置类扫描包作用探索
- springfox 源码分析(七) 文档初始化
- springfox 源码分析(八) 遍历接口获取 Model 对象
- springfox 源码分析(九) 文档初始化分组
- springfox 源码分析(十) 遍历接口获取 Model 对象
- springfox 源码分析(十一) 自定义添加 Swagger Models 功能实现
- springfox 源码分析(十二) 遍历接口获取 ApiDescription 集合
- springfox 源码分析(十三) 自定义扩展实现接口的排序
- springfox 源码分析(十四) 归档得到 ApiListing 接口集合
- springfox 源码分析(十五) 归档得到 Documentation 文档对象
- springfox 源码分析(十六) 分组接口 swagger-resouces
- springfox 源码分析(十七) Swagger2 接口文档示例接口 api-docs
- springfox 源码分析(十八) 自定义扩展实现分组的排序
- springfox 源码分析(十九) guava 库学习
- springfox 源码分析(二十一) 忽略参数 Class 类型
springfox 源码分析(五) Web 配置类 Plugin 插件的使用
时间:2019-5-23 14:46:50
地点:家中
前言
我们在上一篇文章,通过 @EnableSwagger2
注解,知道springfox使用开启Plugin注解的配置,注入了很多Plugin的配置类,结合我们第二篇针对Spring Plugin的使用文章介绍,该篇主要探索springfox中的各种不同Plugin的具体作用,以及声明了那些方法
插件
在 SpringfoxWebMvcConfiguration
配置中,主要涉及了以下Plugin
- DocumentationPlugin
- ApiListingBuilderPlugin
- OperationBuilderPlugin
- ParameterBuilderPlugin
- ExpandedParameterBuilderPlugin
- OperationModelsProviderPlugin
- DefaultsProviderPlugin
- PathDecorator
- ApiListingScannerPlugin
代码结构一览:
plugin中声明的接口,都是为处理contexts上下文中的属性
DocumentationPlugin
先来看 DocumentationPlugin
的源码
public interface DocumentationPlugin extends Plugin<DocumentationType> {
/**
* @return indicator to determine if the plugin is enabled
*/
boolean isEnabled();
DocumentationType getDocumentationType();
/**
* Creates a documentation context based on a given DocumentationContextBuilder
*
* @param builder - @see springfox.documentation.spi.service.contexts.DocumentationContextBuilder
* @return context to use for building the documentation
*/
DocumentationContext configure(DocumentationContextBuilder builder);
/**
* Gets the group name for the plugin. This is expected to be unique for each instance of the plugin
* @return group the plugin belongs to
*/
String getGroupName();
}
此Plugin使用的分隔符类是 DocumentationType
,文档类型,在Springfox中声明了三个版本的文档类型,主要是:
- SWAGGER_2:swagger的2.0版本
- SWAGGER_12:Swagger的1.2版本
- SPRING_WEB:springfox项目是由原spring-mvc-swagger项目演变而来,所以这是最早的一个版本
DocumentationPlugin
定义了三个方法:
- 是否启用
- 获取文档类型
- 通过文档上下文Builder构建文档上下文对象
- 获取分组名称
那么,他的实现类是谁,我们通过IDEA的编辑器功能能轻松定位到,是Docket类
来看类图:
由于Docket对象是最终实现类,而我们开发者一般在使用时,都是通过创建Docket的实体对象来注入到Spring的容器中
所以,我们创建几个Docket对象的Bean实例,那么通过 PluginRetry<DocumentationPlugin,DocumentationType>
的getPlugins()方法,最终就会获取到外部注入的Docket对象实例,然后再程序中就可以使用了
ApiListingBuilderPlugin
来看 ApiListingBuilderPlugin
的源码
public interface ApiListingBuilderPlugin extends Plugin<DocumentationType> {
/**
* Implement this method to override the ApiListing using the ApiListingBuilder
*
* @param apiListingContext - context that can be used to override the model property attributes
* @see springfox.documentation.service.ApiListing
* @see springfox.documentation.builders.ApiListingBuilder
*/
void apply(ApiListingContext apiListingContext);
}
实现 ApiListingBuilderPlugin
插件类需要实现apply方法,主要是处理ApiListingContext上下文的属性信息
来看类图:
从 ApiListingBuilderPlugin
类图中,我们可以看到,他有三个子类,分别是:
- MediaTypeReader:获取接口的
RequestMapping
注解,赋值Produces和Consumes属性 - ApiListingReader:针对controller名称的处理操作,最后赋值给ApiListingBuilder对象description属性
- SwaggerApiListingReader:获取@Api注解,赋值tag及description属性
这三个实现类都通过 @Component
注解注入到了Spring的容器中
OperationBuilderPlugin
springfox中的一些列插件Plugin最终的作用都是分别为定义传参的Context上下文进行一系列的赋值处理
每个上下文中几乎都会存在该对象的Builder,最终通过各种不同的Plugin来分别进行赋值,这样整个程序架构会清晰很多
Operation
也不例外,先来看Operation的上下文类
OperationContext.java
public class OperationContext {
//builder函数
private final OperationBuilder operationBuilder;
//Spring中接口的请求方法类型枚举
private final RequestMethod requestMethod;
//请求接口上下文
private final RequestMappingContext requestContext;
private final int operationIndex;
//getter setter and constructor
}
此时,我们来看 OperationBuilderPlugin
插件的源码:
public interface OperationBuilderPlugin extends Plugin<DocumentationType> {
/**
* Implement this method to override the Operation using the OperationBuilder available in the context
*
* @param context - context that can be used to override the parameter attributes
* @see springfox.documentation.service.Operation
* @see springfox.documentation.builders.OperationBuilder
*/
void apply(OperationContext context);
}
顶级Plugin声明接口,分层逐步给OperationContext对象赋值
先来看部分类图:
由于 OperationBuilderPlugin
实现类比较多,此处类图进列出其中四个实现类,我们通过文字来一一说明
DefaultOperationReader
:请求方法、接口说明、唯一id值MediaTypeReader
:consumes、producesOperationAuthReader
:权限赋值OperationDeprecatedReader
;接口是否过时OperationHiddenReader
:是否隐藏OperationHttpMethodReader
:接口请求方法OperationImplicitParameterReader
:针对@ApiImplicitParam
注解的接口进行读取赋值OperationImplicitParametersReader
:针对@ApiImplicitParams
注解的接口进行读取赋值OperationNicknameIntoUniqueIdReader
:昵称属性,通过读取@ApiOperation
注解中的nickname
属性进行赋值OperationNotesReader
:接口说明OperationParameterHeadersConditionReader
:请求头OperationParameterReader
:后端配置的全局parameter以及接口的parameter参数进行读取赋值OperationParameterRequestConditionReader
:参数条件OperationPositionReader
:position属性OperationResponseClassReader
:响应类处理OperationSummaryReader
:接口名称OperationTagsReader
:tagsResponseMessagesReader
:响应状态码信息,先读取后端配置的全局,然后读取接口SwaggerMediaTypeReader
:consumes、producesSwaggerOperationResponseClassReader
:响应class类SwaggerOperationTagsReader
:接口的tags处理SwaggerResponseMessageReader
:状态码信息,针对@ApiResponse
注解标注的接口VendorExtensionsReader
:扩展
整个代码结构一览:
ParameterBuilderPlugin
针对参数处理的Plugin,先来看相关类图:
总共有七个实现类,我们一一说明:
ApiParamParameterBuilder
:针对接口使用@ApiParam
注解的参数进行处理ParameterDataTypeReader
:参数的数据类型ParameterDefaultReader
:参数默认值ParameterMultiplesReader
:ParameterNameReader
:参数名称ParameterRequiredReader
:参数是否必须ParameterTypeReader
:参数类型,包括(form、header、query、formdata、body),默认是body
ExpandedParameterBuilderPlugin
先来看类图关系
从类图关系中,实现类主要有两个:
ExpandedParameterBuilder
:实体类参数的默认属性赋值SwaggerExpandedParameterBuilder
:针对我们的类使用@ApiModelProperty
注解的操作
OperationModelsProviderPlugin
来看类图关系
OperationModelsProvider
:收集所有的参数Models,返回类型,全局ModelsSwaggerOperationModelsProvider
:接口返回类型已经使用@ApiResponse
标注的返回类型
DefaultsProviderPlugin
来看 DefaultsProviderPlugin
的源码
public interface DefaultsProviderPlugin extends Plugin<DocumentationType> {
/**
* Implement this method to override the @see springfox.documentation.spi.service.contexts
* .DocumentationContextBuilder
*
* @param documentationType - creates a default DocumentationContextBuilder based on documentation type
* @return - returns the documentation context builder
*/
DocumentationContextBuilder create(DocumentationType documentationType);
}
根据文档类型创建 DocumentationContextBuilder
对象
而 DefaultsProviderPlugin
只有一个实现子类,那就是 springfox.documentation.spring.web.plugins.DefaultConfiguration
public class DefaultConfiguration implements DefaultsProviderPlugin {
private final Defaults defaults;
private final TypeResolver typeResolver;
private final ServletContext servletContext;
public DefaultConfiguration(Defaults defaults,
TypeResolver typeResolver,
ServletContext servletContext) {
this.servletContext = servletContext;
this.defaults = defaults;
this.typeResolver = typeResolver;
}
@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);
}
@Override
public boolean supports(DocumentationType delimiter) {
return true;
}
}
给DocumentationContextBuilder创建一系列空对象默认值,方便后期其他Plugin进行赋值初始化
Defaults
和 TypeResolver
在前面的Configuration配置类中已经通过Bean注解进行了注入
PathDecorator
先来看类图:
PathDecorator
声明了一个Guava函数库中的Function函数接口
Function
@GwtCompatible
public interface Function<F, T> {
@Nullable
@CanIgnoreReturnValue // TODO(kevinb): remove this
T apply(@Nullable F input);
/**
* <i>May</i> return {@code true} if {@object} is a {@code Function} that behaves identically to
* this function.
*
* <p><b>Warning: do not depend</b> on the behavior of this method.
*
* <p>Historically, {@code Function} instances in this library have implemented this method to
* recognize certain cases where distinct {@code Function} instances would in fact behave
* identically. However, as code migrates to {@code java.util.function}, that behavior will
* disappear. It is best not to depend on it.
*/
@Override
boolean equals(@Nullable Object object);
}
传入输入参数,返回输出参数
主要实现类:
OperationPathDecorator
:basePath处理类PathMappingDecorator
:接口path处理PathSanitizer
:接口path-origin处理QueryStringUriTemplateDecorator
:接口参数处理
ApiListingScannerPlugin
来看源码
public interface ApiListingScannerPlugin extends Plugin<DocumentationType> {
/**
* Implement this method to manually add ApiDescriptions
*
* @param context - Documentation context that can be used infer documentation context
* @see springfox.documentation.service.ApiDescription
* @return List of {@link ApiDescription}
*/
List<ApiDescription> apply(DocumentationContext context);
}
该Plugin没有任何实现子类
总结
通过上面的Plugin,我们大致了解了Springfox中定义的Plugin接口,以及实现类,完事具备,此时只需要查看springfox的初始化代码部分了
在下一篇文章中我们继续.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论