SpringBoot整合Swagger3生成接口文檔的示例代碼
一:前言
Swagger 是一個(gè) RESTful API 的開(kāi)源框架,它的主要目的是幫助開(kāi)發(fā)者設(shè)計(jì)、構(gòu)建、文檔化和測(cè)試 Web API。Swagger 的核心思想是通過(guò)定義和描述 API 的規(guī)范、結(jié)構(gòu)和交互方式,以提高 API 的可讀性、可靠性和易用性,同時(shí)降低 API 開(kāi)發(fā)的難度和開(kāi)發(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公司收購(gòu)。在過(guò)去幾年中,Swagger經(jīng)歷了許多重大的更新和變化,其發(fā)展史大概可以分為以下幾個(gè)階段:
①:Swagger 1.x 階段(2011-2014年)
Swagger最初是一個(gè)簡(jiǎn)單的API文檔生成工具,通過(guò)對(duì)JAX-RS和Jersey注解的支持自動(dòng)生成API文檔,使得API文檔的維護(hù)變得更加容易。
在這個(gè)階段,Swagger還沒(méi)有完全成熟,只能支持基本的API描述和文檔生成。
②:Swagger 2.x 階段(2014-2017年)
在Swagger 2.x階段,Swagger發(fā)生了重大變化。它不再僅僅是一個(gè)文檔生成工具,而是一個(gè)完整的API開(kāi)發(fā)和管理平臺(tái)。Swagger 2.x加入了強(qiáng)大的注解支持,可以描述API的細(xì)節(jié)信息,如請(qǐng)求參數(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基金會(huì)旗下的OpenAPI規(guī)范。這標(biāo)志著Swagger從一款工具演變成為了一個(gè)開(kāi)放且標(biāo)準(zhǔn)的API定義框架。OpenAPI規(guī)范不僅繼承了Swagger 2.x的特性,還提供了更加全面和嚴(yán)格的API定義規(guī)范,并且擴(kuò)展了對(duì)非RESTful API的支持
隨著OpenAPI規(guī)范的普及,越來(lái)越多的API開(kāi)發(fā)者開(kāi)始使用Swagger/OpenAPI來(lái)開(kāi)發(fā)、測(cè)試和文檔化他們的RESTful API?! ?/p>
所以,隨著Linux基金會(huì)旗下的OpenAPI收購(gòu)了Swagger2.x后對(duì)其進(jìn)行了更嚴(yán)格的規(guī)范,又進(jìn)行了各種優(yōu)化,所以我們也可以稱OpenAPI是一個(gè)全新的Swagger3.x,因?yàn)镺penAPI對(duì)其作了更多的優(yōu)化和規(guī)范。
除了上述幾個(gè)主要階段之外,還有一些其他重要的事件和版本,如Swagger UI、Swagger Codegen、SwaggerHub等等。
這些工具和服務(wù)進(jìn)一步擴(kuò)展了Swagger的功能,使其成為了一個(gè)更加完整、強(qiáng)大和易于使用的API定義和管理平臺(tái)。
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)和特征,支持自動(dòng)生成文檔、客戶端與服務(wù)端代碼、Mock Server和測(cè)試工具等。
OpenAPI規(guī)范最初由開(kāi)發(fā)Swagger的團(tuán)隊(duì)在2010年推出,從Swagger 2.0開(kāi)始,Swagger規(guī)范被正式更名為OpenAPI規(guī)范,并得到了許多社區(qū)的支持和貢獻(xiàn)。OpenAPI規(guī)范采用JSON或YAML格式編寫,并支持多種數(shù)據(jù)類型,可以描述API的基本信息、路徑、HTTP方法、參數(shù)、響應(yīng)等各種細(xì)節(jié)。通過(guò)遵循OpenAPI規(guī)范,開(kāi)發(fā)者可以快速定義和構(gòu)建RESTful API,并且可以生成相應(yīng)的文檔和代碼來(lái)幫助他們更快地開(kāi)發(fā)與測(cè)試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ī)范的版本號(hào)進(jìn)行了更新。因此,Swagger 3.0對(duì)應(yīng)的就是OpenAPI 3.0版本,它是Swagger在OpenAPI階段推出的一個(gè)重要版本。與前幾個(gè)版本相比,Swagger 3.0更加強(qiáng)調(diào)對(duì)RESTful API的支持和規(guī)范化,提供了更豐富和靈活的定義方式,并且可以用于自動(dòng)生成文檔、客戶端代碼、服務(wù)器代碼和測(cè)試工具等。
3:SpringFox工具(不推薦)
Springfox是一套可以幫助Java開(kāi)發(fā)者自動(dòng)生成API文檔的工具,它是基于Swagger 2.x基礎(chǔ)上開(kāi)發(fā)的。Swagger已經(jīng)成為了RESTful API文檔生態(tài)系統(tǒng)的事實(shí)標(biāo)準(zhǔn),而Springfox是一個(gè)用于集成Swagger2.x到Spring應(yīng)用程序中的庫(kù)。而且Springfox提供了一些注解來(lái)描述API接口、參數(shù)和返回值,并根據(jù)這些信息生成Swagger UI界面,從而方便其他開(kāi)發(fā)人員查看和使用您的API接口。此外,Springfox還支持自動(dòng)生成API文檔和代碼片段,簡(jiǎn)化了開(kāi)發(fā)人員的工作量。除了集成Swagger 2.x,Springfox還提供了一些額外功能,例如自定義Swagger文檔、API版本控制、請(qǐng)求驗(yàn)證等等。這些功能使得Springfox可以勝任各種類型和規(guī)模的應(yīng)用程序,同時(shí)還可以提高代碼質(zhì)量和開(kāi)發(fā)效率??傊?,Springfox是一個(gè)非常有用的工具,它可以幫助Java開(kāi)發(fā)者快速、簡(jiǎn)單地集成Swagger2.x,并為他們的應(yīng)用程序生成高質(zhì)量的API文檔。無(wú)論您開(kāi)發(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日)開(kāi)始就一直沒(méi)有更新;也得注意的是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對(duì)應(yīng)坐標(biāo)是springdoc-openapi-ui,它是一個(gè)集成Swagger UI和ReDoc的接口文檔生成工具,在使用上與springfox-boot-starter類似,但提供了更為靈活、功能更加強(qiáng)大的工具。其中除了可以生成Swagger UI風(fēng)格的接口文檔,還提供了ReDoc的文檔渲染方式,可以自動(dòng)注入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庫(kù)來(lái)集成Swagger3.x。在這些版本中,springdoc-openapi-ui庫(kù)已被廣泛應(yīng)用,并且得到了社區(qū)的大力支持和推廣。而在Spring Boot 2.3及其以下版本,可以使用springfox-boot-starter庫(kù)來(lái)集成Swagger2.x。
SpringDoc是有著更加先進(jìn)的技術(shù)架構(gòu)和更好的擴(kuò)展性,使得其逐漸取代了springfox-boot-starter工具包,成為了當(dāng)前Spring Boot生態(tài)中最受歡迎的API文檔工具之一。同時(shí)springdoc-openapi-ui還擁有更為完善的開(kāi)發(fā)文檔和社區(qū)支持,從而吸引了越來(lái)越多的開(kāi)發(fā)者加入到這個(gè)項(xiàng)目中。因此作為一個(gè)Spring Boot開(kāi)發(fā)者,如果想要快速、方便地生成符合OpenAPI 3.0規(guī)范的接口文檔,建議使用springdoc-openapi-ui這個(gè)優(yōu)秀的工具。
二:SpringBoot集成Open API 3.0(Swagger3.0)
我們?cè)赟pringBoot中想集成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)它提供了一組注解和工具來(lái)集成Swagger UI和OpenAPI規(guī)范等--> <dependency> <groupId>org.springdoc</groupId> <artifactId>springdoc-openapi-ui</artifactId> <version>1.7.0</version> </dependency> 說(shuō)明:上面的坐標(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注解庫(kù),提供了一組注解,用于描述API元數(shù)據(jù)。 例如,@Operation、@Parameter、@ApiResponse等注解基本包含了OpenAPI規(guī)范中的所有元素。 ③:io.swagger.core.v3:swagger-models:2.2.9 Swagger Models是Swagger 3.x規(guī)范的Java模型庫(kù),提供了一組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配置類對(duì)象方式
其實(shí)我們通過(guò)配置類的方式創(chuàng)建一個(gè)OpenAPI的Bean對(duì)象就可以創(chuàng)建Swagger3.0的文檔說(shuō)明,下面我就直創(chuàng)建。
OpenAPI對(duì)象是Swagger中的核心類之一,用于描述整個(gè)API的結(jié)構(gòu)和元數(shù)據(jù)。可以理解為一個(gè)API文檔對(duì)象,其中包含了許多元素,如: ①:openapi屬性: 表示使用的 OpenAPI 規(guī)范版本(例如 3.0.1)。 ②:info屬性: 表示API的基本信息,包括標(biāo)題、版本號(hào)、描述、聯(lián)系人等。使用Info類來(lái)創(chuàng)建這個(gè)對(duì)象。 ③:servers屬性: 表示服務(wù)器地址或者URL模板列表。每個(gè)URL模板可以包含占位符,這些占位符可以被路徑參數(shù)或者查詢參數(shù)替換。 使用Server類來(lái)創(chuàng)建這個(gè)對(duì)象。 ④:paths屬性(推薦使用注解方式,不推薦使用配置類配置): 表示API的所有路徑和操作信息,使用PathItem類來(lái)描述每一個(gè)路徑,使用Operation類來(lái)描述操作。 ⑤:components屬性: 表示API的組件信息,比如響應(yīng)模板、請(qǐng)求模板和安全方案等。 使用Schema、Response、Parameter、SecurityScheme等類來(lái)創(chuàng)建這些對(duì)象。 ⑥:tags屬性: 表示API的標(biāo)簽信息,用于對(duì)相似的操作進(jìn)行分組。 ⑦:addServersItem(Server server)方法: 向servers屬性中添加一個(gè)Server對(duì)象。 ⑧:addPaths(String name, PathItem pathItem)方法: 向paths屬性中添加一個(gè)PathItem對(duì)象,其中name參數(shù)表示路徑模板。 ⑨:addTag(Tag tag)方法: 向tags屬性中添加一個(gè)Tag對(duì)象。 ⑩: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文檔說(shuō)明 * @return 返回 OpenAPI */ @Bean public OpenAPI customOpenAPI() { // 聯(lián)系人信息(contact),構(gòu)建API的聯(lián)系人信息,用于描述API開(kāi)發(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的開(kāi)源標(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)識(shí)授權(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框架而用來(lái)定義測(cè)試的文檔") // 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í)這種寫起來(lái)感覺(jué)還行,但是在使用了注解方式是很舒服的,下面就簡(jiǎn)單說(shuō)明:
定義Swagger3.0配置信息注解:@OpenAPIDefinition (具體參考 io.swagger.v3.oas.annotations)注意:這個(gè)注解全局只能配置一個(gè),主要配置文檔信息和安全配置 說(shuō)明:用于描述整個(gè)API的元信息和全局屬性,可以定義和描述,包括API版本、基本信息、服務(wù)器信息、安全方案等 常用屬性: ①:info:用于描述 API 基本信息的對(duì)象,包括標(biāo)題、版本號(hào)、描述等屬性; ②:servers:用于描述 API 服務(wù)的 URL 和配置信息的數(shù)組; ③:security:用于描述 API 安全方案的數(shù)組,其中每個(gè)安全方案包含多個(gè)安全需求; ④:tags:用于描述 API 標(biāo)簽的數(shù)組,每個(gè)標(biāo)簽包含名稱、描述等屬性; ⑤:externalDocs:用于描述外部文檔鏈接的對(duì)象,包含描述和 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)題、版本號(hào)、描述、聯(lián)系人等 info = @Info( title = "Swagger3.0 (Open API) 框架學(xué)習(xí)示例文檔", // Api接口文檔標(biāo)題(必填) description = "學(xué)習(xí)Swagger框架而用來(lái)定義測(cè)試的文檔", // 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í)切換(只不過(guò)是有多臺(tái)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)容請(qǐng)查看該鏈接", url = "xxx")) public class SwaggerOpenApiConfig { }
4:配置API接口信息(注解,重要)
說(shuō)了這么久,Swagger3.0的全局基本信息配置是處理好了,接下來(lái)就是配置接口了,因?yàn)槲抑皩懥薈ontroller代碼,但是沒(méi)有接口配置信息,這里我就使用Swagger的方式進(jìn)行一個(gè)簡(jiǎn)單的配置。
示例代碼,不是太明白屬性的可以看下面屬性介紹
// 響應(yīng)對(duì)象模型定義 @Data @AllArgsConstructor @Schema(description = "響應(yīng)返回?cái)?shù)據(jù)對(duì)象") 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é)生愛(ài)好", description = "學(xué)生愛(ài)好屬性(List類型)", type = "array", example = "[\"玩\", \"寫字\"]") private List<String> likes; // 學(xué)生愛(ài)好 }
// 接口定義 @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 可以用于對(duì)接口進(jìn)行分類和歸類,便于開(kāi)發(fā)人員組織和管理 API 文檔 具體屬性: ①:name:表示標(biāo)簽的名稱,必填屬性,也得注意多個(gè)Controller上的name不要寫一樣的,這樣就會(huì)把它們歸類在一起。 ②:description:表示標(biāo)簽的描述信息,非必填屬性。 ③:externalDocs:用于指定URL地址文檔信息來(lái)追加描述接口的信息。非必填屬性。 示例: @Tag( name = "StudentControllerAPI", description = "學(xué)生控制器接口", externalDocs = @ExternalDocumentation( description = "這是一個(gè)接口文檔介紹", url = "https://www.cnblogs.com/antLaddie/"))
配置文檔下的每一個(gè)接口信息,就是Controller里的每一個(gè)RequestMapping
注解:@Operation用于對(duì)API操作(即方法)進(jìn)行描述和標(biāo)記。就是我們熟知的Controller下的一個(gè)個(gè)請(qǐng)求的方法上。 具體可以參考 io.swagger.v3.oas.annotations。 具體屬性: ①:summary:用于簡(jiǎn)要描述API操作的概要。 ②:description:用于詳細(xì)描述API操作的描述信息。 ③:parameters:用于指定API操作的參數(shù)列表,包括路徑參數(shù)、請(qǐng)求參數(shù)、請(qǐng)求頭部等??梢允褂聾Parameter注解進(jìn)一步定義參數(shù)。 ④:operationId:用于指定API操作的唯一標(biāo)識(shí)符,可以用于生成客戶端代碼或文檔等。 說(shuō)明:第三方工具使用operationId來(lái)唯一標(biāo)識(shí)此操作。(具體我也沒(méi)用過(guò)) ⑤:requestBody:用于定義API操作的請(qǐng)求體,可以使用@RequestBody注解進(jìn)一步定義請(qǐng)求體。 說(shuō)明:這里的@RequestBody注解是@io.swagger.v3.oas.annotations.parameters.RequestBody包里的 ⑥:responses:用于定義 API 操作的響應(yīng)列表,包括成功響應(yīng)和錯(cuò)誤響應(yīng)。可以使用@ApiResponse注解進(jìn)一步定義響應(yīng)。 ⑦:security:用于對(duì)API操作進(jìn)行安全控制,可以使用@SecurityRequirement注解進(jìn)一步定義安全需求。(后面說(shuō)) ⑧:deprecated:表示該API操作已經(jīng)過(guò)時(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}) ) ) } )
配置請(qǐng)求接口參數(shù)信息
注解:@Parameter用于描述HTTP請(qǐng)求的參數(shù)信息,它是一個(gè)Parameter[]類型的數(shù)組,每個(gè)元素表示一個(gè)請(qǐng)求參數(shù); 具體參考:io.swagger.v3.oas.annotations;它是一個(gè)注解,和Parameter類一樣,只不過(guò)一個(gè)是注解一個(gè)是類的方式 ①:name:參數(shù)名稱。 ②:in:參數(shù)位置,可以是 query、header、path、cookie 等。 ③:description:參數(shù)描述。 ④:required:參數(shù)是否必須,默認(rèn)為 false。 ⑤:deprecated:參數(shù)是否已過(guò)時(shí),默認(rèn)為 false。 ⑥:allowEmptyValue:是否允許空值,默認(rèn)為false。 ⑦:style:參數(shù)的序列化風(fēng)格,可以是 "matrix"、"label"、"form"、"simple"、 "spaceDelimited"、"pipeDelimited"、"deepObject"; ⑧:explode:當(dāng)參數(shù)值是對(duì)象或數(shù)組時(shí),是否將其展開(kāi)成多個(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:指定屬性名。該屬性只對(duì)屬性有效,對(duì)類無(wú)效。 ③:title:用于顯示在生成的文檔中的標(biāo)題。 ④:requiredMode:用于指定該屬性是否必填項(xiàng)。枚舉Schema.RequiredMode內(nèi)可選值如下: 默認(rèn)AUTO:可有可無(wú);REQUIRED:必須存在此字段(會(huì)加紅色*);NOT_REQUIRED:不需要存在此字段 ⑤:accessMode:用于指定該屬性的訪問(wèn)方式。 包括AccessMode.READ_ONLY(只讀)、AccessMode.WRITE_ONLY(只寫)、AccessMode.READ_WRITE(讀寫) ⑥:format:用于指定該屬性的數(shù)據(jù)格式。例如:日期格式、時(shí)間格式、數(shù)字格式。 ⑦:example:為當(dāng)前的屬性創(chuàng)建一個(gè)示例的值,后期測(cè)試可以使用此值。 ⑧:deprecated:用于指定該屬性是否為已過(guò)時(shí)的屬性,默認(rèn)為false。 ⑨:defaultValue:用于指定該屬性的默認(rèn)值。 ⑩:implementation:用于顯示為該類或?qū)傩砸刖唧w的實(shí)體路徑,這代表當(dāng)前指定的類或者屬性將參考引入的實(shí)體。 就是說(shuō)有個(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。對(duì)于數(shù)組類型,還可以使用 schema 屬性指定其元素類型的 Schema 信息。 對(duì)象類型:不用指定type,可以通過(guò)implementation屬性引入。 枚舉類型:取值為enum。對(duì)于枚舉類型,還需要使用enumAsRef屬性指定是否將其定義為一個(gè)獨(dú)立的引用類型。 其它類型:不用指定type,可以通過(guò)implementation屬性引入。 @Schema注解:提供了四個(gè)屬性來(lái)描述復(fù)雜類型,分別是allOf、anyOf、oneOf和not。 這四個(gè)屬性可以用于組合不同的JSON Schema以描述一個(gè)復(fù)雜類型,具體如下: ①:allOf: 表示當(dāng)前schema是多個(gè)其它schema的并集。 例如,如果一個(gè)Java類型同時(shí)實(shí)現(xiàn)了兩個(gè)接口,那么可以使用allOf來(lái)表示這個(gè)Java類型繼承了這兩個(gè)接口的所有屬性和方法。 ②:anyOf: 表示當(dāng)前schema可以匹配其中任意一個(gè)schema,其本身也是一個(gè)組合體,可以嵌套使用。 例如,一個(gè)返回類型可能是多個(gè)Java類型中的任意一個(gè),可以使用anyOf來(lái)描述這種情況。 ③:oneOf: 表示當(dāng)前schema只能匹配其中一個(gè)schema,其本身也是一個(gè)組合體,可以嵌套使用。 例如,一個(gè)Java類型只能是多個(gè)子類型中的任意一個(gè),可以使用oneOf來(lái)描述這種情況。 ④:not: 表示當(dāng)前Schema不能匹配某個(gè)schema。 例如,一個(gè)Java類型不能是某個(gè)子類型,可以使用not來(lái)描述這種情況。 但是總感覺(jué)這個(gè)Swagger無(wú)法滿足我特定要求的實(shí)體,具體解決如下: 比如我現(xiàn)在有個(gè)AjaxResult類(code,msg,data),其中data為Object或其它類型,這時(shí)我返回的數(shù)據(jù)里data為其它類型的 實(shí)體,所以我這里不理解如何返回的實(shí)體中,通過(guò)點(diǎn)擊data而顯示另外實(shí)體,我只能通過(guò)anyOf方式來(lái)實(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接口信息(定義類方式,不推薦)
上面介紹了使用注解的方式完成接口的說(shuō)明,這里我來(lái)說(shuō)說(shuō)定義類的方式來(lái)完成接口的定義,其實(shí)這種方式不推薦,寫起來(lái)繁瑣麻煩,后期改起來(lái)也亂,但是還是說(shuō)下,下面就是具體的代碼信息接口及模型的描述(使用定義類的方式)
/** * 老師接口描述 * * @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("老師評(píng)分"); Schema likes = new ArraySchema().minItems(1).maxItems(10).description("這是一個(gè)愛(ài)好數(shù)組"); Schema isHeadmaster = new BooleanSchema().example(true).description("是否是班主任"); Schema schema = new ObjectSchema().description("老師對(duì)象屬性") .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)信息對(duì)象") .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("測(cè)試響應(yīng)頭1").schema(new StringSchema())); headers.put("my-header2", new Header().description("測(cè)試響應(yīng)頭2").schema(new StringSchema())); headers.put("my-header3", new Header().description("測(cè)試響應(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è)置請(qǐng)求信息 RequestBody requestBody = new RequestBody() .content(new Content().addMediaType("application/json", new MediaType().schema(schema))); // 設(shè)置請(qǐng)求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è)置接口路徑信息及請(qǐng)求方式(這里我設(shè)置了一個(gè)post請(qǐng)求的接口) return new PathItem().post(operation1).description("POST請(qǐng)求"); } } 接口及模型的描述(使用定義類的方式)
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文檔說(shuō)明 * @return 返回 OpenAPI */ @Bean public OpenAPI customOpenAPI() { // 配置Info信息 ... //通過(guò)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è)接口在請(qǐng)求時(shí)都是包含校驗(yàn),如我們常見(jiàn)的JWT校驗(yàn),我們?cè)L問(wèn)每個(gè)接口都需要攜帶Token信息,下面我就簡(jiǎn)單說(shuō)說(shuō)校驗(yàn)認(rèn)證的方式描述。
注解權(quán)限設(shè)置:@SecurityScheme (具體參考io.swagger.v3.oas.annotations.security) 說(shuō)明:用于定義API的安全方案。通過(guò)使用@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)證); 防止客戶端需要在請(qǐng)求頭部中添加一個(gè)包含用戶名和密碼的 Base64 編碼字符串,并以 "Basic " 開(kāi)頭,如: 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請(qǐng)求頭部 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請(qǐng)求頭部 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)行效果
訪問(wè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接口文檔的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Java中的@RequiredArgsConstructor注解詳解
這篇文章主要介紹了Java中的@RequiredArgsConstructor注解詳解,@RequiredArgsConstructor是Lombok的一個(gè)注解,簡(jiǎn)化了我們對(duì)@Autowired書寫,@RequiredArgsConstructor注解可以代替@Autowired注解,需要的朋友可以參考下2024-01-01java list,set,map,數(shù)組間的相互轉(zhuǎn)換詳解
這篇文章主要介紹了java list,set,map,數(shù)組間的相互轉(zhuǎn)換詳解的相關(guān)資料,這里附有實(shí)例代碼,具有參考價(jià)值,需要的朋友可以參考下2017-01-01Java開(kāi)發(fā)druid數(shù)據(jù)連接池maven方式簡(jiǎn)易配置流程示例
本篇文章主要為大家介紹了java開(kāi)發(fā)中druid數(shù)據(jù)連接池maven方式的簡(jiǎn)易配置流程示例,文中附含詳細(xì)的代碼示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助2021-10-10Spring需要三個(gè)級(jí)別緩存解決循環(huán)依賴原理解析
這篇文章主要為大家介紹了Spring需要三個(gè)級(jí)別緩存解決循環(huán)依賴原理解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-02-02spring boot 下支付寶的開(kāi)箱既用環(huán)境
這篇文章主要介紹了spring boot 下支付寶的開(kāi)箱既用環(huán)境包括使用場(chǎng)景和使用技巧,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友參考下吧2017-10-10Java負(fù)載均衡服務(wù)器實(shí)現(xiàn)上傳文件同步
這篇文章主要介紹了Java負(fù)載均衡服務(wù)器實(shí)現(xiàn)上傳文件同步,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-09-09