@ResponseBody @RequestBody-对象究竟发生了什么

时间:2014-02-04 05:24:20

标签: java xml json spring rest

编辑我清理了相当长的帖子。我会单独发布问题。

请帮助澄清我的疑虑。如果需要,我会发布代码。

我使用Spring rest模板作为带有消息转换器的客户端测试了Spring Rest控制器,没有消息转换器,类路径中有JSON jar,类路径中没有JSON jar。

每种情况下的行为都不同,这是我之前想澄清的。

我的要求是我需要从客户端发送并获取XML作为String。将来我们可能需要支持对象。

我设计了一个带有@RequestBody方法的简单控制器,其中JAXBObject作为方法参数,由在服务器端将XML字符串转换为JAXB对象的消息转换器设置。

//控制器

   @RequestMapping(method=RequestMethod.POST, value="/updatePricePlan" , consumes="application/xml" , produces = "application/xml")
   public @ResponseBody  ResponseEntity<Employee> updateEmployee( @RequestBody Employee emp ) {
  // code 
  }

我想知道:

  1. 我的方法将来会支持对象的交换。
  2. 可以单独使用JAXB对象作为@RequestBody的一部分发送
  3. 如果json jar在调用rest服务的客户端代码的类路径中,即使我在头文件中明确设置了application / xml,JSON也是默认格式。
  4. 如何将对象作为@ResponseBody或@RequestBody的一部分准确发送。
  5. 如果客户端期望而对象而不是XML作为字符串,则服务器端的消息转换器不会将上例中的JAXB对象转换为XML作为字符串并按原样返回对象
  6. 如果根据我的理解,第5点是真的,那么对象是否按原样传递给客户端?发送JAXB对象而不是POJO对象是一种好习惯

1 个答案:

答案 0 :(得分:1)

  1. 我不知道你将来交换物品是什么意思。如果您的意思是想要将Employee替换为其他对象,则可以正常工作,但您将获得不同的XML。除非EmployeeNewEmployee(无论你用什么替换它)具有相同的XML输出,否则这将是无缝的。
    1. 同样,我不完全确定你在问什么,如果你问的是JAXB是否是唯一允许的XML库,那么情况并非如此。 JAX-RS支持添加MessageBodyReaderMessageBodyWriter个提供程序。您可以使用它们来添加备用XML读取器和编写器。如果你问你是否可以使用其他格式(例如JSON与杰克逊)那么你可以,但你最好写一个不同的方法来做它。
    2. 作为服务器,除非您正在拦截并替换客户端的标头,否则您不会设置请求的标头。如果客户端使用JSON内容类型标头发出请求,那么他们会收到HTTP 415错误,因为您没有任何“消耗”JSON内容类型的方法。
    3. 下面说明
    4. 我不确定你的意思。客户端将获得XML字符串。他们没有Employee对象的概念,除非他们自己写了这样一个类。他们还必须将XML字符串反序列化为Employee对象。
    5. 为客户端提供XML字符串,而不是对象。 JAXB对象和POJO对象之间有什么区别?
  2. 以下是您收到请求时会发生的情况。

    1. 请求到达服务器。此时它是一个HTTP请求,它是一个很长的标头和HTTP信息串加一个只是一个字节流的主体。我假设正文是一个XML字符串。
    2. 请求被传递给JAX-RS servlet。
    3. JAX-RS servlet查看其资源列表(@Path)以查找与URL,内容类型标头和接受标头匹配的所有方法。不同的内容类型可能有多个匹配。
    4. JAX-RS servlet查看其MessageBodyReadersMessageBodyWriters列表,看看它是否可以找到MessageBodyReader,它可以将具有给定内容类型的消息转换为对象类型即@RequestBody(它使用accept方法检查)和MessageBodyWriter可以将响应对象类转换为具有适当生产类型的消息。
    5. 如果找到匹配项,则使用MessageBodyReaderMessageBodyWriter执行该方法以序列化/反序列化对象。
    6. 例如,假设您拥有的是上面发布的方法。

      • 如果请求带有内容类型的application / json,那么JAX-RS将找到具有相同URL但与使用注释不匹配的匹配。 JAX-RS将返回415。
      • 如果请求带有application / xml的内容类型和application / json的accept标头,那么JAX-RS将找到具有相同URL但与produce批注不匹配的匹配。 JAX-RS将返回415。
      • 如果请求带有application / xml的内容类型和application / xml的accept标头,那么JAX-RS将找到该方法作为匹配项。然后,它会查找可以接受MessageBodyReader的{​​{1}}。默认的JAXB ("application/xml", Employee.class)接受MessageBodyReader,因此它将匹配此项。然后,JAX-RS会查找可以接受("application/xml", <any class with @XmlRootElement>)的{​​{1}}。默认的JAXB MessageBodyWriter接受("application/xml", Employee.class),因此它将与此匹配。
      • JAX-RS然后将请求正文作为MessageBodyWriter传递给默认的JAXB ("application/xml", <any class with @XmlRootElement>),它将请求反序列化为InputStream对象。
      • JAX-RS将使用MessageBodyReader对象调用您的方法并接受响应。
      • JAX-RS然后将响应传递给默认的JAXB Employee以及Employee来表示响应正文。 MessageBodyWriter会将OutputStream对象序列化为XML字符串。
      • 此XML字符串将封装到内容类型为“application / xml”的HTTP响应中,并发送回客户端。