Những bạn nào mới nhập môn Java SpringBoot đôi khi sẽ thắc mắc về @Controller, @RestController@ResponseBody. Bài viết này sẽ phân biệt rõ chức năng của từng annotation.

@Controller là gì?

Nếu bạn jump to definition của @Controller bạn sẽ thấy

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Controller {
@AliasFor(annotation = Component.class)
String value() default "";
}

Giải thích từng annotation một:

  • @Target(ElementType.TYPE): annotation này chỉ áp dụng cho khai báo kiểu ví dụ class, interface, record, không áp dụng cho phương thức.
  • @Retention(RetentionPolicy.RUNTIME): annotation này chỉ có hiệu lực khi ứng dụng chạy, không có hiệu lực khi code, test, hay build !
  • @Documented: đảm bảo chắc chắn rằng annotation này sẽ được liệt kê khi tạo văn bản chú thích mã nguồn.
  • @Component: đánh dấu class, interface sẽ trở thành bean component, sẽ được Spring Boot quét (scan) và ghi vào danh sách Application Context. Thông thường các bean component chỉ được khởi tạo 1 lần duy nhất, singleton.

Như vậy các class được annotated bởi @Controller bản chất là một singleton bean component.

@RestController = @Controller + @ResponseBody

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Controller
@ResponseBody
public @interface RestController {
@AliasFor(annotation = Controller.class)
String value() default "";
}

Nhìn vào mã nguồn, bạn có thể thấy @RestController = @Controller + @ResponseBody. Có nghĩa là gì?

  • @RestController sẽ trả dữ liệu về luôn cho trình duyệt, thay vì có thể phải trả dữ liệu cho View Template Engine sau đó View Template Engine kết hợp template + data để sinh ra mã HTML
  • @RestController là một @Controller chuyên dùng để tạo REST API. Còn @Controller khai báo bean component để hứng và xử lý request rồi trả về response nói chung.

Có phải @ResponseBody chỉ trả về định dạng JSON?

Mặc định, annotation @ResponseBody sẽ định hướng để tất cả các method trong class sẽ trả về định dạng application/json. Bản chất việc này là marshalling đối tượng Java ra chuỗi JSON. Tuy nhiên, nếu bạn muốn trả về định dạng khác, hãy thêm thuộc tính produce trong annotation @RequestMapping, @GetMapping

@GetMapping(value = "/xml", produces = MediaType.APPLICATION_XML_VALUE)
@ResponseBody
public Book book_xml() {
return new Book("x111", "Dế Mèn Phiêu Lưu Ký", "Tô Hoài");
}