大家好,我是小富~
说个挺奇葩的事,有个老铁给我发私信吐槽了一下它的面试经历,他去了个国企单位面试,然后面试官跟他就Swagger的问题聊了半个多小时。额~ 面试嘛这些都不稀奇,总能遇到是千奇百怪的人,千奇百怪的问题。不过,我分析这个面试官是不太好意思直接让他走,哈哈哈!
Swagger目前是比较主流的RESTful
风格的API文档工具,做过开发的人应该都用过它吧!
它提供了一套工具和规范,让开发人员能够更轻松地创建和维护可读性强、易于使用和交互的API文档(官方口吻)。
以往在没有这样的API文档工具,开发人员需要手动编写和维护功能API的文档。而且,由于API变更往往难以及时更新到文档中,这可能会给依赖文档的开发者带来困惑。
说几个Swagger
的特点:
能生成的绝对不手写
,而且API文档与API定义会同步更新。Java
、PHP
、Python
等语言都支持,喜欢什么语言构建API都行。总的来说,Swagger可以让我们更多时间在专注于编写代码(摸鱼),而不是花费额外精力来维护文档,实践出真知先跑个demo试试。
目前使用的版本是Swagger3.0、Springboot 2.7.6,Swagger2.0与3.0依赖包名称的变化有些大,需要特别注意一下。
首先我们创建一个控制器TestController
类,里边只有一个最简单的请求 /test
。
接下来创建配置类SwaggerConfig
,类标注@EnableSwagger2
注解是关键,到这最简单的Swagger文档环境就搭建好了。
启动时可能会报如下的错误,这是由于高版本的Springboot
与Swagger
版本使用的路径匹配策略冲突导致的。
Springfox
使用的路径匹配规则为AntPathMatcher
的,而SpringBoot2.7.6
使用的是PathPatternMatcher
,两者冲突了。
这个错误的解决办法比较多,我整理了四种解决此问题的方案,你看哪个更合适你。
SpringBoot版本降低到2.5.X 、springfox降到3.X 以下可以解决问题,不过不推荐这么做,毕竟降配置做兼容显得有点傻。
将SpringMVC
的匹配URL路径的策略改为ant_path_matcher
,application.yml
文件增加如下的配置:
在配置类SwaggerConfig
上标注@EnableWebMvc
注解也可以解决。
Swagger
框架需要通过解析和扫描带有注解的Controller
类和方法来生成API文档。@EnableWebMvc
注解会注册一个RequestMappingHandlerMapping
的Bean,并将其作为默认的请求映射处理器,以确保这些Controller类和方法能够被正确处理,可以与Swagger的路径配置规则相匹配,从而使得Swagger能够成功生成API文档。
也可以自行实现兼容逻辑来解决这个问题,我们可以在Spring
容器中注册一个BeanPostProcessor
,在该处理器中对 HandlerMappings 进行定制。
通过过滤掉已存在PatternParser的映射,意味着我们可以将Swagger特定的HandlerMappings添加到HandlerMappings
列表中,从而使用自定义的设置来替代原有的HandlerMappings。
这样修复了可能导致Swagger无法正常使用的问题。
到这,问题解决!我们访问Swagger文档路径 http://127.0.0.1:9002/swagger-ui/index.html
,能够看到我们写的 API 信息以及一些Swagger 文档的默认配置信息。
注意到我们只写了一个 /test
接口,但这里确把这个方法的所有请求方式都列了出来,因为我们在 controller
方法中使用了@RequestMapping
注解,并没有具体的指定接口的请求方式,所以避免文档冗余,尽量指定请求方式或者使用指定请求方式的 @XXXMapping
注解。
指定请求方式后:
上边我们访问的文档中展示的数据都是默认的配置,现在咱们来定制化一下文档。
Springfox
提供了一个Docket
对象,供我们灵活的配置Swagger
的各项属性。Docket
对象内提供了很多的方法来配置文档,下边介绍下常用的配置项。
select()
返回一个ApiSelectorBuilder
对象,是使用apis()
、paths()
两个方法的前提,用于指定Swagger要扫描的接口和路径。
默认情况下,Swagger会扫描整个项目中的接口,通过 apis()
方法,你可以传入一个RequestHandlerSelector
对象实例来指定要包含的接口所在的包路径。
仅将某些特定请求路径的API
展示在Swagger文档中,例如路径中包含/test
。可以使用 apis()
和 paths()
方法一起来过滤接口。
为生成的Swagger
文档指定分组的名称,用来区分不同的文档组。
实现文档的多个分组,则需创建多个 Docket
实例,设置不同的组名,和组内过滤 API 的条件。
设置API文档的基本信息,例如标题、描述、版本等。你可以使用ApiInfo
对象自定义信息。
对应的Swagger文档页面上展示的位置
启用或禁用Swagger文档的生成,有时测试环境会开放API文档,但在生产环境则要禁用,可以根据环境变量控制是否显示。
API文档显示的主机名称或IP地址,即在测试执行接口时使用的IP或域名。
配置API安全认证方式,比如常见的在header
中设置如Bearer
、Authorization
、Basic
等鉴权字段,ApiKey
对象中字段含义分别是别名、鉴权字段key、鉴权字段添加的位置。
这样配置后,Swagger文档将会包含一个Authorize
按钮,供用户输入我们设定的Bearer
、Authorization
、Basic
进行身份验证。
securitySchemes
方法中虽然设置了鉴权字段,但此时在测试接口的时候不会自动在 header
中加上鉴权字段和值,还要配置API的安全上下文,指定哪些接口需要进行安全认证。
现在在测试调用API接口时,header
中可以正常加上鉴权字段和值了。
为API文档中的接口添加标签,标签可以用来对API进行分类或分组,并提供更好的组织和导航功能。
出于对系统安全性的考虑,通常我们还会为API文档增加登录功能。
swagger的安全登录是基于security
实现的,引入相关的maven
依赖。
application.yml
文件中配置登录swagger的用户名和密码。
再次访问文档就会出现如下的登录页
当我们希望在Swagger文档中提供详细和完整的内容时,还可以使用其他许多Swagger内置注解来进一步丰富和定制API文档。
上边我们提到可以根据指定路径或者包路径来提供API,也可以使用粒度更细的@ApiIgnore
注解,来实现某个API在文档中忽略。
在我们的接口中,只要使用实体作为参数或响应体,Swagger就会自动扫描到它们,但你会发现目前这些实体缺乏详细的描述信息。为了让使用者通俗易懂,需要使用swagger提供的注解为这些实体添加详细的描述。
@ApiModel
注解的使用在实体类上,提供对Swagger Model额外信息的描述。
@ApiModelProperty
注解为实体类中的属性添加描述,提供了字段名称、是否必填、字段示例等描述信息。
@Api
注解用于标记一个控制器(controller
)类,并提供接口的详细信息和配置项。
value
:API 接口的描述信息,由于版本swagger版本原因,value
可能会不生效可以使用description
hidden
:该 API 是否在 Swagger 文档中隐藏tags
:API 的标签,如果此处与 new Docket().tags
中设置的标签一致,则会将该 API 放入到这个标签组内authorizations
:鉴权配置,配合 @AuthorizationScope
注解控制权限范围或者特定密钥才能访问该API。produces
:API的响应内容类型,例如 application/json。consumes
:API的请求内容类型,例如 application/json。protocols
:API支持的通信协议。@ApiOperation
该注解作用在接口方法上,用来对一个操作或HTTP方法进行描述。
value
:对接口方法的简单说明notes
:对操作的详细说明。httpMethod
:请求方式code
:状态码,默认为 200。可以传入符合标准的HTTP Status Code Definitions。hidden
:在文档中隐藏该接口response
:返回的对象tags
:使用该注解后,该接口方法会单独进行分组produces
:API的响应内容类型,例如 application/json。consumes
:API的请求内容类型,例如 application/json。protocols
:API支持的通信协议。authorizations
:鉴权配置,配合 @AuthorizationScope
注解控制权限范围或者特定密钥才能访问该API。responseHeaders
:响应的header内容@ApiImplicitParams
注解用在方法上,以数组方式存储,配合@ApiImplicitParam
注解使用。
@ApiImplicitParam
注解对API方法中的单一参数进行注解。
注意这个注解
@ApiImplicitParam
必须被包含在注解@ApiImplicitParams
之内。
name
:参数名称value
:参数的简短描述required
:是否为必传参数dataType
:参数类型,可以为类名,也可以为基本类型(String,int、boolean等)paramType
:参数的传入(请求)类型,可选的值有 path、query、body、header、form。@ApiParam()
也是对API方法中的单一参数进行注解,其内部属性和@ApiImplicitParam
注解相似。
@ApiResponses
注解可用于描述请求的状态码,作用在方法上,以数组方式存储,配合 @ApiResponse
注解使用。
@ApiResponse
注解描述一种请求的状态信息。
code
:HTTP请求响应码。message
:响应的文本消息response
:返回类型信息。responseContainer
:如果返回类型为容器类型,可以设置相应的值。有效值为 "List"、 "Set"、"Map"其他任何无效的值都会被忽略。......
尽管在面试中不会过多考察Swagger这类工具,但作为开发者,养成良好的文档规范习惯是非常重要的,无论使用Swagger还是其他文档工具,编写清晰、详尽的API文档都应该是我们的素养之一。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。