Spring MVC và xử lý yêu cầu HTTP
Định nghĩa endpoint
Sử dụng @RestController để tự động trả về dữ liệu JSON, tương đương với @Controller + @ResponseBody.
Ánh xạ URL bằng @RequestMapping hoặc các biến thể cụ thể như @GetMapping, @PostMapping để ràng buộc phương thức HTTP.
Nhận tham số từ client
- Không dùng annotation: Spring tự động bind tham số từ query string vào đối tượng.
Gọi:@GetMapping("/user") public Person getUser(Person person) { return person; }/user?name=Nguyễn Văn A&age=25 - @RequestParam: Ràng buộc tham số từ query string.
@GetMapping("/info") public Person getInfo(@RequestParam String name, @RequestParam int age) { return new Person(name, age); } - @PathVariable: Lấy giá trị từ đường dẫn URL.
Gọi:@GetMapping("/profile/{username}/{years}") public Person getProfile(@PathVariable String username, @PathVariable int years) { return new Person(username, years); }/profile/Nguyễn Văn A/25 - @RequestBody: Nhận dữ liệu JSON từ body request.
Body request (Content-Type: application/json):@PostMapping("/register") public Person register(@RequestBody Person person) { return person; }{ "name": "Nguyễn Văn A", "age": 25 }
Xác thực dữ liệu đầu vào
Thêm dependency spring-boot-starter-validation và sử dụng các annotation như @NotBlank, @Min trên field entity.
public class Person {
@NotBlank(message = "Tên không được để trống")
private String name;
@Min(value = 1, message = "Tuổi phải lớn hơn 0")
private int age;
}
Trong controller, thêm @Valid trước tham số cần validate:
@PostMapping("/validate")
public Person validatePerson(@RequestBody @Valid Person person) {
return person;
}
Interceptor - Xử lý trước/sau controller
Tạo interceptor để can thiệp vào luồng xử lý request:
@Component
public class RequestInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest req, HttpServletResponse res, Object handler) {
System.out.println("Trước khi xử lý controller");
return true; // tiếp tục xử lý
}
@Override
public void postHandle(HttpServletRequest req, HttpServletResponse res, Object handler, ModelAndView mv) {
System.out.println("Sau khi controller xử lý xong");
}
@Override
public void afterCompletion(HttpServletRequest req, HttpServletResponse res, Object handler, Exception ex) {
System.out.println("Hoàn tất request");
}
}
Đăng ký interceptor trong cấu hình:
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Autowired
private RequestInterceptor interceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(interceptor);
}
}
Thiết kế API theo chuẩn RESTful
Tích hợp Swagger UI
Thêm dependency springfox-boot-starter và cấu hình:
@Configuration
@EnableOpenApi
public class SwaggerConfig {
@Bean
public Docket apiDoc() {
return new Docket(DocumentationType.OAS_30)
.select()
.apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
.paths(PathSelectors.any())
.build()
.apiInfo(new ApiInfoBuilder()
.title("Tài liệu API")
.version("1.0")
.build());
}
}
Gắn annotation cho controller:
@RestController
@Api(tags = "Quản lý người dùng")
public class UserController {
@GetMapping("/users/{id}")
@ApiOperation("Lấy thông tin người dùng theo ID")
public Person findUser(@PathVariable String id) {
return new Person(id, 30);
}
}
Truy cập tài liệu tại: /swagger-ui/index.html
Thay thế bằng Knife4j
Sử dụng knife4j-spring-boot-starter để có giao diện đẹp hơn, không cần thay đổi code. Truy cập tại: /doc.html
Ví dụ thực tế RESTful
@RestController
@RequestMapping("/api/users")
public class UserController {
@GetMapping("/{username}")
public Person fetchUser(@PathVariable String username) {
return new Person(username, 25);
}
@PostMapping
public boolean addUser(@RequestBody Person user) {
return user != null;
}
@PutMapping
public boolean modifyUser(@RequestBody Person user) {
return user != null;
}
@DeleteMapping("/{username}")
public boolean removeUser(@PathVariable String username) {
return username != null;
}
}
Lưu trữ dữ liệu và các kỹ thuật hỗ trợ
Các phần về kết nối cơ sở dữ liệu, kiểm thử đơn vị, xử lý ngoại lệ và ghi log sẽ được trình bày chi tiết trong các bài hướng dẫn tiếp theo.