我正在研究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的请求。

10-04 20:30