[Java Backend Zero to Hello] BÀI 6.2: API DOCUMENTATION (OPENAPI/SWAGGER)
📚 Bài viết thuộc series Java Backend Zero to Hello 📌 Phần: Phase 6: REST API & Best Practices | Bài 61/86
BÀI 6.2: API DOCUMENTATION (OPENAPI/SWAGGER)
Mục tiêu
- Sử dụng SpringDoc OpenAPI
- Tạo API documentation tự động
- Tùy chỉnh Swagger UI
- Mô tả API chi tiết
1. OPENAPI LÀ GÌ?
OpenAPI (trước đây là Swagger) là chuẩn mô tả API, cho phép:
- Tự động generate documentation
- Test API trực tiếp trên browser
- Generate client code
- Validate request/response
2. DEPENDENCY
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
<version>2.3.0</version>
</dependency>
Truy cập:
- Swagger UI:
http://localhost:8080/swagger-ui.html - OpenAPI JSON:
http://localhost:8080/v3/api-docs
3. CẤU HÌNH CƠ BẢN
@Configuration
public class OpenApiConfig {
@Bean
public OpenAPI customOpenAPI() {
return new OpenAPI()
.info(new Info()
.title("My API")
.version("1.0.0")
.description("API documentation for MyApp")
.contact(new Contact()
.name("Support")
.email("support@example.com"))
.license(new License()
.name("MIT")
.url("https://opensource.org/licenses/MIT")))
.servers(List.of(
new Server().url("http://localhost:8080").description("Local"),
new Server().url("https://api.example.com").description("Production")
));
}
}
4. ANNOTATION TRÊN CONTROLLER
@RestController
@RequestMapping("/api/users")
@Tag(name = "User", description = "User management APIs")
public class UserController {
@Operation(
summary = "Get all users",
description = "Returns a list of all users with pagination"
)
@ApiResponses({
@ApiResponse(responseCode = "200", description = "Success"),
@ApiResponse(responseCode = "401", description = "Unauthorized")
})
@GetMapping
public Page<UserResponse> getAll(
@Parameter(description = "Page number", example = "0")
@RequestParam(defaultValue = "0") int page,
@Parameter(description = "Page size", example = "10")
@RequestParam(defaultValue = "10") int size
) {
return userService.findAll(page, size);
}
@Operation(summary = "Get user by ID")
@GetMapping("/{id}")
public UserResponse getById(
@Parameter(description = "User ID", required = true)
@PathVariable Long id
) {
return userService.findById(id);
}
@Operation(summary = "Create new user")
@PostMapping
public ResponseEntity<UserResponse> create(
@io.swagger.v3.oas.annotations.parameters.RequestBody(
description = "User to create",
required = true,
content = @Content(schema = @Schema(implementation = CreateUserRequest.class))
)
@RequestBody @Valid CreateUserRequest request
) {
UserResponse created = userService.create(request);
return ResponseEntity.status(HttpStatus.CREATED).body(created);
}
}
5. ANNOTATION TRÊN DTO
@Schema(description = "User creation request")
public record CreateUserRequest(
@Schema(description = "User name", example = "An", requiredMode = RequiredMode.REQUIRED)
@NotBlank String name,
@Schema(description = "Email address", example = "an@example.com")
@Email String email,
@Schema(description = "Age", example = "25", minimum = "0", maximum = "150")
@Min(0) @Max(150) Integer age
) {}
6. JWT AUTHENTICATION TRONG SWAGGER
@Configuration
public class OpenApiConfig {
@Bean
public OpenAPI customOpenAPI() {
final String securitySchemeName = "bearerAuth";
return new OpenAPI()
.info(new Info().title("My API").version("1.0"))
.addSecurityItem(new SecurityRequirement().addList(securitySchemeName))
.components(new Components()
.addSecuritySchemes(securitySchemeName,
new SecurityScheme()
.name(securitySchemeName)
.type(SecurityScheme.Type.HTTP)
.scheme("bearer")
.bearerFormat("JWT")));
}
}
7. NHÓM API VỚI @TAG
@Tag(name = "Authentication", description = "Login, register APIs")
@RestController
@RequestMapping("/api/auth")
public class AuthController { ... }
@Tag(name = "User", description = "User management APIs")
@RestController
@RequestMapping("/api/users")
public class UserController { ... }
8. CẤU HÌNH SWAGGER UI
springdoc:
swagger-ui:
path: /swagger-ui.html
operations-sorter: alpha
tags-sorter: alpha
display-request-duration: true
filter: true
api-docs:
path: /v3/api-docs
show-actuator: false
packages-to-scan: com.example.controller
9. BẢO MẬT SWAGGER UI
@Configuration
public class SwaggerSecurityConfig {
@Bean
public SecurityFilterChain swaggerSecurity(HttpSecurity http) throws Exception {
http.securityMatcher("/swagger-ui/**", "/v3/api-docs/**")
.authorizeHttpRequests(auth -> auth
.requestMatchers("/v3/api-docs/**").permitAll()
.requestMatchers("/swagger-ui/**").hasRole("ADMIN")
)
.httpBasic(Customizer.withDefaults());
return http.build();
}
}
10. CUSTOM ENDPOINT
@Hidden // Ẩn khỏi Swagger
@GetMapping("/internal")
public String internal() { ... }
11. VÍ DỤ HOÀN CHỈNH
@RestController
@RequestMapping("/api/v1/products")
@Tag(name = "Product", description = "Product management APIs")
@RequiredArgsConstructor
public class ProductController {
private final ProductService productService;
@GetMapping
@Operation(summary = "List all products")
public Page<ProductResponse> list(
@RequestParam(defaultValue = "0") int page,
@RequestParam(defaultValue = "10") int size,
@RequestParam(required = false) String category) {
return productService.findAll(page, size, category);
}
@GetMapping("/{id}")
@Operation(summary = "Get product by ID")
public ProductResponse getById(@PathVariable Long id) {
return productService.findById(id);
}
@PostMapping
@ResponseStatus(HttpStatus.CREATED)
@Operation(summary = "Create new product")
public ProductResponse create(@RequestBody @Valid CreateProductRequest request) {
return productService.create(request);
}
@PutMapping("/{id}")
@Operation(summary = "Update product")
public ProductResponse update(@PathVariable Long id,
@RequestBody @Valid UpdateProductRequest request) {
return productService.update(id, request);
}
@DeleteMapping("/{id}")
@ResponseStatus(HttpStatus.NO_CONTENT)
@Operation(summary = "Delete product")
public void delete(@PathVariable Long id) {
productService.delete(id);
}
}
12. BÀI TẬP THỰC HÀNH
Bài 1: Document User API
Thêm Swagger annotations cho UserController.
Bài 2: JWT Security
Cấu hình JWT authentication trong Swagger UI.
Bài 3: Custom Info
Tùy chỉnh thông tin API (title, version, contact).
13. TÓM TẮT
| Annotation | Mô tả |
|---|---|
@Tag |
Nhóm API |
@Operation |
Mô tả endpoint |
@ApiResponse |
Mô tả response |
@Parameter |
Mô tả parameter |
@Schema |
Mô tả schema |
@Hidden |
Ẩn endpoint |
springdoc.swagger-ui.path |
Đường dẫn UI |
Bài tiếp theo: 6.3 DTO & Mapper
🧭 Điều Hướng Series
⬅️ Bài trước: BÀI 6.1: RESTFUL API DESIGN
📋 Lộ trình tổng quan: Xem Toàn Bộ Series
➡️ Bài tiếp theo: BÀI 6.3: DTO & MAPPER
All rights reserved