Swagger 全量注解應(yīng)用指南:從@Tag到@SecurityScheme,全面掌握API設(shè)計(jì)
本文是Swagger注解的完整參考指南,詳細(xì)解析了6大類40+個(gè)核心注解的使用方法和實(shí)戰(zhàn)場(chǎng)景。從基礎(chǔ)的@Tag、@Operation到高級(jí)的@SecurityScheme、@Callback,每個(gè)注解都配有清晰的代碼示例和實(shí)際應(yīng)用案例。包含全局配置、多安全方案、復(fù)雜響應(yīng)結(jié)構(gòu)、Webhook回調(diào)等企業(yè)級(jí)場(chǎng)景,幫助你構(gòu)建專業(yè)級(jí)的API文檔系統(tǒng)。
一、注解介紹
1. API 基本信息與分組注解
這些注解用于描述整個(gè)API或?qū)涌谶M(jìn)行分組,通常用在控制器類上。
注解 | 適用范圍 | 屬性 | 說(shuō)明 | 示例 |
| 類 |
: (必填) 標(biāo)簽名稱。 | 用于對(duì)API操作進(jìn)行邏輯分組。一個(gè)控制器可以有多個(gè)標(biāo)簽。在Swagger UI中顯示為不同的分類。 |
|
| 類、方法 | 無(wú) | 隱藏 被注解的類或方法,不會(huì)出現(xiàn)在生成的API文檔中。 |
|
2. 接口操作注解 (Operation Annotations)
這些注解用于描述具體的HTTP接口,用在控制器方法上。
注解 | 適用范圍 | 屬性 | 說(shuō)明 | 示例 |
| 方法 |
:操作摘要。 | 描述一個(gè)HTTP請(qǐng)求操作(如一個(gè)GET或POST端點(diǎn)),是方法上最重要的注解。 |
|
| 方法 |
: (必填) HTTP狀態(tài)碼,如 "200", "404"。 | 聲明一個(gè)操作可能返回的響應(yīng)。通常與 |
|
| 方法 |
:一個(gè) | 當(dāng)需要聲明多個(gè)響應(yīng)時(shí),用它來(lái)包裹多個(gè) |
|
| 方法 |
:回調(diào)名稱。 | 描述一個(gè)回調(diào)操作,用于Webhooks等異步通知場(chǎng)景,使用相對(duì)較少。 | (略復(fù)雜,此處不展開(kāi)示例) |
3. 參數(shù)注解 (Parameter Annotations)
這些注解用于描述接口的入?yún)?,可以用在方法參?shù)上。
注解 | 適用范圍 | 屬性 | 說(shuō)明 | 示例 |
| 參數(shù) |
:參數(shù)描述。 | 描述一個(gè)操作參數(shù),如 |
|
| 方法 |
:一個(gè) | 當(dāng)需要在方法上為多個(gè)參數(shù)添加描述時(shí),用它來(lái)包裹多個(gè) |
|
| 參數(shù) | 與 | 它是 |
|
4. 請(qǐng)求體與內(nèi)容注解 (Request Body & Content)
這些注解用于描述復(fù)雜的請(qǐng)求或響應(yīng)內(nèi)容。
注解 | 適用范圍 | 屬性 | 說(shuō)明 | 示例 |
| 參數(shù) |
:請(qǐng)求體的描述。 | 專門(mén)用于描述 。提供對(duì)請(qǐng)求體的詳細(xì)說(shuō)明。 |
|
| 與 |
:指定內(nèi)容的schema(使用 | 定義請(qǐng)求或響應(yīng)體的媒體類型和結(jié)構(gòu)。 |
|
| 模型類 、模型屬性、參數(shù) |
:描述。 | 這是最重要的模型注解 。用于描述DTO(數(shù)據(jù)傳輸對(duì)象)、VO(值對(duì)象)等模型,或修飾 |
|
5. 安全方案注解 (Security Annotations)
用于描述API的認(rèn)證和授權(quán)方式。
注解 | 適用范圍 | 屬性 | 說(shuō)明 | 示例 |
| 類 (配置類) |
:安全方案類型(如 | 在配置類中定義全局的安全方案 ,如JWT、OAuth2、ApiKey等。 | 見(jiàn)下方配置示例 |
| 類 、方法 |
:引用的安全方案名稱。 | 聲明一個(gè)操作或整個(gè)控制器需要哪些安全方案。在Swagger UI中會(huì)出現(xiàn)Authorize按鈕。 |
|
安全配置示例:
@Configuration
@SecurityScheme( // 定義安全方案
name = "bearerAuth",
type = SecurityScheme.Type.HTTP,
scheme = "bearer",
bearerFormat = "JWT"
)
publicclass OpenApiConfig {}
@RestController
@SecurityRequirement(name = "bearerAuth") // 整個(gè)控制器都需要認(rèn)證
@Tag(name = "Secure API")
class SecureController {
@GetMapping("/secure")
public String secureEndpoint() {
return"This is secure!";
}
}二、swagger注解使用案例
1. 全局配置類 (OpenAPIConfig.java)
package com.example.config;
import io.swagger.v3.oas.annotations.enums.SecuritySchemeType;
import io.swagger.v3.oas.annotations.security.SecurityScheme;
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 org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
@SecurityScheme( // 定義全局安全方案
name = "bearerAuth",
type = SecuritySchemeType.HTTP,
scheme = "bearer",
bearerFormat = "JWT",
description = "JWT認(rèn)證令牌,格式: Bearer {token}"
)
publicclass OpenAPIConfig {
@Bean
public OpenAPI customOpenAPI() {
returnnew OpenAPI()
.info(new Info()
.title("企業(yè)級(jí)應(yīng)用API文檔")
.version("1.0.0")
.description("""
這是企業(yè)級(jí)應(yīng)用的完整API文檔,包含:
- 用戶管理系統(tǒng)
- 電商訂單系統(tǒng)
- 文件服務(wù)系統(tǒng)
""")
.contact(new Contact()
.name("技術(shù)支持")
.email("support@company.com")
.url("https://support.company.com"))
.license(new License()
.name("Apache 2.0")
.url("https://www.apache.org/licenses/LICENSE-2.0")))
.addSecurityItem(new SecurityRequirement().addList("bearerAuth")); // 全局安全要求
}
}2. 安全配置類
@Configuration
@SecuritySchemes({ // 使用 @SecuritySchemes 包裹多個(gè) @SecurityScheme
@SecurityScheme(
name = "JWT",
type = SecuritySchemeType.HTTP,
scheme = "bearer",
bearerFormat = "JWT",
description = "JWT認(rèn)證令牌"
),
@SecurityScheme(
name = "APIKey",
type = SecuritySchemeType.APIKEY,
in = SecuritySchemeIn.HEADER,
paramName = "X-API-KEY",
description = "API密鑰認(rèn)證"
),
@SecurityScheme(
name = "OAuth2",
type = SecuritySchemeType.OAUTH2,
flows = @OAuthFlows( // 使用 @OAuthFlows 和 @OAuthFlow
authorizationCode = @OAuthFlow(
authorizationUrl = "https://example.com/oauth/authorize",
tokenUrl = "https://example.com/oauth/token",
scopes = {
@OAuthScope(name = "read", description = "讀取權(quán)限"),
@OAuthScope(name = "write", description = "寫(xiě)入權(quán)限")
}
)
)
),
@SecurityScheme(
name = "BasicAuth",
type = SecuritySchemeType.HTTP,
scheme = "basic",
description = "基礎(chǔ)認(rèn)證"
)
})
publicclass SecurityConfig {
}3. 控制器
@RestController
@RequestMapping("/api/v1/comprehensive")
@Tag(name = "綜合演示API", description = "展示所有Swagger注解的用法")
@SecurityRequirement(name = "JWT")
publicclass ComprehensiveController {
// 1. 演示所有參數(shù)類型
@PostMapping("/all-params/{pathVar}")
@Operation(summary = "所有參數(shù)類型演示")
@Parameters({
@Parameter(name = "pathVar", description = "路徑參數(shù)", in = ParameterIn.PATH, example = "123"),
@Parameter(name = "queryParam", description = "查詢參數(shù)", in = ParameterIn.QUERY, example = "value"),
@Parameter(name = "X-Custom-Header", description = "頭部參數(shù)", in = ParameterIn.HEADER, example = "header-value"),
@Parameter(name = "sessionId", description = "Cookie參數(shù)", in = ParameterIn.COOKIE, example = "session-123")
})
public ResponseEntity<String> allParameterTypes(
@PathVariable String pathVar,
@RequestParam String queryParam,
@RequestHeader("X-Custom-Header") String customHeader,
@CookieValue("sessionId") String sessionId) {
return ResponseEntity.ok("Success");
}
// 2. 演示數(shù)組和復(fù)雜Schema
@PostMapping("/batch-create")
@Operation(summary = "批量創(chuàng)建項(xiàng)目")
public ResponseEntity<String> batchCreate(
@io.swagger.v3.oas.annotations.parameters.RequestBody(
description = "批量創(chuàng)建請(qǐng)求",
content = @Content(
mediaType = "application/json",
array = @ArraySchema( // 使用 @ArraySchema
schema = @Schema(implementation = User.class),
minItems = 1,
maxItems = 100
),
examples = @ExampleObject(
value = """
[
{"username": "user1", "email": "user1@example.com"},
{"username": "user2", "email": "user2@example.com"}
]
"""
)
)
)
@RequestBody List<@Valid User> users) {
return ResponseEntity.ok("Batch created");
}
// 3. 演示多安全方案
@GetMapping("/sensitive-data")
@Operation(summary = "獲取敏感數(shù)據(jù)")
@SecurityRequirement(name = "JWT") // 方法級(jí)別安全要求
@SecurityRequirement(name = "APIKey") // 多個(gè)安全要求
public ResponseEntity<Map<String, String>> getSensitiveData() {
return ResponseEntity.ok(Map.of("data", "sensitive information"));
}
// 4. 演示復(fù)雜響應(yīng)
@GetMapping("/complex-response")
@Operation(summary = "復(fù)雜響應(yīng)結(jié)構(gòu)")
@ApiResponses({
@ApiResponse(
responseCode = "200",
description = "成功響應(yīng)",
content = {
@Content(
mediaType = "application/json",
schema = @Schema(implementation = ComplexResponse.class),
examples = {
@ExampleObject(
name = "success_example",
summary = "成功示例",
value = """
{
"status": "SUCCESS",
"data": {
"users": [
{"id": 1, "name": "John"},
{"id": 2, "name": "Jane"}
],
"metadata": {
"page": 1,
"total": 2
}
}
}
"""
),
@ExampleObject(
name = "error_example",
summary = "錯(cuò)誤示例",
value = """
{
"status": "ERROR",
"message": "數(shù)據(jù)不存在"
}
"""
)
}
),
@Content(
mediaType = "application/xml",
schema = @Schema(implementation = ComplexResponse.class)
)
}
),
@ApiResponse(
responseCode = "403",
description = "權(quán)限不足",
content = @Content(schema = @Schema(implementation = ErrorResponse.class))
)
})
public ResponseEntity<ComplexResponse> getComplexResponse() {
return ResponseEntity.ok(new ComplexResponse());
}
// 5. 演示隱藏特定端點(diǎn)
@GetMapping("/internal/stats")
@io.swagger.v3.oas.annotations.Hidden // 隱藏內(nèi)部端點(diǎn)
public ResponseEntity<String> getInternalStats() {
return ResponseEntity.ok("Internal statistics");
}
}4. 模型類
@Data
@Schema(
description = "用戶實(shí)體",
requiredProperties = {"username", "email"}, // 必需屬性
accessMode = Schema.AccessMode.READ_WRITE
)
publicclass User {
@Schema(
description = "用戶ID",
example = "1",
accessMode = Schema.AccessMode.READ_ONLY,
minimum = "1"
)
private Long id;
@Schema(
description = "用戶名",
example = "john_doe",
minLength = 3,
maxLength = 50,
pattern = "^[a-zA-Z0-9_]+$"
)
private String username;
@Schema(
description = "郵箱地址",
example = "john@example.com",
format = "email",
maxLength = 100
)
private String email;
@Schema(
description = "用戶年齡",
example = "25",
minimum = "0",
maximum = "150",
exclusiveMinimum = true,
exclusiveMaximum = true
)
private Integer age;
@Schema(
description = "用戶狀態(tài)",
example = "ACTIVE",
allowableValues = {"ACTIVE", "INACTIVE", "SUSPENDED"},
defaultValue = "ACTIVE"
)
private String status;
@Schema(
description = "標(biāo)簽列表",
example = "["vip", "new_user"]",
maxItems = 10
)
private List<String> tags;
@Schema(
description = "元數(shù)據(jù)",
example = "{"key": "value"}",
additionalProperties = Schema.AdditionalPropertiesValue.TRUE
)
private Map<String, Object> metadata;
@Schema(
description = "創(chuàng)建時(shí)間",
example = "2023-10-01T12:00:00",
accessMode = Schema.AccessMode.READ_ONLY
)
private LocalDateTime createdAt;
}
@Data
@Schema(description = "復(fù)雜響應(yīng)結(jié)構(gòu)")
class ComplexResponse {
@Schema(
description = "響應(yīng)狀態(tài)",
example = "SUCCESS",
allowableValues = {"SUCCESS", "ERROR"}
)
private String status;
@Schema(
description = "響應(yīng)數(shù)據(jù)",
oneOf = {User.class, Product.class} // 使用 oneOf
)
private Object data;
@Schema(
description = "分頁(yè)信息",
allOf = {Pagination.class} // 使用 allOf
)
private Object pagination;
}
@Data
@Schema(description = "分頁(yè)信息")
class Pagination {
@Schema(description = "當(dāng)前頁(yè)碼", example = "1")
privateint page;
@Schema(description = "每頁(yè)大小", example = "20")
privateint size;
@Schema(description = "總記錄數(shù)", example = "100")
privatelong total;
}
@Data
@Schema(description = "錯(cuò)誤響應(yīng)")
class ErrorResponse {
@Schema(description = "錯(cuò)誤代碼", example = "403")
privateint code;
@Schema(description = "錯(cuò)誤信息", example = "權(quán)限不足")
private String message;
@Schema(description = "時(shí)間戳", example = "2023-10-01T12:00:00")
private LocalDateTime timestamp;
}5. 回調(diào)控制器
@RestController
@RequestMapping("/api/v1/webhook")
@Tag(name = "Webhook管理", description = "Webhook回調(diào)接口")
publicclass WebhookController {
@PostMapping("/subscribe")
@Operation(summary = "訂閱Webhook")
@Callbacks({
@Callback(
name = "onEvent",
callbackUrlExpression = "http://localhost:8080/api/v1/webhook/event",
operation = @Operation(
method = "POST",
description = "事件回調(diào)",
requestBody = @io.swagger.v3.oas.annotations.parameters.RequestBody(
content = @Content(
schema = @Schema(implementation = WebhookEvent.class)
)
),
responses = @ApiResponse(
responseCode = "200",
description = "回調(diào)處理成功"
)
)
)
})
public String subscribeWebhook() {
return"Subscription created";
}
}
@Schema(description = "Webhook事件")
class WebhookEvent {
@Schema(description = "事件類型", example = "user.created")
private String type;
@Schema(description = "事件數(shù)據(jù)")
private Object data;
@Schema(description = "時(shí)間戳", example = "2023-10-01T12:00:00")
private String timestamp;
}6. Swagger注解總結(jié)
這個(gè)完整的案例包含了所有核心的Swagger注解:
6.1. 基本信息與分組
- @Tag - API分組
- @Hidden - 隱藏API
6.2. 接口操作
- @Operation - 操作描述
- @ApiResponse - 單個(gè)響應(yīng)
- @ApiResponses - 多個(gè)響應(yīng)
- @Callback / @Callbacks - 回調(diào)操作
6.3. 參數(shù)描述
- @Parameter - 參數(shù)描述
- @Parameters - 多個(gè)參數(shù)
- 所有 in 類型:PATH, QUERY, HEADER, COOKIE
6.4. 請(qǐng)求體與內(nèi)容
- @RequestBody - 請(qǐng)求體描述
- @Content - 內(nèi)容類型
- @Schema - 數(shù)據(jù)模型
- @ArraySchema - 數(shù)組結(jié)構(gòu)
- @ExampleObject - 示例對(duì)象
6.5. 安全方案
- @SecurityScheme - 安全方案定義
- @SecuritySchemes - 多個(gè)安全方案
- @SecurityRequirement - 安全要求
- 所有安全類型:HTTP, APIKEY, OAUTH2, OPENIDCONNECT
- @OAuthFlows / @OAuthFlow / @OAuthScope - OAuth2流程
6.6. Schema高級(jí)特性
- oneOf / allOf - 組合模式
- accessMode - 訪問(wèn)模式
- requiredMode - 必需模式
- allowableValues - 允許值
- format - 數(shù)據(jù)格式
- pattern - 正則模式
- minimum / maximum - 數(shù)值范圍
- minLength / maxLength - 長(zhǎng)度限制
- minItems / maxItems - 數(shù)組限制




































