Swagger/OpenAPI 是 RESTful API 文檔化的行業標準。本文示範如何在 Spring Boot 3.x 中整合最新的 SpringDoc OpenAPI (Swagger 3),實現代碼與文檔零距離同步,並掌握常用註解與進階客製化技巧。
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
<version>2.3.0</version>
</dependency>
@Configuration
@OpenAPIDefinition(
info = @Info(
title = "用戶管理 API 文檔",
version = "v1.0.0",
description = "基於 Spring Boot 3 + SpringDoc OpenAPI 3 構建",
contact = @Contact(name = "開發團隊", email = "dev@example.com", url = "https://example.com"),
license = @License(name = "Apache 2.0", url = "https://www.apache.org/licenses/LICENSE-2.0")
),
servers = {
@Server(url = "https://localhost:8080/api", description = "開發環境"),
@Server(url = "https://api.example.com", description = "生產環境")
}
)
public class OpenApiConfig {
@Bean
public OpenAPI customOpenAPI() {
return new OpenAPI()
.addSecurityItem(new SecurityRequirement().addList("Bearer Authentication"))
.components(new Components()
.addSecuritySchemes("Bearer Authentication", new SecurityScheme()
.type(SecurityScheme.Type.HTTP)
.scheme("bearer")
.bearerFormat("JWT")
.description("JWT 授權 Token,格式:Bearer {token}")
)
);
}
@Bean
public GroupedOpenApi publicApi() {
return GroupedOpenApi.builder()
.group("public")
.pathsToMatch("/api/**")
.packagesToScan("com.example.controller")
.build();
}
}
@Schema(description = "用戶實體")
public class User {
@Schema(description = "用戶唯一標識", example = "1001", accessMode = Schema.AccessMode.READ_ONLY)
private Long id;
@Schema(description = "用戶名", example = "zhangsan", requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank(message = "用戶名不能為空")
@Size(min = 2, max = 20, message = "用戶名長度 2-20 位")
private String username;
@Schema(description = "郵箱", example = "zhangsan@example.com", format = "email")
@Email(message = "郵箱格式不正確")
private String email;
@Schema(description = "狀態", allowableValues = {"ENABLED", "DISABLED", "LOCKED"}, example = "ENABLED")
private UserStatus status;
@Schema(description = "創建時間", example = "2024-01-15T10:30:00Z", accessMode = Schema.AccessMode.READ_ONLY)
private LocalDateTime createdAt;
// Getter/Setter 略
}
常用註解速查表
| 註解 | 作用位置 | 說明 |
|---|---|---|
| @Tag | Controller 類 | 分組標籤與描述 |
| @Operation | 方法 | 單個 API 操作元數據 |
| @Parameter | 方法參數 | 路徑/查詢/Header 參數描述 |
| @RequestBody | 方法參數 | 請求體描述 (OpenAPI 3 專用) |
| @ApiResponses/@ApiResponse | 方法 | 響應碼、描述、Schema 映射 |
| @Schema | 類/字段 | 模型屬性描述、範例、驗證規則 |
| @SecurityRequirement | 類/方法 | 指定安全方案 (如 JWT) |
| @Hidden | 類/方法 | 隱藏不對外暴露的接口 |
@Bean
public OpenAPICustomiser globalParamsCustomiser() {
return openApi -> openApi.getPaths().values().forEach(pathItem ->
pathItem.readOperations().forEach(op -> op.addParametersItem(
new Parameter().name("X-Request-ID").in("header").description("請求追蹤 ID")
.schema(new StringSchema()).required(false)
))
);
}
@Bean
public OpenAPICustomiser enumCustomiser() {
return openApi -> openApi.getComponents().getSchemas().values().forEach(schema ->
schema.getProperties().forEach((k, v) -> {
if (v.getEnum() != null) return;
// 針對 Java Enum 類型自動填充 allowableValues
})
);
}
@Bean
public GroupedOpenApi v1Api() { return GroupedOpenApi.builder().group("v1").pathsToMatch("/api/v1/**").build(); }
@Bean
public GroupedOpenApi v2Api() { return GroupedOpenApi.builder().group("v2").pathsToMatch("/api/v2/**").build(); }
https://localhost:8080/swagger-ui.html 或 /swagger-ui/index.htmlhttps://localhost:8080/v3/api-docshttps://localhost:8080/v3/api-docs.yamlSpringDoc OpenAPI 3 透過註解驅動實現「代碼即文檔」,消除了文檔滯後於代碼的痛點。合理使用 @Tag、@Operation、@Schema 等註解,配合全域客製化,可生成企業級、可直接對接 API 网關/測試工具的標準化文檔。