赞
踩
Swagger3.0出来一段时间了,虽然简化了基础的配置,但作为一个大版本的升级肯定存在不少问题,不少2.x版本的类都被标记为过时了,大部分类的构造与属性设置依旧都交给了对应的Buidler处理,但不少配置上都引入了函数式接口去处理,对于对函数式编程不太了解的开发者而言可能有一定的配置难度。目前国内较少对3.0版本的配置介绍,所以自己在项目里将Swagger升级到3.0后看了下替代了标记过时(@Deprecated
)相应功能的源码进行相应的配置,结果踩了2个坑,所以分享下踩坑记录与3.0的通用配置方式。
项目中使用了jwt鉴权,但无论对于开发人员还是测试人员来说每次Swagger测接口前都要登录获取token,每次传token都是一件很麻烦的事,所以我便打算按Swagger比较常用的全局参数设置将Authorization
设为全局header并设置默认值,于是有了以下3.0(OAS_30指Open API Spefication 3.0
)中的配置:
@Bean public Docket docket() { return new Docket(DocumentationType.OAS_30) .globalRequestParameters(Lists.newArrayList( new RequestParameterBuilder() .name("debug") .description("ignore authorization") .in(ParameterType.HEADER) // 类内部创建了默认的builder以供属性设置 .query(parameterSpecificationBuilder -> parameterSpecificationBuilder.defaultValue("1") .allowEmptyValue(true)) .build(), new RequestParameterBuilder() .name("Authorization") .description("token") .query(parameterSpecificationBuilder -> parameterSpecificationBuilder.defaultValue("1") .allowEmptyValue(true)) .in(ParameterType.HEADER) .build() )) .select() .paths(PathSelectors.regex("^(?!/error).*")) .build(); }
以上配置中的query()
可以看成是Swagger3.0中配置风格的一个核心:在配置类中创建好相应的属性对象builder,并暴露一个该builder的Conumser函数式接口作为参数的方法,开发者根据需要提供一个Consumer进行对该builder的操作(属性设置),只要了解了该风格相信基本上新版本的配置看看源码也能很快上手。
以上配置代码query()
方法中我取了RequestParameterBuilder
类中的属性对象simpleParameterBuilder
引用进行了属性设置,RequestParameterBuilder
部分源码:
public class RequestParameterBuilder { ...... SimpleParameterSpecificationBuilder simpleParameterBuilder; ...... private SimpleParameterSpecificationBuilder queryBuilder() { if (simpleParameterBuilder == null) { simpleParameterBuilder = new SimpleParameterSpecificationBuilder(); } return simpleParameterBuilder; } public RequestParameterBuilder query(@NonNull Consumer<SimpleParameterSpecificationBuilder> parameter) { parameter.accept(queryBuilder()); return this; } ......
其实个人认为既然集成SpringBoot了以properties类为主导进行属性设置而非Builder与FunctionalInterface对开发者使用而言会更便利,现在先踩坑填坑。按照对2.x的版本配置与了解个人以为以上的配置应该是没有问题的,然而居然出现了2个坑。
Authorization
的全局header参数值将无法传到后端当我添加一个Authorization
的全局header的时候测试时发现怎么传都没有传到后端,一开始以为是Swagger的bug,但考虑到这个name的敏感性,我就去翻了下OpenAPI 3.0(Swagger 3.0是按照OpenAPI 3.0的规范去设计实现的,文档的数据格式也是遵循3.0规范),于是翻出了以下内容:
当全局header参数中包含命名为Accpet
、Content-Type
、Authorization
的参数时,参数的定义将被忽略。于是我加了一个非忽略header,得到了以下结果:
可以看到全局header设置中debug
是能接收到的,而Authorization
是被忽略的,即基本确认非bug,只是我没有看规范而已。既然以该方式定义的Authorization
header无法被接收,但Swagger以往的版本还有一种设置全局token的方式-SecurityContext
与SecurityReference
:
@Bean
public Docket docket() {
return new Docket(DocumentationType.OAS_30)
.securityContexts(Arrays.asList(SecurityContext.builder()
.securityReferences(Arrays.asList(SecurityReference.builder()
.reference("Authorization")
.scopes(new AuthorizationScope[]{new AuthorizationScope("global", "accessEverything")})
.build()))
.build()))
.securitySchemes(Arrays.asList(new ApiKey("Authorization", "Authorization", "header")))
.select()
.paths(PathSelectors.regex("^(?!/error).*"))
.build();
}
SecurityContext
与SecurityReference
的设置与以往版本变化不大,结果也达到了个人的期望(后端能获取到Authorization
header),只是该方式配置的header无法设置默认值而已,效果图如下:
虽然通过query()
方法设置了参数默认值,但实质上Swagger并没有把该默认值设置到页面上,从坑1中的演示图1可以看到全局参数即使设置了初始值1
,但页面上还是空的。该坑确认了是3.0的bug,在github里也找到了相应的issue,该bug已加到了3.0.1的里程碑中(即3.0.1版本会修复):
虽然官方框架的使用更具有普遍性,但目前还是觉得自己写的香,如果以上3.0版本出现的问题会影响当前项目的测试使用则不建议先升级,玩玩尚可。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。