Swagger 3.0 天天刷屏,真的香吗?
持续原创输出,点击上方蓝字关注我

目录
- 前言 
- 官方文档如何说? 
- Spring Boot版本说明 
- 添加依赖 
- springfox-boot-starter做了什么? 
- 撸起袖子就是干? - 定制一个基本的文档示例 
- 文档如何分组? 
- 如何添加授权信息? 
- 如何携带公共的请求参数? 
 
- 粗略是一个BUG 
- 总结 
前言
最近频繁被Swagger 3.0刷屏,官方表示这是一个突破性的变更,有很多的亮点,我还真不太相信,今天来带大家尝尝鲜,看看这碗汤到底鲜不鲜....
官方文档如何说?
该项目开源在Github上,地址:https://github.com/springfox/springfox。
Swagger 3.0有何改动?官方文档总结如下几点:
- 删除了对 - springfox-swagger2的依赖
- 删除所有 - @EnableSwagger2...注解
- 添加了 - springfox-boot-starter依赖项
- 移除了 - guava等第三方依赖
- 文档访问地址改变了,改成了 - http://ip:port/project/swagger-ui/index.html。
姑且看到这里,各位初始感觉如何?

既然人家更新出来了,咱不能不捧场,下面就介绍下Spring Boot如何整合Swagger 3.0吧。
Spring Boot版本说明
作者使用Spring Boot的版本是2.3.5.RELEASE
添加依赖
Swagger 3.0已经有了与Spring Boot整合的启动器,只需要添加以下依赖:
  <dependency>
       <groupId>io.springfox</groupId>
       <artifactId>springfox-boot-starter</artifactId>
       <version>3.0.0</version>
  </dependency>
springfox-boot-starter做了什么?
Swagger 3.0主推的一大特色就是这个启动器,那么这个启动器做了什么呢?
「记住」:启动器的一切逻辑都在自动配置类中。
找到springfox-boot-starter的自动配置类,在/META-INF/spring.factories文件中,如下:

从上图可以知道,自动配置类就是OpenApiAutoConfiguration,源码如下:
@Configuration
@EnableConfigurationProperties(SpringfoxConfigurationProperties.class)
@ConditionalOnProperty(value = "springfox.documentation.enabled", havingValue = "true", matchIfMissing = true)
@Import({
    OpenApiDocumentationConfiguration.class,
    SpringDataRestConfiguration.class,
    BeanValidatorPluginsConfiguration.class,
    Swagger2DocumentationConfiguration.class,
    SwaggerUiWebFluxConfiguration.class,
    SwaggerUiWebMvcConfiguration.class
})
@AutoConfigureAfter({ WebMvcAutoConfiguration.class, JacksonAutoConfiguration.class,
    HttpMessageConvertersAutoConfiguration.class, RepositoryRestMvcAutoConfiguration.class })
public class OpenApiAutoConfiguration {
}
敢情这个自动配置类啥也没干,就光导入了几个配置类(@Import)以及开启了属性配置(@EnableConfigurationProperties)。

「重点」:记住
OpenApiDocumentationConfiguration这个配置类,初步看来这是个BUG,本人也不想深入,里面的代码写的实在拙劣,注释都不写。
撸起袖子就是干?
说真的,还是和以前一样,真的没什么太大的改变,按照文档的步骤一步步来。
定制一个基本的文档示例
一切的东西还是需要配置类手动配置,说真的,我以为会在全局配置文件中自己配置就行了。哎,想多了。配置类如下:
@EnableOpenApi
@Configuration
@EnableConfigurationProperties(value = {SwaggerProperties.class})
public class SwaggerConfig {
  /**
     * 配置属性
     */
    @Autowired
    private SwaggerProperties properties;
    @Bean
    public Docket frontApi() {
        return new Docket(DocumentationType.OAS_30)
                //是否开启,根据环境配置
                .enable(properties.getFront().getEnable())
                .groupName(properties.getFront().getGroupName())
                .apiInfo(frontApiInfo())
                .select()
                //指定扫描的包
                .apis(RequestHandlerSelectors.basePackage(properties.getFront().getBasePackage()))
                .paths(PathSelectors.any())
                .build();
    }
    /**
     * 前台API信息
     */
    private ApiInfo frontApiInfo() {
        return new ApiInfoBuilder()
                .title(properties.getFront().getTitle())
                .description(properties.getFront().getDescription())
                .version(properties.getFront().getVersion())
                .contact(    //添加开发者的一些信息
                        new Contact(properties.getFront().getContactName(), properties.getFront().getContactUrl(),
                                properties.getFront().getContactEmail()))
                .build();
    }
}
@EnableOpenApi这个注解文档解释如下:
Indicates that Swagger support should be enabled.
This should be applied to a Spring java config and should have an accompanying '@Configuration' annotation.
Loads all required beans defined in @see SpringSwaggerConfig
什么意思呢?大致意思就是「只有在配置类标注了@EnableOpenApi这个注解才会生成Swagger文档」。
@EnableConfigurationProperties这个注解使开启自定义的属性配置,这是作者自定义的Swagger配置。
总之还是和之前一样配置,根据官方文档要求,需要在配置类上加一个
@EnableOpenApi注解。
文档如何分组?
我们都知道,一个项目可能分为前台,后台,APP端,小程序端.....每个端的接口可能还相同,不可能全部放在一起吧,肯定是要区分开的。
因此,实际开发中文档肯定是要分组的。
分组其实很简单,Swagger向IOC中注入一个Docket即为一个组的文档,其中有个groupName()方法指定分组的名称。
因此只需要注入多个Docket指定不同的组名即可,当然,这些文档的标题、描述、扫描的路径都是可以不同定制的。
如下配置两个Docket,分为前台和后台,配置类如下:
@EnableOpenApi
@Configuration
@EnableConfigurationProperties(value = {SwaggerProperties.class})
public class SwaggerConfig {
  /**
     * 配置属性
     */
    @Autowired
    private SwaggerProperties properties;
    @Bean
    public Docket frontApi() {
        return new Docket(DocumentationType.OAS_30)
                //是否开启,根据环境配置
                .enable(properties.getFront().getEnable())
                .groupName(properties.getFront().getGroupName())
                .apiInfo(frontApiInfo())
                .select()
                //指定扫描的包
                .apis(RequestHandlerSelectors.basePackage(properties.getFront().getBasePackage()))
                .paths(PathSelectors.any())
                .build();
    }
    /**
     * 前台API信息
     */
    private ApiInfo frontApiInfo() {
        return new ApiInfoBuilder()
                .title(properties.getFront().getTitle())
                .description(properties.getFront().getDescription())
                .version(properties.getFront().getVersion())
                .contact(    //添加开发者的一些信息
                        new Contact(properties.getFront().getContactName(), properties.getFront().getContactUrl(),
                                properties.getFront().getContactEmail()))
                .build();
    }
    /**
     * 后台API
     */
    @Bean
    public Docket backApi() {
        return new Docket(DocumentationType.OAS_30)
                //是否开启,根据环境配置
                .enable(properties.getBack().getEnable())
                .groupName("后台管理")
                .apiInfo(backApiInfo())
                .select()
                .apis(RequestHandlerSelectors.basePackage(properties.getBack().getBasePackage()))
                .paths(PathSelectors.any())
                .build();
    }
    /**
     * 后台API信息
     */
    private ApiInfo backApiInfo() {
        return new ApiInfoBuilder()
                .title(properties.getBack().getTitle())
                .description(properties.getBack().getDescription())
                .version(properties.getBack().getVersion())
                .contact(    //添加开发者的一些信息
                        new Contact(properties.getBack().getContactName(), properties.getBack().getContactUrl(),
                                properties.getBack().getContactEmail()))
                .build();
    }
}
属性配置文件SwaggerProperties如下,分为前台和后台两个不同属性的配置:
/**
 * swagger的属性配置类
 */
@ConfigurationProperties(prefix = "spring.swagger")
@Data
public class SwaggerProperties {
    /**
     * 前台接口配置
     */
    private SwaggerEntity front;
    /**
     * 后台接口配置
     */
    private SwaggerEntity back;
    @Data
    public static class SwaggerEntity {
        private String groupName;
        private String basePackage;
        private String title;
        private String description;
        private String contactName;
        private String contactEmail;
        private String contactUrl;
        private String version;
        private Boolean enable;
    }
}
此时的文档截图如下,可以看到有了两个不同的分组:

如何添加授权信息?
现在项目API肯定都需要权限认证,否则不能访问,比如请求携带一个TOKEN。
在Swagger中也是可以配置认证信息,这样在每次请求将会默认携带上。
在Docket中有如下两个方法指定授权信息,分别是securitySchemes()和securityContexts()。在配置类中的配置如下,在构建Docket的时候设置进去即可:
    @Bean
    public Docket frontApi() {
        RequestParameter parameter = new RequestParameterBuilder()
                .name("platform")
                .description("请求头")
                .in(ParameterType.HEADER)
                .required(true)
                .build();
        List<RequestParameter> parameters = Collections.singletonList(parameter);
        return new Docket(DocumentationType.OAS_30)
                //是否开启,根据环境配置
                .enable(properties.getFront().getEnable())
                .groupName(properties.getFront().getGroupName())
                .apiInfo(frontApiInfo())
                .select()
                //指定扫描的包
                .apis(RequestHandlerSelectors.basePackage(properties.getFront().getBasePackage()))
                .paths(PathSelectors.any())
                .build()
                .securitySchemes(securitySchemes())
                .securityContexts(securityContexts());
    }
    /**
     * 设置授权信息
     */
    private List<SecurityScheme> securitySchemes() {
        ApiKey apiKey = new ApiKey("BASE_TOKEN", "token", In.HEADER.toValue());
        return Collections.singletonList(apiKey);
    }
    /**
     * 授权信息全局应用
     */
    private List<SecurityContext> securityContexts() {
        return Collections.singletonList(
                SecurityContext.builder()
                        .securityReferences(Collections.singletonList(new SecurityReference("BASE_TOKEN", new AuthorizationScope[]{new AuthorizationScope("global", "")})))
                        .build()
        );
    }
以上配置成功后,在Swagger文档的页面中将会有Authorize按钮,只需要将请求头添加进去即可。如下图:

如何携带公共的请求参数?
不同的架构可能发请求的时候除了携带TOKEN,还会携带不同的参数,比如请求的平台,版本等等,这些每个请求都要携带的参数称之为公共参数。
那么如何在Swagger中定义公共的参数呢?比如在请求头中携带。
在Docket中的方法globalRequestParameters()可以设置公共的请求参数,接收的参数是一个List<RequestParameter>,因此只需要构建一个RequestParameter集合即可,如下:
@Bean
public Docket frontApi() {
   //构建一个公共请求参数platform,放在在header
   RequestParameter parameter = new RequestParameterBuilder()
      //参数名称
      .name("platform")
      //描述
      .description("请求的平台")
      //放在header中
      .in(ParameterType.HEADER)
      //是否必传
      .required(true)
      .build();
      //构建一个请求参数集合
      List<RequestParameter> parameters = Collections.singletonList(parameter);
        return new Docket(DocumentationType.OAS_30)
                .....
                .build()
                .globalRequestParameters(parameters);
    }
以上配置完成,将会在每个接口中看到一个请求头,如下图:

粗略是一个BUG
作者在介绍自动配置类的时候提到了一嘴,现在来简单分析下。
OpenApiAutoConfiguration这个自动配置类中已经导入OpenApiDocumentationConfiguration这个配置类,如下一段代码:
@Import({
    OpenApiDocumentationConfiguration.class,
    ......
})
@EnableOpenApi的源码如下:
@Retention(value = java.lang.annotation.RetentionPolicy.RUNTIME)
@Target(value = {java.lang.annotation.ElementType.TYPE})
@Documented
@Import(OpenApiDocumentationConfiguration.class)
public @interface EnableOpenApi {
}
从源码可以看出:@EnableOpenApi这个注解的作用就是导入OpenApiDocumentationConfiguration这个配置类,纳尼???
既然已经在自动配置类OpenApiAutoConfiguration导入了,那么无论需不需要在配置类上标注@EnableOpenApi注解不都会开启Swagger支持吗?
「测试一下」:不在配置类上标注@EnableOpenApi这个注解,看看是否Swagger运行正常。结果在意料之中,还是能够正常运行。
「总结」:作者只是大致分析了下,这可能是个
BUG亦或是后续有其他的目的,至于结果如此,不想验证了,没什么意思。
总结
这篇文章也是尝了个鲜,个人感觉不太香,有点失望。你喜欢吗?
Spring Boot整合的源码已经上传,需要的朋友公号回复关键词「Swagger3.0」获取。点击前往
Swagger 3.0 天天刷屏,真的香吗?的更多相关文章
- Ambiguous HTTP method Actions require an explicit HttpMethod binding for Swagger 2.0
		异常内容 NotSupportedException: Ambiguous HTTP method for action . Actions require an explicit HttpMetho ... 
- netcore3.0 webapi集成Swagger 5.0,Swagger使用
		Swagger使用 1.描述 Swagger 是一个规范和完整的框架,用于生成.描述.调用和可视化 RESTful 风格的 Web 服务. 作用: 1.接口的文档在线自动生成. 2.功能测试 本文转自 ... 
- .Net Core Swagger:Actions require an explicit HttpMethod binding for Swagger 2.0
		添加完Swagger包引用后运行报错:Actions require an explicit HttpMethod binding for Swagger 2.0 第一时间想到了父类控制器 没有添加 ... 
- Swagger 2.0 集成配置
		传统的API文档编写存在以下几个痛点: 对API文档进行更新的时候,需要通知前端开发人员,导致文档更新交流不及时: API接口返回信息不明确 大公司中肯定会有专门文档服务器对接口文档进行更新. 缺乏在 ... 
- .Netcore Swagger - 解决外部库导致的“Actions require an explicit HttpMethod binding for Swagger 2.0”
		现象: 项目中导入Ocelot后,swagger页面无法正常显示,查看异常发现 Ocelot.Raft.RaftController 中的 Action 配置不完全,swagger扫描时不能正确生成 ... 
- spring boot:swagger3的安全配置(swagger 3.0.0 / spring security / spring boot 2.3.3)
		一,swagger有哪些环节需要注意安全? 1,生产环境中,要关闭swagger application.properties中配置: springfox.documentation.swagger- ... 
- spring boot:swagger3文档展示分页和分栏的列表数据(swagger 3.0.0 / spring boot 2.3.3)
		一,什么情况下需要展示分页和分栏的数据的文档? 分页时,页面上展示的是同一类型的列表的数据,如图: 分栏时,每行都是一个列表,而且展示的数据类型也可能不同 这也是两种常用的数据返回形式 说明:刘宏缔的 ... 
- spring boot:用swagger3生成接口文档,支持全局通用参数(swagger 3.0.0 / spring boot 2.3.2)
		一,什么是swagger? 1, Swagger 是一个规范和完整的文档框架, 用于生成.描述.调用和可视化 RESTful 风格的 Web 服务文档 官方网站: https://swagger.i ... 
- swagger 2.0
		1.引入jar包 <dependency> <groupId>io.springfox</groupId> <artifactId>springfox- ... 
随机推荐
- 软件定义网络实验记录④--Open vSwitch 实验——Mininet 中使用 OVS 命令
			一.实验目的 Mininet 安装之后,会连带安装 Open vSwitch,可以直接通过 Python 脚本调用 Open vSwitch 命令,从而直接控制 Open vSwitch,通过实验了解 ... 
- 下载、安装 PL/SQL Developer
			操作系统:Windows 10 x64 第一节:下载 Oracle Database XE 11gR2 第二节:安装.验证安装 Oracle Database XE 11gR2 第三节:Oracle ... 
- 【题解】CF1426E Rock, Paper, Scissors
			题目戳我 \(\text{Solution:}\) 考虑第二问,赢的局数最小,即输和平的局数最多. 考虑网络流,\(1,2,3\)表示\(Alice\)选择的三种可能性,\(4,5,6\)同理. 它们 ... 
- CSS中居中的完全指南(中英对照翻译)
			翻译自:https://css-tricks.com/centering-css-complete-guide/ Centering things in CSS is the poster child ... 
- 【数量技术宅|金融数据分析系列分享】为什么中证500(IC)是最适合长期做多的指数
			更多精彩内容,欢迎关注公众号:数量技术宅.探讨数据分析.量化投资问题,请加技术宅微信:sljsz01 投资股票指数相比个股的优势 我们在投资股票的时候,如果持仓集中在一只或者有限几只股票上,恰好不幸遇 ... 
- 4-K8S 部署Java应用及应用程序生命周期管理
			1.在kubernetes中部署应用程序流程 准备项目源码-->编译构建-->产出war包,打包到镜像中-->推送到镜像仓库 获取源代码是开发人员提交代码的代码托管地址,有Git.S ... 
- JVM系列【2】Class文件结构
			JVM系列笔记目录 虚拟机的基础概念 class文件结构 class文件加载过程 jvm内存模型 JVM常用指令 GC与调优 如何查看class字节码文件 在idea中可以通过插件BinEd来查看二进 ... 
- lftp源码安装时 error: Package requirements (gnutls >= 1.0.0) were not met:  No package 'gnutls' found
			lftp 使用疑惑与解决方法: 一,从官网下载源码后,解压./configure后,报错: error: Package requirements (gnutls >= 1.0.0) were ... 
- Linux系统编程 —线程同步概念
			同步概念 同步,指对在一个系统中所发生的事件之间进行协调,在时间上出现一致性与统一化的现象. 但是,对于不同行业,对于同步的理解略有不同.比如:设备同步,是指在两个设备之间规定一个共同的时间参考:数据 ... 
- pytest学习纪要123-针对经常用到的内容详实记录
			pytest123 本文主要参考:https://www.cnblogs.com/yoyoketang/tag/pytest 如有侵权,请站内联系我 目录 pytest123 1.setup和tear ... 
