在Spring MVC以前咱们须要在Servlet里处理HttpServletRequest参数对象,但这个对象里的属性都是通用类型的对象(如字符串),处理起来很繁琐而且容易出错,而Spring MVC容许咱们直接把参数和返回值定义为对象,好比:git
先定义一个对象:github
@Data public class User { private String id; private String name; }
而后定义一个Spring MVC方法:spring
@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方法。json
除把参数定义为对象外,返回值也能为对象:app
@RequestMapping(value = "/find-user", method = RequestMethod.GET) @ResponseBody public User findUser() { return new User("01", "yw"); }
返回值对象须要加@ResponseBody注解,该注解通知Spring MVC把返回值对象转换为字符串,并做为http响应消息中的body部分。curl
除@RequestBody、@ResponseBody注解外,Spring MVC还提供了其它注解,具体请参见相关文档说明。ide
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":"01","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>02</id><name>yw</name></xml>
Jackson XML
上面说到,Spring MVC支持jackson-databind-xml做为xml转换器,并实际测试获得返回的xml:
<User xmlns=""><id>01</id><name>yw</name></xml>
其中有 xmlns="" 。该xmlns并没有什么反作用,但若是你很在乎必定要去掉它则可增长依赖项:
<dependency> <groupId>com.fasterxml.woodstox</groupId> <artifactId>woodstox-core</artifactId> <version>5.0.2</version> </dependency>
其缘由请参见[FasterXML讨论](https://github.com/FasterXML/jackson-dataformat-xml/issues/32)。
面向对象
上面咱们花了不少篇幅介绍了json和xml,但Spring MVC给咱们带来的好处却在于让咱们忽视它们的存在,让咱们只关注对象,无需去考虑对象是从json来的仍是从xml来的,这些底层的事就交给Spring MVC去处理吧。同时,直接把咱们本身的对象做为参数和返回值也使得单元测试更容易写。
练习
一、若是你的系统同时有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":"01","name":"yw"}
二、本说明文档介绍了用Jackson-Xml做为Xml转换器,同时说到你也能够用jaxb进行Xml转换。请改成使用jaxb方式。