我正在研究Spring如何处理 REST Web服务,并且我对 HttpMessageConverter 的概念有一些疑问。
在官方文档中,我可以阅读:
因此 HttpMessageConverter 似乎是一个接口(interface),但是策略接口(interface)到底是什么?是否与策略模式相关?
因此,据我了解,Spring在使用 @EnableWebMvc 或 时会自动提供默认情况下注册的一些实现。
但是这些实现到底是什么?你能给我一个实际的例子吗?
我认为它是这样工作的:
例如,客户端执行一个HttpRequest,将 JSON 消息放入此请求的主体中(我不太实际,但我认为我可以这样做),然后处理此HttpRequst的 Controller 将使用 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的主体中获取 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转换器。为什么在上一个示例中未指定?如何选择合适的转换器?
特纳克斯
最佳答案
处理程序方法参数由Spring的HandlerMethodArgumentResolver
生成,处理程序方法返回值由Spring的HandlerMethodReturnValueHandler
处理。同时处理@ResponseBody
和@RequestBody
的实现是RequestResponseBodyMethodProcessor
。
其中之一是默认注册的(@EnableWebMvc
配置),带有默认的HttpMessageConverter
实例列表。这是在WebMvcConfigurationSupport#addDefaultHttpMessageConverters(List)
中完成的。您可以找到源代码,并查看添加的源代码和源代码的顺序。
当Spring生成@RequestBody
参数的参数时,它会循环遍历HttpMessageConverter
实例,检查该实例HttpMessageConverter#canRead
是否满足请求中给出的内容类型,并可以生成参数类型的实例。如果可以,Spring将使用该HttpMessageConverter
产生一个参数。如果不能,Spring将跳过它并尝试下一个实例,直到用完为止。此时,它将引发异常。
对于@ResponseBody
,过程相同,只是Spring现在使用HttpMessageConverter#canWrite
。它将检查HttpMessageConverter
是否可以序列化返回类型并生成适合响应中期望的内容类型的响应内容(在Accept
请求 header 中给出)。consumes
的@RequestParam
属性
@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
的任何请求。第二个只能处理内容类型为/pets
的对application/json
的请求。