在Spring MVC之前我们需要在Servlet里处理HttpServletRequest参数对象,但这个对象里的属性都是通用类型的对象(如字符串),处理起来很繁琐并且容易出错,而Spring MVC允许我们直接把参数和返回值定义为对象,比如:

先定义一个对象:

@Data
public class User { private String id;
private String name; }

然后定义一个Spring MVC方法:

@RequestMapping(value = "/create-user", method = RequestMethod.POST)
public void createUser(@RequestBody User user) {
LOGGER.debug("参数:user = {}", user);
}

其中,参数为User类型的对象,@RequestBody注解通知Spring MVC把http请求的body转换为User对象,并作为参数调用我们写的createUser方法。

除把参数定义为对象外,返回值也能为对象:

@RequestMapping(value = "/find-user", method = RequestMethod.GET)
@ResponseBody
public User findUser() {
return new User("01", "yw");
}

返回值对象需要加@ResponseBody注解,该注解通知Spring MVC把返回值对象转换为字符串,并作为http响应消息中的body部分。

除@RequestBody、@ResponseBody注解外,Spring MVC还提供了其它注解,具体请参见相关文档说明。

Spring MVC是如何进行http消息与对象之间的转换呢?答案是HttpMessageConverter转换器接口。

HttpMessageConverter

Spring MVC就像是一个中间人,一边为http消息(即HttpServletRequest和HttpServletResponse),另一边是@RequestMapping方法,Spring MVC的使命就是自动把http消息转换为对象,以及反过来把对象转换为字符串返回。这一切都依赖于HttpMessageConverter转换接口。Spring MVC内置了其很多实现,每个实现对应于一种格式的数据转换,我们可按需配置加载转换器。如果未配置则Spring MVC进行默认加载,至于默认加载了哪些转换器请参见WebMvcConfigurationSupport#addDefaultHttpMessageConverters方法,另请参见[Http Message Converters with the Spring Framework](http://www.baeldung.com/spring-httpmessageconverter-rest)。

特别要提醒的是,如果你配置了则Spring MVC将只加载你配置的,如果你未配置则默认加载。因此,不要误以为你的配置是对默认值的补充。

我们基本上不需要自己去配置转换器,使用默认配置就足够了。但如果你有必要则可这样配置:

@Configuration
@EnableWebMvc
public class WeMvcConfiguration extends WebMvcConfigurerAdapter {
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.add(...);
}
}

不论你是否配置了,我们最好都检查一下运行时到底加载了哪些转换器:

@EventListener
public void on(ContextRefreshedEvent event) {
RequestMappingHandlerAdapter requestMappingHandlerAdapter = applicationContext.getBean(RequestMappingHandlerAdapter.class);
List<?> messageConverters = requestMappingHandlerAdapter.getMessageConverters();
StringBuilder sb = new StringBuilder();
sb.append("Spring共加载了").append(messageConverters.size()).append("个消息转换器对象:").append(messageConverters.toString());
LOGGER.info(sb.toString());
}

上面的事件监听器方法将在Spring启动完毕后打印输出所有加载的转换器。你可做两个试验,一是自己不配置,二是自己配置,然后分别启动系统看看到底加载了哪些转换器。

JSON

如果系统加载了json转换器你就可以发送json消息了:

curl -X POST -H 'Content-Type: application/json' -d '{"id":"01","name":"yw"}' http://localhost:8080/create-user

如果调用不成功则很可能是系统并未加载json转换器。Spring MVC的默认配置只当存在jackson-databind时才加载json转换器。

你可先检查是否存在jackson-databind依赖项:

mvn dependency:tree | find "jackson-databind"

若不存在则定义之:

<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>

这样Spring MVC将自动加载json转换器。

除发送json消息外,你也可以接收json消息:

curl http://localhost:8080/find-user
{"id":"","name":"yw"}

XML

同json一样,Spring MVC也是利用转换器来实现发送和接收xml消息。不同的是,Spring MVC只支持jackson-databind一种json转换器,但支持jaxb和jackson-databind-xml两种xml转换器,你可选择其一使用。

要让Spring MVC自动配置jackson-databind-xml就需存在该依赖项。你可先检查是否存在该依赖项:

mvn dependency:tree | find "jackson-databind-xml"

若不存在则定义之:

<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-xml</artifactId>
</dependency>

接着你就可以传xml消息了:

curl -X POST -H 'Content-Type: application/xml' -d '<root><id>01</id><name>yw</name></root>' http://localhost:8080/create-user

强制数据格式

如上,你的create-user方法既可接收xml消息,也可接收json消息,但有时你希望限制数据格式,此时可加consumes参数:

@RequestMapping(value = "/xml-create-user", consumes = {MediaType.APPLICATION_XML_VALUE}, method = RequestMethod.POST)
public void xmlCreateUser(@RequestBody User user) {
LOGGER.debug("参数:user = {}", user);
}

上例表示只接收xml格式的消息。因此若你再发json消息则将失败。

同样,你也可以限制返回值为xml:

@RequestMapping(value = "/xml-find-user", method = RequestMethod.GET, produces = {MediaType.APPLICATION_XML_VALUE})
@ResponseBody
public User xmlFindUser() {
return new User("02", "yw");
}

接着我们就可以接收xml消息了:

curl http://localhost:8080/xml-find-user
<User xmlns=""><id></id><name>yw</name></xml>

Jackson XML

上面说到,Spring MVC支持jackson-databind-xml作为xml转换器,并实际测试得到返回的xml:

<User xmlns=""><id></id><name>yw</name></xml>

其中有 xmlns="" 。该xmlns并无什么副作用,但如果你很在意一定要去掉它则可增加依赖项:

<dependency>
<groupId>com.fasterxml.woodstox</groupId>
<artifactId>woodstox-core</artifactId>
<version>5.0.</version>
</dependency>

其原因请参见[FasterXML讨论](https://github.com/FasterXML/jackson-dataformat-xml/issues/32)。

面向对象

上面我们花了很多篇幅介绍了json和xml,但Spring MVC给我们带来的好处却在于让我们忽视它们的存在,让我们只关注对象,无需去考虑对象是从json来的还是从xml来的,这些底层的事就交给Spring MVC去处理吧。同时,直接把我们自己的对象作为参数和返回值也使得单元测试更容易写。

练习

1、如果你的系统同时有json和xml转换器,请解释为何用RestTemplate代码和curl工具调用同一个Spring MVC方法时时,一个返回的是xml,另一个返回的是json?

@Test
public void test() {
RestTemplate restTemplate = new RestTemplate();
String s = restTemplate.getForObject("http://localhost:8080/find-user", String.class);
System.out.println(s);
// <User xmlns=""><id>01</id><name>yw</name></xml>
}
curl http://localhost:8080/find-user
{"id":"","name":"yw"}

2、本说明文档介绍了用Jackson-Xml作为Xml转换器,同时说到你也可以用jaxb进行Xml转换。请改为使用jaxb方式。

Spring MVC对象转换说明的更多相关文章

  1. spring mvc日期转换(前端到后端,后端到前端)

    在做web开发的时候,页面传入的都是String类型,SpringMVC可以对一些基本的类型进行转换,但是对于日期类的转换可能就需要我们配置. 1.如果查询类使我们自己写,那么在属性前面加上@Date ...

  2. spring mvc 对象型参数的传递(遇到坑了)

    直接来个列子: 这里设置了,contenType="application/json" 这里post 接收的参数对象. 但是问题来了: <html> <head& ...

  3. Spring mvc 时间转换

    http://www.cnblogs.com/ssslinppp/p/4600043.html

  4. spring mvc 接受多对象的处置

    spring mvc 接受多对象的处理 spring mvc感觉非常好用,尤其是对接收对象參数的自己主动绑定非常简便,但对于同一时候传多个对象时有些困扰. 同一时候项目并没有直接使用spring的fo ...

  5. Spring MVC 后端获取前端提交的json格式字符串并直接转换成control方法对应的参数对象

    场景: 在web应用开发中,spring mvc凭借出现的性能和良好的可扩展性,导致使用日渐增多,成为事实标准,在日常的开发过程中,有一个很常见的场景:即前端通过ajax提交方式,提交参数为一个jso ...

  6. spring mvc各种常见类型参数绑定方式以及json字符串绑定对象

    在使用spring mvc作为框架的时候,为了规范,我们通常希望客户端的请求参数符合规范直接通过DTO的方式从客户端提交到服务端,以便保持规范的一致性,除了很简单的情况使用RequestParam映射 ...

  7. spring MVC 如何接收前台传入的JSON对象数组并处理

    spring MVC 如何接收前台传入的JSON对象数组 主要方法: (主要用到的包是 net.sf.json  即:json-lib-2.3-jdk15.jar 完整相关jar包: commons- ...

  8. Spring MVC 自动为对象注入枚举类型

    原文地址:http://1358440610-qq-com.iteye.com/blog/2079048 如果一个对象里面有枚举类型的话,则Spring MVC是不能够直接进行注入的,因为它只实现了一 ...

  9. spring MVC 如何接收前台传入的JSON对象数组

    spring MVC 如何接收前台传入的JSON对象数组 主要方法: (主要用到的包是 net.sf.json  即:json-lib-2.3-jdk15.jar 完整相关jar包: commons- ...

随机推荐

  1. android的原理--为什么我们不需要手动关闭程序

    内容搜集自网络,有所删改       不用在意剩余内存的大小,其实很多人都是把使用其他系统的习惯带过来来了.android大多应用没有退出的设计其实是有道理的,这和系统对进程的调度机制有关系.如果你知 ...

  2. Linux下串口编程入门

    简介: Linux操作系统从一开始就对串行口提供了很好的支持,本文就Linux下的串行口通讯编程进行简单的介绍. 串口简介  串行口是计算机一种常用的接口,具有连接线少,通讯简单,得到广泛的使用.常用 ...

  3. tyvj1297 小气的小B

    描述 其实你们都不知道,小B是很小气的.一天小B带着他的弟弟小B'一起去摘果子,走着走着,他们忽然发现了一颗长满了果子的树.由于弟弟长得太矮了,弟弟只有让哥哥小B帮他摘一些果子下来.哥哥小B说:&qu ...

  4. unix c 04

      系统调用(System Call)   文件的操作函数(Unix/Liunx系统内部提供的函数)   time 可以查看程序的运行时间,包括用户层时间和系统层的时间.   系统调用其实就是一系列的 ...

  5. sae-v2ex 一个运行在SAE上的类似v2ex的轻型python论坛 - 技术讨论 - 云计算开发者社区 - Powered by Discuz!

    sae-v2ex 一个运行在SAE上的类似v2ex的轻型python论坛 - 技术讨论 - 云计算开发者社区 - Powered by Discuz! sae-v2ex 一个运行在SAE上的类似v2e ...

  6. Spring MVC基础

    1.Web MVC基础 MVC的本质是表现层模式,我们以视图模型为中心,将视图和控制器分离出来.就如同分层模式一样,我们以业务逻辑为中心,把表现层和数据访问层代码分离出来是一样的方法.框架只能在技术层 ...

  7. 第10讲- UI线程阻塞及其优化

    第10讲UI线程阻塞及其优化 .UI 阻塞demo (首先在activity_main.xml中放置两个button,分别命名为button1,button2) //首先设置一个button1用来进行 ...

  8. [转载]Vertica “ERROR: Too many ROS containers exist”

    最近在用Vertica的时候碰到一个问题,Vertica在运行了一段时间后总是出现类似下面的错误 1: java.sql.SQLException: [Vertica][VJDBC](5065) 2: ...

  9. linux下修改防火墙端口对外开放方法

    ---linix CentOS7的防火墙换成了firewall了,这里做一些记录,下面是一些命令:添加例外端口:# firewall-cmd --add-port=8080/tcp删除例外端口:# f ...

  10. Android 4.4前后版本读取图库图片和拍照完美解决方案

    转载:http://blog.csdn.net/zbjdsbj/article/details/42387551 4.3或以下,选了图片之后,根据Uri来做处理,很多帖子都有了,我就不详细说了. 主要 ...