Spring MVC對象轉換說明

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

相關文章
相關標籤/搜索