在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方式。