SpringBoot整合Swagger3生成接口文檔的示例代碼
一:前言
Swagger 是一個(gè) RESTful API 的開源框架,它的主要目的是幫助開發(fā)者設(shè)計(jì)、構(gòu)建、文檔化和測試 Web API。Swagger 的核心思想是通過定義和描述 API 的規(guī)范、結(jié)構(gòu)和交互方式,以提高 API 的可讀性、可靠性和易用性,同時(shí)降低 API 開發(fā)的難度和開發(fā)者之間的溝通成本。
這里我采用了Swagger3.0(Open API 3.0)的方式集成到SpringBoot。springfox-boot-start和springfox-swagger2都是基于Swagger2.x的。這里將介紹springdoc-openapi-ui,它是SpringBoot基于Open API 3.0(Swagger3.0)
1:Swagger發(fā)展史
Swagger它最初由Tony Tam在2011年創(chuàng)建,并在之后被SmartBear Software公司收購。在過去幾年中,Swagger經(jīng)歷了許多重大的更新和變化,其發(fā)展史大概可以分為以下幾個(gè)階段:
①:Swagger 1.x 階段(2011-2014年)
Swagger最初是一個(gè)簡單的API文檔生成工具,通過對JAX-RS和Jersey注解的支持自動生成API文檔,使得API文檔的維護(hù)變得更加容易。
在這個(gè)階段,Swagger還沒有完全成熟,只能支持基本的API描述和文檔生成。
②:Swagger 2.x 階段(2014-2017年)
在Swagger 2.x階段,Swagger發(fā)生了重大變化。它不再僅僅是一個(gè)文檔生成工具,而是一個(gè)完整的API開發(fā)和管理平臺。Swagger 2.x加入了強(qiáng)大的注解支持,可以描述API的細(xì)節(jié)信息,如請求參數(shù)、返回類型等,以及定義RESTful API的元數(shù)據(jù),如API描述、標(biāo)簽等。此外,Swagger 2.x還引入了OpenAPI規(guī)范,在API定義方面有了更嚴(yán)格的標(biāo)準(zhǔn)和規(guī)則。
③:OpenAPI 階段(2017-至今)(也被稱為Swagger 3.x)
在2017年,Swagger 2.x的規(guī)范成為了Linux基金會旗下的OpenAPI規(guī)范。這標(biāo)志著Swagger從一款工具演變成為了一個(gè)開放且標(biāo)準(zhǔn)的API定義框架。OpenAPI規(guī)范不僅繼承了Swagger 2.x的特性,還提供了更加全面和嚴(yán)格的API定義規(guī)范,并且擴(kuò)展了對非RESTful API的支持
隨著OpenAPI規(guī)范的普及,越來越多的API開發(fā)者開始使用Swagger/OpenAPI來開發(fā)、測試和文檔化他們的RESTful API?! ?/p>
所以,隨著Linux基金會旗下的OpenAPI收購了Swagger2.x后對其進(jìn)行了更嚴(yán)格的規(guī)范,又進(jìn)行了各種優(yōu)化,所以我們也可以稱OpenAPI是一個(gè)全新的Swagger3.x,因?yàn)镺penAPI對其作了更多的優(yōu)化和規(guī)范。
除了上述幾個(gè)主要階段之外,還有一些其他重要的事件和版本,如Swagger UI、Swagger Codegen、SwaggerHub等等。
這些工具和服務(wù)進(jìn)一步擴(kuò)展了Swagger的功能,使其成為了一個(gè)更加完整、強(qiáng)大和易于使用的API定義和管理平臺。
2:Swagger其它介紹
其實(shí) OpenAPI規(guī)范(也稱為 Swagger 3.x 規(guī)范) 是一種用于描述RESTful API的標(biāo)準(zhǔn)化格式,它定義了如何描述API的基本信息、結(jié)構(gòu)、參數(shù)、響應(yīng)等方面的規(guī)范。OpenAPI規(guī)范以機(jī)器可讀的方式定義了RESTful API的結(jié)構(gòu)和特征,支持自動生成文檔、客戶端與服務(wù)端代碼、Mock Server和測試工具等。
OpenAPI規(guī)范最初由開發(fā)Swagger的團(tuán)隊(duì)在2010年推出,從Swagger 2.0開始,Swagger規(guī)范被正式更名為OpenAPI規(guī)范,并得到了許多社區(qū)的支持和貢獻(xiàn)。OpenAPI規(guī)范采用JSON或YAML格式編寫,并支持多種數(shù)據(jù)類型,可以描述API的基本信息、路徑、HTTP方法、參數(shù)、響應(yīng)等各種細(xì)節(jié)。通過遵循OpenAPI規(guī)范,開發(fā)者可以快速定義和構(gòu)建RESTful API,并且可以生成相應(yīng)的文檔和代碼來幫助他們更快地開發(fā)與測試API。同時(shí),OpenAPI規(guī)范還可以促進(jìn)不同系統(tǒng)之間的交互和集成,因?yàn)楦鶕?jù)規(guī)范定義的API可以被多個(gè)客戶端程序和服務(wù)端程序所理解和使用。
OpenAPI階段的Swagger也被稱為Swagger 3.0。在Swagger 2.0后,Swagger規(guī)范正式更名為OpenAPI規(guī)范,并且根據(jù)OpenAPI規(guī)范的版本號進(jìn)行了更新。因此,Swagger 3.0對應(yīng)的就是OpenAPI 3.0版本,它是Swagger在OpenAPI階段推出的一個(gè)重要版本。與前幾個(gè)版本相比,Swagger 3.0更加強(qiáng)調(diào)對RESTful API的支持和規(guī)范化,提供了更豐富和靈活的定義方式,并且可以用于自動生成文檔、客戶端代碼、服務(wù)器代碼和測試工具等。
3:SpringFox工具(不推薦)
Springfox是一套可以幫助Java開發(fā)者自動生成API文檔的工具,它是基于Swagger 2.x基礎(chǔ)上開發(fā)的。Swagger已經(jīng)成為了RESTful API文檔生態(tài)系統(tǒng)的事實(shí)標(biāo)準(zhǔn),而Springfox是一個(gè)用于集成Swagger2.x到Spring應(yīng)用程序中的庫。而且Springfox提供了一些注解來描述API接口、參數(shù)和返回值,并根據(jù)這些信息生成Swagger UI界面,從而方便其他開發(fā)人員查看和使用您的API接口。此外,Springfox還支持自動生成API文檔和代碼片段,簡化了開發(fā)人員的工作量。除了集成Swagger 2.x,Springfox還提供了一些額外功能,例如自定義Swagger文檔、API版本控制、請求驗(yàn)證等等。這些功能使得Springfox可以勝任各種類型和規(guī)模的應(yīng)用程序,同時(shí)還可以提高代碼質(zhì)量和開發(fā)效率??傊琒pringfox是一個(gè)非常有用的工具,它可以幫助Java開發(fā)者快速、簡單地集成Swagger2.x,并為他們的應(yīng)用程序生成高質(zhì)量的API文檔。無論您開發(fā)的是大型企業(yè)應(yīng)用程序還是小型服務(wù),使用Springfox都能夠提高團(tuán)隊(duì)的生產(chǎn)力和代碼質(zhì)量。
注意:但是隨著時(shí)間的推移,Swagger2.x終究成為歷史,所以我們可以看出springfox-boot-starter的坐標(biāo)從3.0.0版本(2020年7月14日)開始就一直沒有更新;也得注意的是springfox-swagger2坐標(biāo)和springfox-boot-start是一樣的,但springfox-boot-start只有3.0.0版本。這里我就不在使用Swagger2.x版本,具體可以在網(wǎng)上找到許多,因?yàn)榇蟛糠值木W(wǎng)上資料都是Swagger2.x的方式。
4:SpringDoc工具(推薦)
SpringDoc對應(yīng)坐標(biāo)是springdoc-openapi-ui,它是一個(gè)集成Swagger UI和ReDoc的接口文檔生成工具,在使用上與springfox-boot-starter類似,但提供了更為靈活、功能更加強(qiáng)大的工具。其中除了可以生成Swagger UI風(fēng)格的接口文檔,還提供了ReDoc的文檔渲染方式,可以自動注入OpenAPI規(guī)范的JSON描述文件,支持OAuth2、JWT等認(rèn)證機(jī)制,并且支持全新的OpenAPI 3.0規(guī)范。
SpringDoc是基于OpenAPI 3.0規(guī)范構(gòu)建的,因此推薦在Spring Boot 2.4及以上版本中使用springdoc-openapi-ui庫來集成Swagger3.x。在這些版本中,springdoc-openapi-ui庫已被廣泛應(yīng)用,并且得到了社區(qū)的大力支持和推廣。而在Spring Boot 2.3及其以下版本,可以使用springfox-boot-starter庫來集成Swagger2.x。
SpringDoc是有著更加先進(jìn)的技術(shù)架構(gòu)和更好的擴(kuò)展性,使得其逐漸取代了springfox-boot-starter工具包,成為了當(dāng)前Spring Boot生態(tài)中最受歡迎的API文檔工具之一。同時(shí)springdoc-openapi-ui還擁有更為完善的開發(fā)文檔和社區(qū)支持,從而吸引了越來越多的開發(fā)者加入到這個(gè)項(xiàng)目中。因此作為一個(gè)Spring Boot開發(fā)者,如果想要快速、方便地生成符合OpenAPI 3.0規(guī)范的接口文檔,建議使用springdoc-openapi-ui這個(gè)優(yōu)秀的工具。
二:SpringBoot集成Open API 3.0(Swagger3.0)
我們在SpringBoot中想集成Swagger3.0,一般不選擇原生的Maven坐標(biāo),而是選擇 springdoc-openapi-ui的Maven坐標(biāo),它可以很好的和Spring或SpringBoot項(xiàng)目集成;這個(gè)坐標(biāo)也被Spring社區(qū)廣泛支持和認(rèn)可,并被認(rèn)為是集成Swagger UI和OpenAPI規(guī)范的一個(gè)優(yōu)秀選擇。下面將直接介紹使用。
1:引入Maven依賴
<!-- 導(dǎo)入SpringBoot集成Open API 3.0(Swagger3.0)的坐標(biāo) -->
<!-- 這個(gè)坐標(biāo)它提供了一組注解和工具來集成Swagger UI和OpenAPI規(guī)范等-->
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-ui</artifactId>
<version>1.7.0</version>
</dependency>
說明:上面的坐標(biāo)內(nèi)部導(dǎo)入了Swagger3.0的原生依賴(我們只需要在SpringBoot導(dǎo)入springdoc-openapi-ui即可)
①:io.swagger.core.v3:swagger-core:2.2.9
Swagger Core是Swagger 3.x規(guī)范的核心實(shí)現(xiàn),提供了一組Java API,用于生成和處理OpenAPI規(guī)范文件。
它包括Swagger的核心功能,例如Model、Schema、Parameter、Response等,是構(gòu)建Swagger API的必要條件。
②:io.swagger.core.v3:swagger-annotations:2.2.9
Swagger Annotations是一個(gè)用于編寫Swagger API文檔的Java注解庫,提供了一組注解,用于描述API元數(shù)據(jù)。
例如,@Operation、@Parameter、@ApiResponse等注解基本包含了OpenAPI規(guī)范中的所有元素。
③:io.swagger.core.v3:swagger-models:2.2.9
Swagger Models是Swagger 3.x規(guī)范的Java模型庫,提供了一組Java模型類,用于表示OpenAPI規(guī)范文件。
它包含了OpenAPI規(guī)范中的所有數(shù)據(jù)模型,例如PathItem、Operation、Parameter、Components等。
2:配置SwaggerOpenApiConfig(配置類方式)
注:io.swagger.v3.oas.annotations 是Swagger注解包,而io.swagger.v3.oas.models是Swagger配置類對象方式
其實(shí)我們通過配置類的方式創(chuàng)建一個(gè)OpenAPI的Bean對象就可以創(chuàng)建Swagger3.0的文檔說明,下面我就直創(chuàng)建。
OpenAPI對象是Swagger中的核心類之一,用于描述整個(gè)API的結(jié)構(gòu)和元數(shù)據(jù)??梢岳斫鉃橐粋€(gè)API文檔對象,其中包含了許多元素,如:
①:openapi屬性:
表示使用的 OpenAPI 規(guī)范版本(例如 3.0.1)。
②:info屬性:
表示API的基本信息,包括標(biāo)題、版本號、描述、聯(lián)系人等。使用Info類來創(chuàng)建這個(gè)對象。
③:servers屬性:
表示服務(wù)器地址或者URL模板列表。每個(gè)URL模板可以包含占位符,這些占位符可以被路徑參數(shù)或者查詢參數(shù)替換。
使用Server類來創(chuàng)建這個(gè)對象。
④:paths屬性(推薦使用注解方式,不推薦使用配置類配置):
表示API的所有路徑和操作信息,使用PathItem類來描述每一個(gè)路徑,使用Operation類來描述操作。
⑤:components屬性:
表示API的組件信息,比如響應(yīng)模板、請求模板和安全方案等。
使用Schema、Response、Parameter、SecurityScheme等類來創(chuàng)建這些對象。
⑥:tags屬性:
表示API的標(biāo)簽信息,用于對相似的操作進(jìn)行分組。
⑦:addServersItem(Server server)方法:
向servers屬性中添加一個(gè)Server對象。
⑧:addPaths(String name, PathItem pathItem)方法:
向paths屬性中添加一個(gè)PathItem對象,其中name參數(shù)表示路徑模板。
⑨:addTag(Tag tag)方法:
向tags屬性中添加一個(gè)Tag對象。
⑩:setComponents(Components components)方法:
設(shè)置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 org.springframework.boot.SpringBootConfiguration;
import org.springframework.context.annotation.Bean;
import java.util.HashMap;
/** 這是一個(gè)普通的Swagger配置文檔,其中不包含API接口的配置(API接口的配置推薦使用注解方式)
* @author Anhui OuYang
* @version 1.0
**/
@SpringBootConfiguration
public class SwaggerOpenApiConfig {
/***
* 構(gòu)建Swagger3.0文檔說明
* @return 返回 OpenAPI
*/
@Bean
public OpenAPI customOpenAPI() {
// 聯(lián)系人信息(contact),構(gòu)建API的聯(lián)系人信息,用于描述API開發(fā)者的聯(lián)系信息,包括名稱、URL、郵箱等
// name:文檔的發(fā)布者名稱 url:文檔發(fā)布者的網(wǎng)站地址,一般為企業(yè)網(wǎng)站 email:文檔發(fā)布者的電子郵箱
Contact contact = new Contact()
.name("螞蟻小哥") // 作者名稱
.email("xiaofeng@qq.com") // 作者郵箱
.url("https://www.cnblogs.com/antLaddie/") // 介紹作者的URL地址
.extensions(new HashMap<String, Object>()); // 使用Map配置信息(如key為"name","email","url")
// 授權(quán)許可信息(license),用于描述API的授權(quán)許可信息,包括名稱、URL等;假設(shè)當(dāng)前的授權(quán)信息為Apache 2.0的開源標(biāo)準(zhǔn)
License license = new License()
.name("Apache 2.0") // 授權(quán)名稱
.url("https://www.apache.org/licenses/LICENSE-2.0.html") // 授權(quán)信息
.identifier("Apache-2.0") // 標(biāo)識授權(quán)許可
.extensions(new HashMap<String, Object>());// 使用Map配置信息(如key為"name","url","identifier")
//創(chuàng)建Api幫助文檔的描述信息、聯(lián)系人信息(contact)、授權(quán)許可信息(license)
Info info = new Info()
.title("Swagger3.0 (Open API) 框架學(xué)習(xí)示例文檔") // Api接口文檔標(biāo)題(必填)
.description("學(xué)習(xí)Swagger框架而用來定義測試的文檔") // Api接口文檔描述
.version("1.2.1") // Api接口版本
.termsOfService("https://example.com/") // Api接口的服務(wù)條款地址
.license(license) // 設(shè)置聯(lián)系人信息
.contact(contact); // 授權(quán)許可信息
// 返回信息
return new OpenAPI()
.openapi("3.0.1") // Open API 3.0.1(默認(rèn))
.info(info); // 配置Swagger3.0描述信息
}
}
3:配置SwaggerOpenApiConfig(注解方式)
上面我們使用了Java代碼創(chuàng)建Bean的方式,其實(shí)這種寫起來感覺還行,但是在使用了注解方式是很舒服的,下面就簡單說明:
定義Swagger3.0配置信息注解:@OpenAPIDefinition (具體參考 io.swagger.v3.oas.annotations)注意:這個(gè)注解全局只能配置一個(gè),主要配置文檔信息和安全配置
說明:用于描述整個(gè)API的元信息和全局屬性,可以定義和描述,包括API版本、基本信息、服務(wù)器信息、安全方案等
常用屬性:
①:info:用于描述 API 基本信息的對象,包括標(biāo)題、版本號、描述等屬性;
②:servers:用于描述 API 服務(wù)的 URL 和配置信息的數(shù)組;
③:security:用于描述 API 安全方案的數(shù)組,其中每個(gè)安全方案包含多個(gè)安全需求;
④:tags:用于描述 API 標(biāo)簽的數(shù)組,每個(gè)標(biāo)簽包含名稱、描述等屬性;
⑤:externalDocs:用于描述外部文檔鏈接的對象,包含描述和 URL 兩個(gè)屬性。
import io.swagger.v3.oas.annotations.ExternalDocumentation;
import io.swagger.v3.oas.annotations.OpenAPIDefinition;
import io.swagger.v3.oas.annotations.info.Contact;
import io.swagger.v3.oas.annotations.info.Info;
import io.swagger.v3.oas.annotations.info.License;
import io.swagger.v3.oas.annotations.servers.Server;
import org.springframework.boot.SpringBootConfiguration;
/**
* @author Anhui OuYang
* @version 1.0
**/
@SpringBootConfiguration
@OpenAPIDefinition(
// ## API的基本信息,包括標(biāo)題、版本號、描述、聯(lián)系人等
info = @Info(
title = "Swagger3.0 (Open API) 框架學(xué)習(xí)示例文檔", // Api接口文檔標(biāo)題(必填)
description = "學(xué)習(xí)Swagger框架而用來定義測試的文檔", // Api接口文檔描述
version = "1.2.1", // Api接口版本
termsOfService = "https://example.com/", // Api接口的服務(wù)條款地址
contact = @Contact(
name = "螞蟻小哥", // 作者名稱
email = "xiaofeng@qq.com", // 作者郵箱
url = "https://www.cnblogs.com/antLaddie/" // 介紹作者的URL地址
),
license = @License( // 設(shè)置聯(lián)系人信息
name = "Apache 2.0", // 授權(quán)名稱
url = "https://www.apache.org/licenses/LICENSE-2.0.html" // 授權(quán)信息
)
),
// ## 表示服務(wù)器地址或者URL模板列表,多個(gè)服務(wù)地址隨時(shí)切換(只不過是有多臺IP有當(dāng)前的服務(wù)API)
servers = {
@Server(url = "http://192.168.2.235/demo/", description = "本地服務(wù)器一服務(wù)"),
@Server(url = "http://192.168.2.236/demo/", description = "本地服務(wù)器二服務(wù)"),
},
externalDocs = @ExternalDocumentation(description = "更多內(nèi)容請查看該鏈接", url = "xxx"))
public class SwaggerOpenApiConfig {
}
4:配置API接口信息(注解,重要)
說了這么久,Swagger3.0的全局基本信息配置是處理好了,接下來就是配置接口了,因?yàn)槲抑皩懥薈ontroller代碼,但是沒有接口配置信息,這里我就使用Swagger的方式進(jìn)行一個(gè)簡單的配置。
示例代碼,不是太明白屬性的可以看下面屬性介紹
// 響應(yīng)對象模型定義
@Data
@AllArgsConstructor
@Schema(description = "響應(yīng)返回?cái)?shù)據(jù)對象")
public class AjaxResult {
@Schema(
title = "code",
description = "響應(yīng)碼",
format = "int32",
requiredMode = Schema.RequiredMode.REQUIRED
)
private Integer code;
@Schema(
title = "msg",
description = "響應(yīng)信息",
accessMode = Schema.AccessMode.READ_ONLY,
example = "成功或失敗",
requiredMode = Schema.RequiredMode.REQUIRED
)
private String msg;
@Schema(title = "data", description = "響應(yīng)數(shù)據(jù)", accessMode = Schema.AccessMode.READ_ONLY)
private Object data;
}
// 模型定義示例:
@Data
@AllArgsConstructor
@Schema(title = "學(xué)生模型VO", description = "響應(yīng)視圖學(xué)生模型VO")
public class StudentVO {
@Schema(name = "學(xué)生ID", description = "學(xué)生ID屬性", format = "int64", example = "1")
private Long id; // 學(xué)生ID
@Schema(name = "學(xué)生姓名", description = "學(xué)生姓名屬性", example = "jack")
private String name; // 學(xué)生姓名
@Schema(name = "學(xué)生年齡", description = "學(xué)生年齡屬性", format = "int32", example = "24")
private Integer age; // 學(xué)生年齡
@Schema(name = "學(xué)生地址", description = "學(xué)生地址屬性", example = "安徽合肥")
private String address; // 學(xué)生地址
@Schema(name = "學(xué)生分?jǐn)?shù)", description = "學(xué)生分?jǐn)?shù)屬性", format = "double", example = "55.50")
private Double fraction; // 學(xué)生分?jǐn)?shù)
@Schema(name = "學(xué)生愛好", description = "學(xué)生愛好屬性(List類型)",
type = "array", example = "[\"玩\", \"寫字\"]")
private List<String> likes; // 學(xué)生愛好
}
// 接口定義
@RestController
@RequestMapping("/student")
@Tag(
name = "StudentControllerAPI",
description = "學(xué)生控制器接口",
externalDocs = @ExternalDocumentation(
description = "這是一個(gè)接口文檔介紹",
url = "https://www.cnblogs.com/antLaddie/"))
public class StudentController {
/***
* 根據(jù)ID查詢學(xué)生信息(單條)
* @param id 學(xué)生id
* @return 返回一條數(shù)據(jù)
*/
@Operation(
summary = "根據(jù)Id查詢學(xué)生信息",
description = "根據(jù)ID查詢學(xué)生信息,并返回響應(yīng)結(jié)果信息",
parameters = {
@Parameter(name = "id", description = "學(xué)生ID", required = true, example = "1")
},
responses = {
@ApiResponse(
responseCode = "200",
description = "響應(yīng)成功",
content = @Content(
mediaType = "application/json",
schema = @Schema(
title = "AjaxResul和StudentVO組合模型",
description = "返回實(shí)體,AjaxResult內(nèi)data為StudentVO模型",
anyOf = {AjaxResult.class, StudentVO.class})
)
),
@ApiResponse(
responseCode = "500",
description = "響應(yīng)失敗",
content = @Content(
mediaType = "application/json",
schema = @Schema(
title = "AjaxResul模型",
description = "返回實(shí)體,AjaxResult內(nèi)data為空",
implementation = AjaxResult.class)
)
)
}
)
@GetMapping("/findOne/{id}")
public AjaxResult findOneStudent(@PathVariable(value = "id") Long id) {
//模擬學(xué)生數(shù)據(jù)
List<String> likes = Arrays.asList("抓魚", "爬山", "寫字");
StudentVO studentVO = new StudentVO(id, "張三", 22, "安徽六安", 93.5, likes);
return new AjaxResult(200, "成功", studentVO);
}
/***
* 查詢?nèi)繉W(xué)生數(shù)據(jù)
* @return 返回d條數(shù)據(jù)
*/
@Operation(
summary = "查詢?nèi)繉W(xué)生數(shù)據(jù)",
description = "查詢學(xué)生信息,并返回響應(yīng)結(jié)果信息",
parameters = {},
deprecated = true,
responses = {
@ApiResponse(
responseCode = "200",
description = "響應(yīng)成功",
content = @Content(
mediaType = "application/json",
schema = @Schema(
title = "AjaxResul和StudentVO組合模型",
description = "返回實(shí)體,AjaxResult內(nèi)data為" +
"StudentVO模型(并且StudentVO為集合)",
anyOf = {AjaxResult.class, StudentVO.class})
)
)
}
)
@GetMapping("/findAll")
public AjaxResult findAllStudent() {
//模擬學(xué)生數(shù)據(jù)
List<String> likes = Arrays.asList("抓魚", "爬山", "寫字");
StudentVO student1 = new StudentVO(1L, "張三", 22, "安徽六安", 93.5, likes);
StudentVO student2 = new StudentVO(2L, "李四", 24, "安徽合肥", 99.5, likes);
return new AjaxResult(200, "成功", Arrays.asList(student1, student2));
}
/***
* 學(xué)生添加接口
* @param studentDTO 學(xué)生DTO信息
* @return 成功信息
*/
@Operation(
summary = "學(xué)生添加接口",
description = "學(xué)生添加接口",
parameters = {},
requestBody = @io.swagger.v3.oas.annotations.parameters.RequestBody(
description = "學(xué)生信息DTO",
required = true,
content = {
@Content(
mediaType = "application/json",
schema = @Schema(implementation = StudentDTO.class)
)
}
),
responses = {
@ApiResponse(
responseCode = "200",
description = "響應(yīng)成功",
content = @Content(
mediaType = "application/json",
schema = @Schema(
title = "AjaxResul模型",
description = "返回實(shí)體AjaxResult,并且Data為null",
implementation = AjaxResult.class)
)
)
}
)
@PostMapping("/saveStudent")
public AjaxResult saveStudent(@RequestBody StudentDTO studentDTO) {
System.out.println("成功添加數(shù)據(jù):" + studentDTO);
return new AjaxResult(200, "成功", null);
}
配置文檔標(biāo)題及歸類,就是在Controller上配置。
注解:@Tag 可以用于對接口進(jìn)行分類和歸類,便于開發(fā)人員組織和管理 API 文檔
具體屬性:
①:name:表示標(biāo)簽的名稱,必填屬性,也得注意多個(gè)Controller上的name不要寫一樣的,這樣就會把它們歸類在一起。
②:description:表示標(biāo)簽的描述信息,非必填屬性。
③:externalDocs:用于指定URL地址文檔信息來追加描述接口的信息。非必填屬性。
示例:
@Tag(
name = "StudentControllerAPI",
description = "學(xué)生控制器接口",
externalDocs = @ExternalDocumentation(
description = "這是一個(gè)接口文檔介紹",
url = "https://www.cnblogs.com/antLaddie/"))
配置文檔下的每一個(gè)接口信息,就是Controller里的每一個(gè)RequestMapping
注解:@Operation用于對API操作(即方法)進(jìn)行描述和標(biāo)記。就是我們熟知的Controller下的一個(gè)個(gè)請求的方法上。
具體可以參考 io.swagger.v3.oas.annotations。
具體屬性:
①:summary:用于簡要描述API操作的概要。
②:description:用于詳細(xì)描述API操作的描述信息。
③:parameters:用于指定API操作的參數(shù)列表,包括路徑參數(shù)、請求參數(shù)、請求頭部等??梢允褂聾Parameter注解進(jìn)一步定義參數(shù)。
④:operationId:用于指定API操作的唯一標(biāo)識符,可以用于生成客戶端代碼或文檔等。
說明:第三方工具使用operationId來唯一標(biāo)識此操作。(具體我也沒用過)
⑤:requestBody:用于定義API操作的請求體,可以使用@RequestBody注解進(jìn)一步定義請求體。
說明:這里的@RequestBody注解是@io.swagger.v3.oas.annotations.parameters.RequestBody包里的
⑥:responses:用于定義 API 操作的響應(yīng)列表,包括成功響應(yīng)和錯(cuò)誤響應(yīng)??梢允褂聾ApiResponse注解進(jìn)一步定義響應(yīng)。
⑦:security:用于對API操作進(jìn)行安全控制,可以使用@SecurityRequirement注解進(jìn)一步定義安全需求。(后面說)
⑧:deprecated:表示該API操作已經(jīng)過時(shí)或不推薦使用。
@Operation(
summary = "根據(jù)Id查詢學(xué)生信息",
description = "根據(jù)ID查詢學(xué)生信息,并返回響應(yīng)結(jié)果信息",
parameters = {
@Parameter(name = "id", description = "學(xué)生ID", required = true, example = "1")
},
responses = {
@ApiResponse(
responseCode = "200",
description = "響應(yīng)成功",
content = @Content(
mediaType = "application/json",
schema = @Schema(
title = "AjaxResul和StudentVO組合模型",
description = "返回實(shí)體,AjaxResult內(nèi)data為StudentVO模型",
anyOf = {AjaxResult.class, StudentVO.class})
)
)
}
)
配置請求接口參數(shù)信息
注解:@Parameter用于描述HTTP請求的參數(shù)信息,它是一個(gè)Parameter[]類型的數(shù)組,每個(gè)元素表示一個(gè)請求參數(shù);
具體參考:io.swagger.v3.oas.annotations;它是一個(gè)注解,和Parameter類一樣,只不過一個(gè)是注解一個(gè)是類的方式
①:name:參數(shù)名稱。
②:in:參數(shù)位置,可以是 query、header、path、cookie 等。
③:description:參數(shù)描述。
④:required:參數(shù)是否必須,默認(rèn)為 false。
⑤:deprecated:參數(shù)是否已過時(shí),默認(rèn)為 false。
⑥:allowEmptyValue:是否允許空值,默認(rèn)為false。
⑦:style:參數(shù)的序列化風(fēng)格,可以是 "matrix"、"label"、"form"、"simple"、
"spaceDelimited"、"pipeDelimited"、"deepObject";
⑧:explode:當(dāng)參數(shù)值是對象或數(shù)組時(shí),是否將其展開成多個(gè)參數(shù),默認(rèn)為 false。
⑨:schema:參數(shù)類型和格式的定義,通常使用@Schema注解。(下面介紹)
⑩:example:參數(shù)值的示例;
示例:
parameters = {
@Parameter(name = "id", in = ParameterIn.PATH, description = "學(xué)生ID",
required = true, example = "1")
},
配置具體的實(shí)體模型信息
注解:@Schema 是用于描述數(shù)據(jù)模型的基本信息和屬性,具體可以參考“io.swagger.v3.oas.annotations.media”
具體屬性:
①:description:用于描述該類或?qū)傩缘淖饔谩?
②:name:指定屬性名。該屬性只對屬性有效,對類無效。
③:title:用于顯示在生成的文檔中的標(biāo)題。
④:requiredMode:用于指定該屬性是否必填項(xiàng)。枚舉Schema.RequiredMode內(nèi)可選值如下:
默認(rèn)AUTO:可有可無;REQUIRED:必須存在此字段(會加紅色*);NOT_REQUIRED:不需要存在此字段
⑤:accessMode:用于指定該屬性的訪問方式。
包括AccessMode.READ_ONLY(只讀)、AccessMode.WRITE_ONLY(只寫)、AccessMode.READ_WRITE(讀寫)
⑥:format:用于指定該屬性的數(shù)據(jù)格式。例如:日期格式、時(shí)間格式、數(shù)字格式。
⑦:example:為當(dāng)前的屬性創(chuàng)建一個(gè)示例的值,后期測試可以使用此值。
⑧:deprecated:用于指定該屬性是否為已過時(shí)的屬性,默認(rèn)為false。
⑨:defaultValue:用于指定該屬性的默認(rèn)值。
⑩:implementation:用于顯示為該類或?qū)傩砸刖唧w的實(shí)體路徑,這代表當(dāng)前指定的類或者屬性將參考引入的實(shí)體。
就是說有個(gè)實(shí)體類,這個(gè)類里面有個(gè)teacher屬性,這時(shí)里面的teacher屬性可以指定具體的實(shí)體類,如下:
public class Student {
...
@Schema(description = "老師信息",implementation = Teacher.class)
private Teacher teacher;
...
}
其它屬性:
①:type:用于指定數(shù)據(jù)類型(Data Type)或者元素類型(Element Type)
基本類型:取值為相應(yīng)的 Java 類型名,例如 int、long、float、double、boolean 等。
包裝類型:與基本類型相同,取值為相應(yīng)的Java包裝類型名,例如Integer、Long、Float、Double、Boolean等。
字符串類型:取值為string。
數(shù)組類型:取值為 array。對于數(shù)組類型,還可以使用 schema 屬性指定其元素類型的 Schema 信息。
對象類型:不用指定type,可以通過implementation屬性引入。
枚舉類型:取值為enum。對于枚舉類型,還需要使用enumAsRef屬性指定是否將其定義為一個(gè)獨(dú)立的引用類型。
其它類型:不用指定type,可以通過implementation屬性引入。
@Schema注解:提供了四個(gè)屬性來描述復(fù)雜類型,分別是allOf、anyOf、oneOf和not。
這四個(gè)屬性可以用于組合不同的JSON Schema以描述一個(gè)復(fù)雜類型,具體如下:
①:allOf: 表示當(dāng)前schema是多個(gè)其它schema的并集。
例如,如果一個(gè)Java類型同時(shí)實(shí)現(xiàn)了兩個(gè)接口,那么可以使用allOf來表示這個(gè)Java類型繼承了這兩個(gè)接口的所有屬性和方法。
②:anyOf: 表示當(dāng)前schema可以匹配其中任意一個(gè)schema,其本身也是一個(gè)組合體,可以嵌套使用。
例如,一個(gè)返回類型可能是多個(gè)Java類型中的任意一個(gè),可以使用anyOf來描述這種情況。
③:oneOf: 表示當(dāng)前schema只能匹配其中一個(gè)schema,其本身也是一個(gè)組合體,可以嵌套使用。
例如,一個(gè)Java類型只能是多個(gè)子類型中的任意一個(gè),可以使用oneOf來描述這種情況。
④:not: 表示當(dāng)前Schema不能匹配某個(gè)schema。
例如,一個(gè)Java類型不能是某個(gè)子類型,可以使用not來描述這種情況。
但是總感覺這個(gè)Swagger無法滿足我特定要求的實(shí)體,具體解決如下:
比如我現(xiàn)在有個(gè)AjaxResult類(code,msg,data),其中data為Object或其它類型,這時(shí)我返回的數(shù)據(jù)里data為其它類型的
實(shí)體,所以我這里不理解如何返回的實(shí)體中,通過點(diǎn)擊data而顯示另外實(shí)體,我只能通過anyOf方式來實(shí)現(xiàn)(加上注解)
@ApiResponse(
responseCode = "200",
description = "響應(yīng)成功",
content = @Content(
mediaType = "application/json",
schema = @Schema(
description = "返回實(shí)體,AjaxResult內(nèi)data為StudentVO模型",
anyOf = {AjaxResult.class, StudentVO.class})
)
)
5:配置API接口信息(定義類方式,不推薦)
上面介紹了使用注解的方式完成接口的說明,這里我來說說定義類的方式來完成接口的定義,其實(shí)這種方式不推薦,寫起來繁瑣麻煩,后期改起來也亂,但是還是說下,下面就是具體的代碼信息接口及模型的描述(使用定義類的方式)
/**
* 老師接口描述
*
* @author Anhui OuYang
* @version 1.0
**/
public class InterfaceDescriptionConfig {
/***
* get方式保存老師信息接口
* @return PathItem
*/
public static PathItem addTeacher() {
//=====================創(chuàng)建字段描述信息(老師類描述)如:TeacherDTO=====================
Schema id = new IntegerSchema().format("int64").description("老師ID");
Schema name = new StringSchema().minLength(2).maxLength(5).example("張三").description("老師姓名");
Schema age = new IntegerSchema().format("int32").maximum(new BigDecimal("99"))
.minimum(new BigDecimal("1")).example("23").description("老師年齡");
Schema birthday = new DateSchema().format("date").example("2023-12-12").description("老師生日");
Schema address = new StringSchema().minLength(2).maxLength(9).example("安徽省").description("老師地址");
Schema salary = new NumberSchema().format("bigDecimal").maximum(new BigDecimal("99999.99"))
.minimum(new BigDecimal("100.00")).example("6500.50").description("老師工資");
Schema fraction = new NumberSchema().format("double").maximum(new BigDecimal("99.99"))
.minimum(new BigDecimal("10.00")).example("25.3").description("老師評分");
Schema likes = new ArraySchema().minItems(1).maxItems(10).description("這是一個(gè)愛好數(shù)組");
Schema isHeadmaster = new BooleanSchema().example(true).description("是否是班主任");
Schema schema = new ObjectSchema().description("老師對象屬性")
.addProperty("id", id).addProperty("name", name).addProperty("age", age)
.addProperty("birthday", birthday).addProperty("address", address)
.addProperty("salary", salary).addProperty("fraction", fraction)
.addProperty("likes", likes).addProperty("isHeadmaster", isHeadmaster);
//=====================響應(yīng)字段描述信息(返回類描述)如:AjaxResult=====================
Schema resultSchema = new ObjectSchema().description("響應(yīng)信息對象")
.addProperty("code", new IntegerSchema().example("200").description("響應(yīng)碼"))
.addProperty("msg", new StringSchema().example("成功").description("響應(yīng)信息"))
.addProperty("data", schema);
//設(shè)置響應(yīng)頭信息,可以設(shè)置系統(tǒng)響應(yīng)頭,也可以設(shè)置自定義響應(yīng)頭,具體聲明,前端好獲取指定響應(yīng)頭信息
HashMap<String, Header> headers = new HashMap<>();
headers.put("my-header1", new Header().description("測試響應(yīng)頭1").schema(new StringSchema()));
headers.put("my-header2", new Header().description("測試響應(yīng)頭2").schema(new StringSchema()));
headers.put("my-header3", new Header().description("測試響應(yīng)頭3").schema(new StringSchema()));
// 設(shè)置響應(yīng)信息
ApiResponses apiResponses = new ApiResponses()
.addApiResponse("200", new ApiResponse().description("響應(yīng)成功信息").headers(headers)
.content(new Content().addMediaType("application/json",
new MediaType().schema(resultSchema))))
.addApiResponse("500", new ApiResponse().description("響應(yīng)失敗"));
// 設(shè)置請求信息
RequestBody requestBody = new RequestBody()
.content(new Content().addMediaType("application/json",
new MediaType().schema(schema)));
// 設(shè)置請求URL后綴參數(shù)信息(可以添加多個(gè)) 接口描述
List<Parameter> parameters = new ArrayList<>();
Parameter sign = new Parameter()
.name("sign") // 設(shè)置參數(shù)名稱
.description("URL參數(shù)標(biāo)記信息") // 設(shè)置描述
.required(false) // 是否必傳
.in("path") // 參數(shù)信息參數(shù)位置(當(dāng)前在URL路徑后)
.schema(new StringSchema()) // 參數(shù)類型
.example("tx117839"); // 示例數(shù)據(jù)
parameters.add(sign);
// 設(shè)置當(dāng)前接口描述信息
Operation operation1 = new Operation()
.operationId("addTeacher")
.description("這是一個(gè)添加老師信息的接口")
.requestBody(requestBody)
.parameters(parameters)
.responses(apiResponses);
// 設(shè)置接口路徑信息及請求方式(這里我設(shè)置了一個(gè)post請求的接口)
return new PathItem().post(operation1).description("POST請求");
}
}
接口及模型的描述(使用定義類的方式)
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.Paths;
import org.springframework.boot.SpringBootConfiguration;
import org.springframework.context.annotation.Bean;
/**
* @author Anhui OuYang
* @version 1.0
**/
@SpringBootConfiguration
public class SwaggerOpenApiConfig1 {
/***
* 構(gòu)建Swagger3.0文檔說明
* @return 返回 OpenAPI
*/
@Bean
public OpenAPI customOpenAPI() {
// 配置Info信息 ...
//通過Paths可以配置多組接口信息(Paths接收PathItem,這里的每個(gè)PathItem我抽取方式出去了)
Paths paths = new Paths();
paths.put("根據(jù)傳入的老師信息進(jìn)行數(shù)據(jù)保存", InterfaceDescriptionConfig.addTeacher());
// 返回信息
return new OpenAPI()
.openapi("3.0.1") // Open API 3.0.1(默認(rèn))
.paths(paths)
.info(null); // 配置Swagger3.0描述信息
}
}
接口信息的綁定到Swagger中
6:權(quán)限認(rèn)證方式
其實(shí)我們的接口都是有權(quán)限校驗(yàn)方式的,每個(gè)接口在請求時(shí)都是包含校驗(yàn),如我們常見的JWT校驗(yàn),我們訪問每個(gè)接口都需要攜帶Token信息,下面我就簡單說說校驗(yàn)認(rèn)證的方式描述。
注解權(quán)限設(shè)置:@SecurityScheme (具體參考io.swagger.v3.oas.annotations.security)
說明:用于定義API的安全方案。通過使用@SecurityScheme注解,我們可以為API定義多種安全方案,并指定每種方案的相關(guān)屬性,
例如認(rèn)證類型、授權(quán)URL、令牌URL、作用域等。
常用屬性:
①:name:
安全方案的名稱;
②:type:
認(rèn)證類型,具體包含如下:SecuritySchemeType.API_KEY(API密鑰)、SecuritySchemeType.HTTP(HTTP認(rèn)證)、
SecuritySchemeType.OAUTH2(OAuth2.0 認(rèn)證)等;
③:description:
安全方案的描述信息;
④:in:
僅在使用API密鑰認(rèn)證時(shí)適用,表示API密鑰的位置,包括如下:
ApiKeyLocation.HEADER(HTTP 頭部)、ApiKeyLocation.COOKIE(Cookie)等
⑤:scheme:
僅在使用HTTP認(rèn)證時(shí)適用,表示認(rèn)證方案,例如HTTP Authentication Scheme.Basic(Basic 認(rèn)證);
防止客戶端需要在請求頭部中添加一個(gè)包含用戶名和密碼的 Base64 編碼字符串,并以 "Basic " 開頭,如:
Authorization: Basic YWRtaW46MTIzNDU2
⑥:bearerFormat:
僅在使用 Bearer Token 認(rèn)證時(shí)適用,表示 Bearer Token 的格式;
⑦:flows:
僅在使用OAuth2.0認(rèn)證時(shí)適用,表示OAuth2.0的認(rèn)證流程,包括@OAuthFlows.authorizationCode、
@OAuthFlows.clientCredentials、@OAuthFlows.password 和 @OAuthFlows.implicit等。
示例:(可以在我們自定義的SwaggerOpenApiConfig內(nèi)設(shè)置權(quán)限認(rèn)證)
@SecurityScheme(
name = "JWT-test", // 認(rèn)證方案名稱
type = SecuritySchemeType.HTTP, // 認(rèn)證類型,當(dāng)前為http認(rèn)證
description = "這是一個(gè)認(rèn)證的描述詳細(xì)", // 描述信息
in = SecuritySchemeIn.HEADER, // 代表在http請求頭部
scheme = "bearer", // 認(rèn)證方案,如:Authorization: bearer token信息
bearerFormat = "JWT") // 表示使用 JWT 格式作為 Bearer Token 的格式
比如我添加了一個(gè)名稱為”JWT-test“的驗(yàn)證方式,使用方式存在2種,一種是設(shè)置全部文檔使用這種驗(yàn)證,另一種是某個(gè)接口使用此種校驗(yàn)方式,具體使用如下:
當(dāng)前在自定義的SwaggerOpenApiConfig類上面設(shè)置了兩種權(quán)限校驗(yàn)方式,如下:
@SecurityScheme(
name = "JWT-test", // 認(rèn)證方案名稱
type = SecuritySchemeType.HTTP, // 認(rèn)證類型,當(dāng)前為http認(rèn)證
description = "這是一個(gè)認(rèn)證的描述詳細(xì)", // 描述信息
in = SecuritySchemeIn.HEADER, // 代表在http請求頭部
scheme = "bearer", // 認(rèn)證方案,如:Authorization: bearer token信息
bearerFormat = "JWT") // 表示使用 JWT 格式作為 Bearer Token 的格式
@SecurityScheme(
name = "X-API-KEY",
type = SecuritySchemeType.APIKEY,
description = "這是一個(gè)認(rèn)證的描述詳細(xì)",
in = SecuritySchemeIn.HEADER,
scheme = "bearer")
設(shè)置全部接口描述都有指定的一種校驗(yàn)方式:
在@OpenAPIDefinition注解里的security屬性設(shè)置校驗(yàn)方式
@OpenAPIDefinition(
....
security = @SecurityRequirement(name = "JWT-test")
)
設(shè)置指定接口描述有指定的一種校驗(yàn)方式:
在@Operation注解里的security屬性設(shè)置校驗(yàn)方式
@Operation(
....
security = @SecurityRequirement(name = "JWT-test")
)
三:SpringBoot集成Open API3.0具體運(yùn)行效果
訪問:http://localhost:8888/demo/swagger-ui/index.html
總覽

學(xué)生Controller根據(jù)ID查詢學(xué)生界面

模型定義信息

權(quán)限認(rèn)證(這里我配置兩個(gè)在Swagger配置類上)

以上就是SpringBoot整合Swagger3生成接口文檔的示例代碼的詳細(xì)內(nèi)容,更多關(guān)于SpringBoot Swagger3接口文檔的資料請關(guān)注腳本之家其它相關(guān)文章!
- Springboot整合Swagger3全注解配置(springdoc-openapi-ui)
- SpringBoot整合Swagger3生成接口文檔過程解析
- Springboot整合Swagger2后訪問swagger-ui.html 404報(bào)錯(cuò)問題解決方案
- Springboot整合Swagger2和Swagger3全過程
- springboot整合swagger3和knife4j的詳細(xì)過程
- SpringBoot整合Swagger的方法示例
- SpringBoot整合swagger的操作指南
- SpringBoot整合Swagger接口文檔工具的流程步驟
- SpringBoot整合Swagger教程詳解
- SpringBoot3.x整合swagger的實(shí)現(xiàn)示例
相關(guān)文章
Java代碼實(shí)現(xiàn)簡單酒店管理系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了Java代碼實(shí)現(xiàn)簡單酒店管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-06-06
Idea入門教程之一分鐘創(chuàng)建一個(gè)Java工程
idea作為Java開發(fā)最好用的編寫代碼軟件之一,首先進(jìn)行的就是工程的創(chuàng)建,這篇文章主要給大家介紹了關(guān)于Idea入門教程之一分鐘創(chuàng)建一個(gè)Java工程的相關(guān)資料,文中通過圖文介紹的非常詳細(xì),需要的朋友可以參考下2024-07-07
idea快速找到項(xiàng)目中對應(yīng)的類圖文詳解(包括源碼)
用IDEA開發(fā)Java項(xiàng)目時(shí)經(jīng)常會使用到各種快捷鍵,其中搜索是最常用的之一,下面這篇文章主要給大家介紹了關(guān)于idea如何快速找到項(xiàng)目中對應(yīng)的類(包括源碼)的相關(guān)資料,文中通過圖文介紹的非常詳細(xì),需要的朋友可以參考下2023-06-06
Springboot實(shí)現(xiàn)ENC加密的詳細(xì)流程
在項(xiàng)目開發(fā)過程中,需要配置數(shù)據(jù)庫連接密碼、Redis密碼、網(wǎng)盤上傳的AK/SK等敏感信息,都需要保存在配置文件里,或者配置中心,這些信息如果泄露,還是會造成一定的困擾,下面這篇文章主要給大家介紹了關(guān)于Springboot實(shí)現(xiàn)ENC加密的詳細(xì)流程,需要的朋友可以參考下2023-06-06
java面向?qū)ο笤O(shè)計(jì)原則之迪米特法則分析詳解
這篇文章主要為大家介紹了java面向?qū)ο笤O(shè)計(jì)原則之迪米特法則的示例分析詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,學(xué)有所得2021-10-10
mybatis映射文件操作存儲過程的實(shí)現(xiàn)
本文主要介紹了mybatis映射文件操作存儲過程的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-03-03
容器環(huán)境的JVM內(nèi)存設(shè)置實(shí)踐記錄
Docker和K8S的興起,很多服務(wù)已經(jīng)運(yùn)行在容器環(huán)境,對于java程序,JVM設(shè)置是一個(gè)重要的環(huán)節(jié),這里總結(jié)下我們項(xiàng)目里的最佳實(shí)踐,對容器環(huán)境的JVM內(nèi)存相關(guān)知識感興趣的朋友一起看看吧2022-03-03

