理解 OpenAPI3 及使用
OpenAPI 3,也被称为OpenAPI规范(OpenAPI Specification,OAS),起源于Swagger 2.0规范,提供一个标准的、与具体编程语言无关的 RESTful API 描述规范
项目中使用 Swagger 来自动生成 RESTful API 的接口文档,对于配置项 SwaggerConfiguration
之前都是 CV ,但关于每一项配置的含义都是一知半解,本文通过 Swagger Editor 和 OpenAPI规范 理解清楚常用配置项的含义。
基于springboot2.x + OpenAPI3,使用Knife4j 来自动生成接口文档,依赖引入
xml
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-openapi3-spring-boot-starter</artifactId>
<version>4.3.0</version>
</dependency>
Info 对象
通过 OpenAPI3 info
对象设置接口文档的基本信息,info 对象:
字段名 | 类型 | 描述 |
---|---|---|
title | string |
必选. 应用的名称。 |
description | string |
对应用的简短描述。可以被用来表示富文本呈现。 |
termsOfService | string |
指向服务条款的URL地址,必须是URL地址格式。 |
contact | 对象 | 所开放的API的联系人信息。 |
license | 对象 | 所开放的API的证书信息。 |
version | string |
必选 . API文档的版本信息(注意:这个版本和开放API规范版本没有任何关系)。 |
Contact 对象:
字段名 | 类型 | 描述 |
---|---|---|
name | string |
人或组织的名称。 |
url | string |
指向联系人信息的URL地址,必须是URL地址格式。 |
string |
人或组织的email地址,必须是email地址格式。 |
License 对象:
字段名 | 类型 | 描述 |
---|---|---|
name | string |
必选. API的证书名。 |
url | string |
指向API所使用的证书的URL地址,必须是URL地址格式。 |
配置项如下:
yml
openapi: "3.0.2"
info:
title: openAPI Demo
description: "This is an API program for teaching"
version: '1.1'
termsOfService: "https://openapi.apifox.cn/"
contact:
name: "api developer"
url: "http://myblog.cn"
email: "[email protected]"
license:
name: "Apache 2.0"
url: "http://springdoc.org"
paths: {}
SwaggerConfiguration 配置项
java
package com.auth.cloud.swagger.config;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.info.Contact;
import io.swagger.v3.oas.models.info.Info;
import io.swagger.v3.oas.models.info.License;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
/**
*
* @author
* @date 2024/02/27
*/
@AutoConfiguration
@ConditionalOnClass({OpenAPI.class})
@EnableConfigurationProperties(SwaggerProperties.class)
@ConditionalOnProperty(prefix = "springdoc.api-docs", name = "enabled", havingValue = "true", matchIfMissing = true)
public class SwaggerConfiguration {
// ========== 全局 OpenAPI 配置 ==========
@Bean
public OpenAPI createOpenApi(SwaggerProperties swaggerProperties) {
System.out.println("SwaggerAutoConfiguration.createOpenApi()"+swaggerProperties);
return new OpenAPI()
.info(buldInfo(swaggerProperties))
;
}
public Info buldInfo(SwaggerProperties swaggerProperties) {
return new Info()
.title(swaggerProperties.getTitle())
.description(swaggerProperties.getDescription())
.version(swaggerProperties.getVersion())
.termsOfService(swaggerProperties.getTermsOfService())
.contact(new Contact().name(swaggerProperties.getAuthor()).email(swaggerProperties.getEmail()).url(swaggerProperties.getUrl()))
.license(new License().name(swaggerProperties.getLicense()).url(swaggerProperties.getLicenseUrl()));
}
}
效果图如下:

servers 对象
servers
主要表示访问服务端的基础路径,既在访问接口前都会带上该参数,无需手动配置,示例如下:

Paths 对象
paths
对象包含真正的 API 信息内容,定义各个的端点和操作的相对路径,自动生成。
字段名模式 | 类型 | 描述 |
---|---|---|
/{path} | Path Item 对象 | 到各个端点的相对路径,路径必须以/ 打头,这个路径会被直接连接 到 Server 对象 的url 字段以组成完整URL地址(不会考虑是否是相对路径)。这里可以使用 Path templating ,当做URL地址匹配时,不带路径参数的路径会被优先匹配。应该避免定义多个具有相同路径层级但是路径参数名不同的路径,因为他们是等价的。当匹配出现歧义时,由使用的工具自行决定使用那个路径。 |

以下是目前会用到的所有关于接口文档的注解
java
import com.auth.cloud.common.pojo.CommonResult;
import com.auth.cloud.i18n.core.I18n;
import com.auth.cloud.permission.service.RoleService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Parameters;
import io.swagger.v3.oas.annotations.enums.ParameterIn;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
/**
* @author
* @date 2024/01/03
*/
@RestController
@RequestMapping("/role")
@Slf4j
@Validated
@Tag(name = "权限管理后台 - 角色", description = "角色信息接口")
public class RoleController {
@Autowired
private I18n i18n;
@Autowired
private RoleService roleService;
@GetMapping("/{id}")
@Operation(summary = "测试接口",description = "测试接口参数")
@Parameters({
@Parameter(name = "id", description = "文件id", in = ParameterIn.PATH),
@Parameter(name = "token", description = "请求token", required = true, in = ParameterIn.HEADER),
@Parameter(name = "name", description = "文件名称", required = true, in = ParameterIn.QUERY)
})
public CommonResult<String> test(@PathVariable("id") String id, @RequestHeader("token") String token,
@RequestParam("name") String name) {
return CommonResult.success("name" + name + "id" + id + "token" + token);
}
}
配置项如下:
yml
paths:
'/role/{id}':
get:
tags:
- 权限管理后台 - 角色
summary: 测试接口
description: 测试接口参数
operationId: test
parameters:
- name: id
in: path
description: 文件id
required: true
schema:
type: string
- name: token
in: header
description: 请求token
required: true
schema:
type: string
- name: name
in: query
description: 文件名称
required: true
schema:
type: string
responses:
'200':
description: OK
content:
'*/*':
schema:
$ref: '#/components/schemas/CommonResultString'
components:
schemas:
CommonResultString:
type: object
properties:
code:
type: integer
format: int32
msg:
type: string
data:
type: string

以上信息描述一个 /role/{id}
的接口 ,它只包含一个 get
操作对象,也称 Operation
对象,属性包含以下:
字段名 | 类型 | 描述 |
---|---|---|
tags | [string ] |
用于控制API文档的标签列表,标签可以用于在逻辑上分组 |
summary | string |
对此操作行为的简短描述。 |
description | string |
对此操作行为的详细解释。 |
operationId | string |
用于标识此操作的唯一字符串,即方法名。 |
parameters | [Parameter 对象 | Reference 对象] | 定义可用于此操作的参数列表,如果一个同名的参数已经存在于 Path Item,那么这里的定义会覆盖它但是不能移除上面的定义。这个列表不允许包含重复的参数,参数的唯一性由 name 和 location 的组合来确定。这个列表可以使用 Reference 对象 来连接定义于 OpenAPI 对象 components/parameters 的参数。 |
responses | Responses 对象 | 必选. 定义执行此操作后的可能的响应值列表。 |
security | [Security Requirement 对象] | 声明哪种安全机制可用于此操作。这个列表可以包含多种可用于此操作的安全需求对象,但是在认证一个请求时应该仅使用其中一种。这里的定义会覆盖任何在顶层 security 中的安全声明,因此可以声明一个空数组来变相的移除顶层的安全声明。 |
parameters
:该接口的请求参数对象,描述如下:
-
name:参数名称
-
in:参数出现的位置,通常是
header
,path
,query
,cookie
-
description:参数的描述(支持 markdown)
-
required:必填项
-
deprecated:是否弃用
-
allowEmptyValue:允许提交空值
-
style:参数序列化方式
-
explode:与数组相关的参数
-
schema:参数的模型
-
example:媒体类型的示例

Response
:描述单个API操作的响应,描述如下:
字段名 | 类型 | 描述 |
---|---|---|
description | string |
必选 . 对响应的简短描述。CommonMark syntax可以被用来呈现富文本格式. |
headers | Map[string , Header 对象 | Reference 对象] |
映射HTTP头名称到其定义。RFC7230 规定了HTTP头名称不区分大小写。如果一个响应头使用"Content-Type" 作为HTTP头名称,它会被忽略。 |
content | Map[string , Media Type 对象] |
一个包含描述预期响应负载的映射。使用 media type 或 media type range 作为键,以响应的描述作为值。当一个响应匹配多个键时,只有最明确的键才适用。比如:text/plain 会覆盖 text/* |
security 对象
大部分的 Web 服务都是需要经过身份认证的才能访问,security 就是用于描述 API 的安全信息和访问授权协议等信息的对象,该属性定义可以放在 Paths
对象的 Operation
对象中,在可在 OpenAPI 文档的根目录添加安全对象,两者的区别如下:


Security Requirement
对象
每个属性的名字都必须与Components 对象 中 Security Schemes 声明的 security scheme 相符。
字段名模式 | 类型 | 描述 |
---|---|---|
{name} | [string ] |
每个名称都必须对应于 Components 对象 下的 Security Schemes 的一个 security scheme。如果此 security scheme 是 "oauth2" 或 "openIdConnect" 类型,那么其值是用于执行的一组 scope names。对于其他 security scheme 类型。此数组必须是空的。 |
Security Requirement 对象示例
Non-OAuth2 Security Requirement
json
{
"api_key": []
}
api_key: []
OAuth2 Security Requirement
json
{
"petstore_auth": [
"write:pets",
"read:pets"
]
}
petstore_auth:
- write:pets
- read:pets
Security Scheme
对象
固定字段
字段名 | 类型 | Applies To | 描述 |
---|---|---|---|
type | string |
Any | 必选 . security scheme 的类型。有效值包括 "apiKey" , "http" , "oauth2" , "openIdConnect" . |
description | string |
Any | 对 security scheme 的简短描述. CommonMark syntax可以被用来呈现富文本格式. |
name | string |
apiKey |
必选. 用于 header、 query 或 cookie 的参数名字。 |
in | string |
apiKey |
必选 . API key 的位置。有效值包括 "query" 、"header" 或 "cookie" . |
scheme | string |
http |
必选 . 用于 Authorization header as defined in RFC7235 的 HTTP Auahorization scheme 的名字. |
bearerFormat | string |
http ("bearer" ) |
用于提示客户端所使用的bearer token的格式。Bearer token 通常通过一个authorization server生成,所以这个字段最主要的目的是用来记录这个信息。 |
flows | OAuth Flows 对象 | oauth2 |
必选. 一个包含所支持的 flow types 的配置信息的对象。 |
openIdConnectUrl | string |
openIdConnect |
必选. 用于发现 OAuth2 配置值的OpenId Connect URL,必须是 URL 形式。 |

java
import io.swagger.v3.oas.models.Components;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.info.Contact;
import io.swagger.v3.oas.models.info.Info;
import io.swagger.v3.oas.models.info.License;
import io.swagger.v3.oas.models.security.SecurityRequirement;
import io.swagger.v3.oas.models.security.SecurityScheme;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.http.HttpHeaders;
import java.util.HashMap;
import java.util.Map;
/**
* Swagger 自动配置类,基于 OpenAPI + Springdoc 实现。
*
* @author
* @date 2024/02/27
*/
@AutoConfiguration
@ConditionalOnClass({OpenAPI.class})
@EnableConfigurationProperties(SwaggerProperties.class)
@ConditionalOnProperty(prefix = "springdoc.api-docs", name = "enabled", havingValue = "true", matchIfMissing = true)
public class SwaggerAutoConfiguration {
// ========== 全局 OpenAPI 配置 ==========
@Bean
public OpenAPI createOpenApi(SwaggerProperties swaggerProperties) {
Map<String, SecurityScheme> securitySchemas = buildSecuritySchemes();
OpenAPI openAPI = new OpenAPI()
.info(buldInfo(swaggerProperties))
// 接口安全配置
.components(new Components().securitySchemes(securitySchemas))
.addSecurityItem(new SecurityRequirement().addList(HttpHeaders.AUTHORIZATION));
return openAPI;
}
/**
* API 摘要信息
*/
public Info buldInfo(SwaggerProperties swaggerProperties) {
return new Info()
.title(swaggerProperties.getTitle())
.description(swaggerProperties.getDescription())
.version(swaggerProperties.getVersion())
.termsOfService(swaggerProperties.getTermsOfService())
.contact(new Contact().name(swaggerProperties.getAuthor()).email(swaggerProperties.getEmail()).url(swaggerProperties.getUrl()))
.license(new License().name(swaggerProperties.getLicense()).url(swaggerProperties.getLicenseUrl()));
}
/**
* 安全模式,这里配置通过请求头 Authorization 传递 token 参数
*/
private Map<String, SecurityScheme> buildSecuritySchemes() {
Map<String, SecurityScheme> securitySchemes = new HashMap<>();
SecurityScheme securityScheme = new SecurityScheme()
.type(SecurityScheme.Type.APIKEY) // 类型
.name(HttpHeaders.AUTHORIZATION) // 请求头的 name
.in(SecurityScheme.In.HEADER); // token 所在位置
securitySchemes.put(HttpHeaders.AUTHORIZATION, securityScheme);
return securitySchemes;
}
}
参考: