SpringDoc OpenAPI là một thư viện Java giúp tự động sinh tài liệu API cho các ứng dụng Spring Boot dựa trên chuẩn OpenAPI 3. Khác với cách tiếp cận thủ công, SpringDoc phân tích mã nguồn tại thời điểm chạy — đặc biệt là các lớp controller — để trích xuất thông tin về endpoint, tham số, mã phản hồi và mô hình dữ liệu, từ đó xây dựng tài liệu tương tác trực quan.
Cài đặt nhanh
Chỉ cần khai báo phụ thuộc trong pom.xml:
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-starter-webmvc-api</artifactId>
<version>2.3.0</version>
</dependency>
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
<version>2.3.0</version>
</dependency>
Sau khi khởi động ứng dụng, truy cập /swagger-ui.html (hoặc /swagger-ui/index.html tùy phiên bản) để xem giao diện tài liệu trực quan. Dữ liệu định dạng JSON theo chuẩn OpenAPI 3 có thể được lấy tại /v3/api-docs, hỗ trợ tích hợp với các công cụ như Postman, Apifox hoặc Redoc.
Gắn chú thích chi tiết cho API
Các chú thích nằm trong gói io.swagger.v3.oas.annotations. Ví dụ:
@Tag(name = "BàiViết", description = "Quản lý nội dung bài viết")
@RestController
@RequestMapping("/api/posts")
public class BaiVietController {
@Operation(summary = "Lấy thông tin bài viết theo ID",
description = "Trả về đối tượng bài viết nếu tồn tại, ngược lại trả mã 404")
@ApiResponses({
@ApiResponse(responseCode = "200", description = "Thành công"),
@ApiResponse(responseCode = "404", description = "Không tìm thấy bài viết")
})
@GetMapping("/{maBaiViet}")
public ResponseEntity<BaiViet> layTheoId(
@Parameter(description = "Mã định danh duy nhất của bài viết", required = true)
@PathVariable Long maBaiViet) {
return ResponseEntity.ok(baiVietService.layBangMa(maBaiViet));
}
}
@Tag: Gắn nhãn nhóm chức năng cho toàn bộ controller.@Operation: Mô tả ngắn và dài cho từng endpoint.@Parameter: Giải thích từng tham số (path, query, body...), bao gồm tính bắt buộc và kiểu dữ liệu.@ApiResponse: Định nghĩa rõ ràng các mã HTTP và ý nghĩa tương ứng.
Mô tả cấu trúc dữ liệu với @Schema
Áp dụng cho các lớp DTO, entity hoặc request/response object:
@Schema(description = "Đối tượng bài viết trên hệ thống")
public class BaiViet implements Serializable {
@Schema(description = "Tiêu đề bài viết", example = "Hướng dẫn tích hợp OpenAPI")
private String tieuDe;
@Schema(description = "Nội dung chính", requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank(message = "Nội dung không được để trống")
private String noiDung;
@Schema(description = "Trạng thái công khai", defaultValue = "true")
private Boolean daDang = true;
}
Các annotation JSR-303 như @NotBlank, @Min, @Email cũng được SpringDoc tự động chuyển thành ràng buộc trong tài liệu.
Tùy chỉnh thông tin chung của tài liệu
Thông qua lớp cấu hình hoặc bean OpenAPI:
@Configuration
public class OpenApiConfig {
@Bean
public OpenAPI customizeOpenAPI() {
return new OpenAPI()
.info(new Info()
.title("Hệ thống Quản lý Nội dung API")
.version("2.1.5")
.description("Tài liệu RESTful API dành cho hệ thống CMS nội bộ")
.contact(new Contact()
.name("Đội phát triển Backend")
.email("backend@company.local"))
.license(new License()
.name("MIT License")
.url("https://opensource.org/licenses/MIT")));
}
}
Phân nhóm API theo chức năng
Khi hệ thống có nhiều module, nên tách tài liệu thành các nhóm riêng biệt:
@Configuration
public class ApiGroupConfig {
@Bean
public GroupedOpenApi publicApi() {
return GroupedOpenApi.builder()
.group("người-dùng")
.displayName("Giao diện người dùng")
.packagesToScan("com.example.app.web.user")
.pathsToMatch("/api/v1/users/**")
.build();
}
@Bean
public GroupedOpenApi adminApi() {
return GroupedOpenApi.builder()
.group("quản-trị")
.displayName("Giao diện quản trị viên")
.packagesToScan("com.example.app.web.admin")
.pathsToMatch("/api/v1/admin/**")
.addOpenApiCustomiser(customizeAdminInfo())
.build();
}
private OpenApiCustomiser customizeAdminInfo() {
return openApi -> openApi.info(new Info()
.title("API Quản trị Hệ thống")
.version("2.1.5-admin"));
}
}
Hoặc cấu hình thuần qua application.yml:
springdoc:
group-configs:
- group: người-dùng
displayName: Giao diện người dùng
packages-to-scan: com.example.app.web.user
paths-to-match: /api/v1/users/**
- group: quản-trị
displayName: Giao diện quản trị viên
packages-to-scan: com.example.app.web.admin
paths-to-match: /api/v1/admin/**
Hỗ trợ xác thực trong Swagger UI
Để kích hoạt nút Authorize và gửi token JWT khi gọi thử API:
@Bean
public GroupedOpenApi securedApi() {
String authName = "JWT Bearer";
return GroupedOpenApi.builder()
.group("bảo-mật")
.packagesToScan("com.example.app.web.secured")
.addOpenApiCustomiser(openApi -> openApi
.components(new Components()
.addSecuritySchemes(authName,
new SecurityScheme()
.type(SecurityScheme.Type.HTTP)
.scheme("bearer")
.bearerFormat("JWT")))
.security(List.of(new SecurityRequirement().addList(authName))))
.build();
}
Khi mở Swagger UI, nhấn nút Authorize, nhập giá trị dạng Bearer eyJhbGciOi... để kích hoạt bảo mật cho tất cả các endpoint trong nhóm.
Chuyển đổi từ Swagger 2 sang OpenAPI 3
Một số ánh xạ phổ biến khi nâng cấp:
| Swagger 2 | OpenAPI 3 (SpringDoc) |
|---|---|
@Api | @Tag |
@ApiOperation | @Operation |
@ApiParam | @Parameter |
@ApiModel | @Schema |
@ApiModelProperty | @Schema hoặc @Schema(accessMode = Schema.AccessMode.READ_ONLY) |
@ApiResponses | @ApiResponses (tên giữ nguyên, nhưng code → responseCode) |
Cấu hình nâng cao
Một số thuộc tính thường dùng trong application.properties:
# Vô hiệu hóa hoàn toàn tài liệu API
springdoc.api-docs.enabled=false
# Ẩn giao diện Swagger UI
springdoc.swagger-ui.enabled=false
# Giới hạn phạm vi quét chỉ các package cụ thể
springdoc.packages-to-scan=com.example.app.web.api,com.example.app.web.admin
# Chỉ bao gồm các đường dẫn khớp mẫu
springdoc.paths-to-match=/api/v1/**,/api/v2/**
# Thay đổi đường dẫn gốc của UI
springdoc.swagger-ui.path=/docs