2015-04-08 17 views
5

Tôi đang nghiên cứu cách Spring xử lý REST dịch vụ web và tôi có một số nghi ngờ liên quan đến khái niệm về HttpMessageConverter.Chú thích @RequestBody hoạt động chính xác như thế nào và cách nó liên quan đến giao diện HttpMessageConverter như thế nào?

Trên tài liệu chính thức tôi có thể đọc:

giao diện Chiến lược chỉ rõ một bộ chuyển đổi có thể chuyển đổi từ và các yêu cầu HTTP và câu trả lời.

Vì vậy, các HttpMessageConverter có vẻ là một giao diện nhưng những gì chính xác một giao diện chiến lược là? Có phải cái gì liên quan đến mẫu chiến lược hay không?

Vì vậy, từ những gì tôi có hiểu mùa xuân tự động cung cấp một số triển khai đăng ký theo mặc định khi sử dụng @EnableWebMvc hoặc

Nhưng chính xác những gì hiện những thực hiện? Bạn có thể cung cấp cho tôi một ví dụ thực tế?

Tôi nghĩ rằng nó hoạt động theo cách này:

Ví dụ một khách hàng thực hiện một HttpRequest đưa vào cơ thể của yêu cầu này một JSON nhắn (Tôi không quá thực tế, nhưng tôi nghĩ rằng tôi có thể làm điều gì đó như thế này), sau đó bộ điều khiển xử lý HttpRequst này sử dụng thực hiện HttpMessageConverter để chuyển đổi thông báo JSON này thành một đối tượng mô hình. Tôi nghĩ rằng đó cũng là sự thật ngược lại.

Lý do chính xác của tôi hoặc tôi thiếu gì đó?

Một nghi ngờ khác liên quan đến chú thích @RequestBody (mà tôi nghĩ rằng nó có liên quan đến chủ đề trước đó).

Tôi có ví dụ này:

@RequestMapping(value="/orders/{id}", method=RequestMethod.PUT) 
@ResponseStatus(HttpStatus.NO_CONTENT) // 204 
public void updateOrder(@RequestBody Order updatedOrder, @PathVariable("id") long id) { 
    // process updated order data and return empty response 
    orderManager.updateOrder(id, updatedOrder); 
} 

Vì vậy, tôi nghĩ rằng @RequestBody tự updatedOrder mất giá trị của updatedOrder tham số đầu vào ra khỏi cơ thể của HttpRequest và sau đó chuyển đổi nó thành một với Đặt hàng đối tượng bằng cách triển khai HttpMessageConverter.

Có đúng hay tôi đang thiếu thứ gì đó? Nếu nó là đúng như thế nào có thể chọn chuyển đổi quyền?

Ví dụ ở đây tôi tìm thấy một ví dụ khác tương tự như trước đó một: http://docs.spring.io/spring/docs/current/spring-framework-reference/html/mvc.html

@Controller 
@RequestMapping(value = "/pets", method = RequestMethod.POST, consumes="application/json") 
public void addPet(@RequestBody Pet pet, Model model) { 
    // implementation omitted 
} 

Tôi nghĩ rằng đây nó được quy định một cách rõ ràng rằng nó phải sử dụng một JSON để mô hình chuyển đổi OBJECT. Tại sao trong ví dụ trước không được chỉ định? Làm thế nào có thể chọn trình chuyển đổi phù hợp?

Tnx

Trả lời

9

thông số phương pháp Handler được tạo ra bởi giá trị HandlerMethodArgumentResolver và phương pháp xử lý trở lại mùa xuân được xử lý bởi Spring HandlerMethodReturnValueHandler. Việc triển khai thỏa thuận với cả hai @ResponseBody@RequestBodyRequestResponseBodyMethodProcessor.

Một trong số này được đăng ký theo mặc định (cấu hình @EnableWebMvc) với danh sách mặc định là HttpMessageConverter trường hợp. Điều này được thực hiện trong WebMvcConfigurationSupport#addDefaultHttpMessageConverters(List). Bạn có thể tìm mã nguồn và xem mã nào được thêm vào và theo thứ tự nào.

Khi Spring đi để tạo đối số cho tham số @RequestBody, nó lặp qua trường hợp HttpMessageConverter, kiểm tra xem loại nội dung đó có trong yêu cầu và có thể tạo phiên bản loại tham số hay không. Nếu có thể, Spring sẽ sử dụng HttpMessageConverter để tạo ra một đối số. Nếu không thể, Spring sẽ bỏ qua nó và thử ví dụ tiếp theo, cho đến khi nó hết. Tại thời điểm đó, nó sẽ ném một ngoại lệ.

Đối với @ResponseBody, quá trình này giống nhau trừ Mùa xuân hiện sử dụng HttpMessageConverter#canWrite. Nó sẽ kiểm tra nếu HttpMessageConverter có thể tuần tự hóa kiểu trả về và tạo nội dung phản hồi phù hợp với kiểu nội dung được mong đợi trong phản hồi (được đưa ra trong tiêu đề yêu cầu Accept).

Các consumes thuộc tính của @RequestParam

@RequestMapping(value = "/pets", method = RequestMethod.POST, consumes="application/json") 

không có gì để làm với các chiến lược khai báo bên trên. Điều duy nhất mà consumes làm ở đây là để hạn chế ánh xạ của trình xử lý. Ví dụ: sử dụng hai trình xử lý này

@RequestMapping(value = "/pets", method = RequestMethod.POST) 

@RequestMapping(value = "/pets", method = RequestMethod.POST, consumes="application/json") 

Người đầu tiên có thể xử lý mọi yêu cầu đến /pets với bất kỳ loại nội dung nào. Người thứ hai chỉ có thể xử lý các yêu cầu đó đến /pets với loại nội dung application/json.

+3

Giải thích hoàn hảo, bạn là một ninja, dành cho bạn – AndreaNobili

Các vấn đề liên quan