@RequestBody 注释究竟是如何工作的以及它与 HttpMessageConverter 接口有何关系?
How exactly works @RequestBody annotation and how it is related to the HttpMessageConverter interface?
我正在研究 Spring 如何处理 REST Web 服务,我对 HttpMessageConverter 的概念有一些疑问.
在官方文档上我可以看到:
Strategy interface that specifies a converter that can convert from
and to HTTP requests and responses.
所以 HttpMessageConverter 似乎是一个接口,但 策略接口 究竟是什么?是否与策略模式有关?
所以据我了解Spring在使用@EnableWebMvc或[=时自动提供一些默认注册的实现14=]
但是这些实现到底是什么?你能给我一个实际的例子吗?
我认为它是这样工作的:
例如,客户端执行一个 HttpRequest 并在此请求的正文中放入一条 JSON 消息(我不是很实际,但我认为我可以做一些事情像这样),然后处理此 HttpRequst 的控制器使用 HttpMessageConverter 的实现将此 JSON 消息转换为模型对象。我认为反之亦然。
我的推理正确还是我遗漏了什么?
还有一个疑惑是关于@RequestBody注解的(我觉得跟之前的话题有关)
我有这个例子:
@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);
}
所以我认为@RequestBody Order updatedOrder从HttpRequest的body中获取updatedOrder输入参数的值,然后转换使用 HttpMessageConverter.
的实现将其放入 Order 对象中
是对的还是我遗漏了什么?如果是正确的如何选择正确的转换器?
例如我在这里找到了另一个与上一个类似的例子: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
}
我认为这里明确规定必须使用 JSON 到 MODEL OBJECT 转换器。为什么在前面的例子中没有指定?如何选择合适的转换器?
Tnx
处理程序方法参数由 Spring 的 HandlerMethodArgumentResolver
生成,处理程序方法 return 值由 Spring 的 HandlerMethodReturnValueHandler
处理。同时处理 @ResponseBody
和 @RequestBody
的实现是 RequestResponseBodyMethodProcessor
。
其中一个默认注册(@EnableWebMvc
配置),默认列表为 HttpMessageConverter
个实例。这是在 WebMvcConfigurationSupport#addDefaultHttpMessageConverters(List)
中完成的。您可以找到源代码并查看添加了哪些以及添加的顺序。
当 Spring 为 @RequestBody
参数生成参数时,它循环遍历 HttpMessageConverter
个实例,检查该实例 HttpMessageConverter#canRead
中给出的内容类型请求并可以生成参数类型的实例。如果可以,Spring 将使用那个 HttpMessageConverter
来产生一个论点。如果不能,Spring 将跳过它并尝试下一个实例,直到用完。此时,它会抛出异常。
对于 @ResponseBody
,除了 Spring 现在使用 HttpMessageConverter#canWrite
,过程是相同的。它将检查 HttpMessageConverter
是否可以序列化 return 类型并生成符合响应中预期内容类型的响应内容(在 Accept
请求 header 中给出) .
@RequestParam
的consumes
属性
@RequestMapping(value = "/pets", method = RequestMethod.POST, consumes="application/json")
与上面声明的策略无关。 consumes
在这里做的唯一一件事是限制处理程序的映射。例如,拿这两个处理程序
@RequestMapping(value = "/pets", method = RequestMethod.POST)
@RequestMapping(value = "/pets", method = RequestMethod.POST, consumes="application/json")
第一个可以处理对 /pets
的任何内容类型的任何请求。第二个只能处理内容类型为 application/json
.
的 /pets
请求
我正在研究 Spring 如何处理 REST Web 服务,我对 HttpMessageConverter 的概念有一些疑问.
在官方文档上我可以看到:
Strategy interface that specifies a converter that can convert from and to HTTP requests and responses.
所以 HttpMessageConverter 似乎是一个接口,但 策略接口 究竟是什么?是否与策略模式有关?
所以据我了解Spring在使用@EnableWebMvc或[=时自动提供一些默认注册的实现14=]
但是这些实现到底是什么?你能给我一个实际的例子吗?
我认为它是这样工作的:
例如,客户端执行一个 HttpRequest 并在此请求的正文中放入一条 JSON 消息(我不是很实际,但我认为我可以做一些事情像这样),然后处理此 HttpRequst 的控制器使用 HttpMessageConverter 的实现将此 JSON 消息转换为模型对象。我认为反之亦然。
我的推理正确还是我遗漏了什么?
还有一个疑惑是关于@RequestBody注解的(我觉得跟之前的话题有关)
我有这个例子:
@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);
}
所以我认为@RequestBody Order updatedOrder从HttpRequest的body中获取updatedOrder输入参数的值,然后转换使用 HttpMessageConverter.
的实现将其放入 Order 对象中是对的还是我遗漏了什么?如果是正确的如何选择正确的转换器?
例如我在这里找到了另一个与上一个类似的例子: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
}
我认为这里明确规定必须使用 JSON 到 MODEL OBJECT 转换器。为什么在前面的例子中没有指定?如何选择合适的转换器?
Tnx
处理程序方法参数由 Spring 的 HandlerMethodArgumentResolver
生成,处理程序方法 return 值由 Spring 的 HandlerMethodReturnValueHandler
处理。同时处理 @ResponseBody
和 @RequestBody
的实现是 RequestResponseBodyMethodProcessor
。
其中一个默认注册(@EnableWebMvc
配置),默认列表为 HttpMessageConverter
个实例。这是在 WebMvcConfigurationSupport#addDefaultHttpMessageConverters(List)
中完成的。您可以找到源代码并查看添加了哪些以及添加的顺序。
当 Spring 为 @RequestBody
参数生成参数时,它循环遍历 HttpMessageConverter
个实例,检查该实例 HttpMessageConverter#canRead
中给出的内容类型请求并可以生成参数类型的实例。如果可以,Spring 将使用那个 HttpMessageConverter
来产生一个论点。如果不能,Spring 将跳过它并尝试下一个实例,直到用完。此时,它会抛出异常。
对于 @ResponseBody
,除了 Spring 现在使用 HttpMessageConverter#canWrite
,过程是相同的。它将检查 HttpMessageConverter
是否可以序列化 return 类型并生成符合响应中预期内容类型的响应内容(在 Accept
请求 header 中给出) .
@RequestParam
的consumes
属性
@RequestMapping(value = "/pets", method = RequestMethod.POST, consumes="application/json")
与上面声明的策略无关。 consumes
在这里做的唯一一件事是限制处理程序的映射。例如,拿这两个处理程序
@RequestMapping(value = "/pets", method = RequestMethod.POST)
@RequestMapping(value = "/pets", method = RequestMethod.POST, consumes="application/json")
第一个可以处理对 /pets
的任何内容类型的任何请求。第二个只能处理内容类型为 application/json
.
/pets
请求