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