1、本文内容

  我们在Web项目开发过程中,一般来说访问一个处理器,然后会返回一个视图,或者跳转到另外的处理器。但是随着项目越来越复杂,需求越来越复杂,对于处理器返回数据的类型要求也越来越多。比如要求能够返回JSON类型的数据、或者能够返回XML格式的数据,或者返回二进制的数据流等等。

  SpringMVC提供了这样的一个机制,允许控制器返回的数据不经过正常的视图处理流程,而是直接将返回的数据写入响应体中(response body)。

  当然HTTP协议支持的各种数据类型与我们程序运行中产生的各种数据类型是不一样的,因此需要有一个机制将处理器返回的数据转换成某种类型的HTTP协议支持的数据类型。

  下面介绍相关的机制。

  2、设置处理器返回值直接写入响应体

  SpringMVC框架提供了一种十分简单的方式来配置控制器中的某个处理器的返回值直接写入响应体,只需要在处理器方法上添加 @ResponseBody 注解即可

  @Controller

  public class HomeController {

  @RequestMapping("/json")

  @ResponseBody

  public Book jsonFun() {

  Book book =new Book("spring-framework", "12345", "2016-10-12");

  return book;

  }

  }

  3、数据类型转换

  SpringMVC提供了一种数据转换机制,这种机制可以根据预先设定的media type,调用合适的转换器将数据转换成合适的类型。

  3.1、默认包含的转换器

  SpringMVC默认包含一系列的数据转换器,此处不一一列举,就介绍几种常用的。

  MappingJackson2XmlHttpMessageConverter 基于Jackson的XML转换器,能够将对象转换成XML格式的数据

  MappingJackson2HttpMessageConverter 基于 Jackson 的JSON转换器,能够将对象转换成JSON格式的数据

  GsonHttpMessageConverter 基于Gson的JSON转换器,能够将对象转换成JSON格式数据

  对于系统中默认包含的转换器,只要我们在项目中加入转换器所依赖的JAR包,相关转换器就会被加载。

  3.2、设置数据转换类型 media type

  现在我们明确了如何允许控制器直接将返回结果写入响应体中,并且明确了处理器将返回的数据写入响应体之前会进行相应的转换。

  但是根据我们前面一节的了解,我们发现SpringMVC中默认携带的转换器不止一种,那么我们如何确定处理器返回的数据交给合适的转换器,转换成我们想要的数据类型呢?

  只需要使用 @ReuqestMapping注解的一个参数进行设置即可

  @RequestMapping(value="/json", produces={"application/json; charset=UTF-8"})

  @ResponseBody

  public Book abc() {

  Book book =new Book("spring-framework", "12345", "2016-10-12");

  return book;

  }

  如上面这个例子,我们将原本使用@RequestMapping设置的路径设置为 value属性的值,此外另外设置一个属性 produces,这个属性接受一个字符串数组。接受的数据类型是 media type。上面这个例子就是标明这个方法的返回结果要转换成UTF-8编码的JSON数据。

  3.3、系统默认的设置的 media type[4]

  在一些简单的环境中,比如项目返回的数据类型只需要JSON格式,可能就不需要设置 produces的类型,来指定 media type,也能够按照要求返回正常的JSON数据,这是为什么?

  因为SpringMVC在项目初始化时,会去扫描系统中的JAR包,然后根据扫描到的JAR包设置默认的转换类型,大概的扫描过程是:

  1)检查系统中是否存在jackson-xml的JAR包,如果存在,就将数据转换类型列表中设置XML类型,以及其对应的转换器

  2)检查系统中是否存在jackson-json的JAR包,如果存在,就在数据转换类型列表中设置JSON类型,以及其对应的转换器

  因为是先检测的XML,因此XML排在JSON前面,如果系统两者的JAR包都存在,那么默认情况下数据会被转换成XML格式

  4、设置JSON数据示例

  4.1、导入相关JAR包

  导入jackson的三个核心包

  jackson-annotations-2.8.5.jar

  jackson-core-2.8.5.jar

  jackson-databind-2.8.5.jar

  4.2、编写控制器

  编写控制器中的方法,注意以下两个方面:

  1)这个方法需要使用 @ResponseBody注解标注

  2)这个方法的返回类型就是需要被转换成JSON数据的类型

  @RequestMapping(value="/json", produces={"application/json; charset=UTF-8"})

  @ResponseBody

  public Book abc() {

  Book book =new Book("spring-framework", "12345", "2016-10-12");

  return book;

  }

  当然,如果你的系统中只导入了JSON的包,那么默认就是JSON类型的,因此也可以写成这样

  @RequestMapping("/json")

  @ResponseBody

  public Book abc() {

  Book book =new Book("spring-framework", "12345", "2016-10-12");

  return book;

  }

  4.3、运行测试

  

  观察返回的内容,可以发现book对象被正确的转换成了一个JSON字符串

  5、设置XML数据示例

  5.1、引入相关JAR包

  jackson中有包含转XML的包

  jackson-dataformat-xml-2.8.5.jar

  不过它依赖于下列一系列的包

  jackson-annotations-2.8.5.jar

  jackson-core-2.8.5.jar

  jackson-databind-2.8.5.jar

  jackson-module-jaxb-annotations-2.8.5.jar

  stax2-api-3.1.4.jar

  woodstox-core-5.0.3.jar

  5.2、编写控制器

  @RequestMapping(value="/xml", produces={"application/xml; charset=UTF-8"})

  @ResponseBody

  public Book abc() {

  Book book =new Book("spring-framework", "12345", "2016-10-12");

  return book;

  }

  前面说过如果同时有XML和JSON的JAR包的话,默认XML的优先级会高一些,这里可以进行一下测试,看看如果不设置 produces,获取的数据是JSON还是XML。

  5.3、测试结果

  

  参考

  [1] 源码