1. 程式人生 > >springMVC4(4)json與物件互轉例項解析請求響應資料轉換器

springMVC4(4)json與物件互轉例項解析請求響應資料轉換器

格式化資料輸入輸出

Spring3.0的重要介面:HttpMessageConveter為我們提供了強大的資料轉換功能,將我們的請求資料轉換為一個java物件,或將java物件轉化為特定格式輸出等。比如我們常見的從前端登錄檔單獲取json資料並轉化為User物件,或前端獲取使用者資訊,後端輸出User物件轉換為json格式傳輸給前端等。

spring 為我們提供了眾多的HttpMessageConveter實現類,其中我們可能用得最多的三個實現類是:

實現類 功能
FormHttpMessageConverter 從請求和響應讀取/編寫表單資料。預設情況下,它讀取媒體型別 application/x-www-form-urlencoded 並將資料寫入MultiValueMap<String,String>
MarshallingHttpMessageConverter 使用 Spring 的 marshaller/un-marshaller 讀取/編寫 XML 資料。它轉換媒體型別為 application/xml
MappingJacksonHttpMessageConverter 使用 Jackson 的 ObjectMapper 讀取/編寫 JSON 資料。它轉換媒體型別為application/json

轉換器的裝配方式有兩種,一種是通過註冊org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter來裝配messageConverters,如下所示:

<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
    <property name="messageConverters"><!-- 裝配資料轉換器 -->
        <list>
            <ref bean="jsonConverter" /><!-- 指定裝配json格式的資料轉換器 -->
        </list>
    </property
>
</bean> <bean id="jsonConverter" class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"> <!-- 使用MappingJacksonHttpMessageConverter完成json資料轉換 --> <property name="supportedMediaTypes" value="application/json" /> <!-- 設定轉換的media型別為application/json --> </bean>>

另一種是啟用註解<mvc:annotation-driven />
該註解會會初始化7個轉換器:
- ByteArrayHttpMessageConverter
- StringHttpMessageConverter
- ResourceHttpMessageConverter
- SourceHttpMessageConverter
- XmlAwareFormHttpMessageConverter
- Jaxb2RootElementHttpMessageConverter
- MappingJacksonHttpMessageConverter

通過以上兩種方法,我們即可完成我們的轉換器註冊。
但我們想要在控制層完成資料的輸入輸出轉換,需要通過下列途徑:
1. 使用@RequestBody和@ResponseBody對處理方法進行標註。其中@RequestBody通過合適的HttpMessageConverter將HTTP請求正文轉換為我們需要的物件內容。而@ResponseBody則將我們的物件內容通過合適的HttpMessageConverter轉換後作為HTTP響應的正文輸出。
2. 使用HttpEntity、ResponseEntity作為處理方法的入參或返回值

例項分析

通過以上講解,我們已經有足夠的知識準備,來完成我們的例項:將json資料轉換為合適的java物件輸入,並將java物件轉換為符合格式的json字元輸出:

1. 匯入需要的jar包

裝配MappingJacksonHttpMessageConverter需要我們的jackson相關jar包,我們使用maven來管理專案,在pom.xml中配置如下資訊:

<dependency>
    <groupId>org.codehaus.jackson</groupId>
    <artifactId>jackson-core-asl</artifactId>
    <version>1.9.2</version>
</dependency>
<dependency>
    <groupId>org.codehaus.jackson</groupId>
    <artifactId>jackson-mapper-asl</artifactId>
    <version>1.9.2</version>
</dependency>

2. 裝配MappingJacksonHttpMessageConverter

這裡我們使用上面提到的方式二更為便利,在spring容器中加入:
<mvc:annotation-driven />

關於springMVC所需的其他配置,可參考我的另一篇文章,或通過文尾的原始碼下載獲取

3. 編寫測試檔案

  1. 下面是我們的User POJO測試類

    public class User {
        private Integer id;
        private String userName;
        private String password;
    
        @Override
        public String toString() {
            return "User [id=" + id + ", userName=" + userName + ", password="
                    + password + "]";
        }
        //忽略每個引數的get和set方法
    }
  2. 下面是我們的控制層測試檔案:

    @Controller
    @RequestMapping("/user")
    public class UserController {
        @RequestMapping("getUser")
        public void getUser( @RequestBody User user){//將輸入資料轉化為User物件
            System.out.println(user);
        }
    
        @RequestMapping("getUser1")
        public void getUser1( HttpEntity<User> userEntity){//將輸入資料轉化為User物件
            System.out.println(userEntity.getBody());
        }
        @ResponseBody//將輸出的java物件轉換為合適的相應正文輸出
        @RequestMapping("getUser2")
        public User getUser2(User user){
            System.out.println(user);
            return user;
        }
        @RequestMapping("getUser3")
        public HttpEntity<User> getUser3(User user){
            System.out.println(user);
            HttpEntity<User> uEntity = new HttpEntity<User>(user);
            return uEntity;
        }
    }

    上面分別展示了註解和HttpEntity的用法。關於HttpResponse只是在HtppEntity的基礎上進一步對相應資訊進行封裝,如修改一些相應頭資訊等

    1. 關於以上的getUser()getUser1()能將我們的json字串轉換為相應的物件,我們可以任何引數名輸入:
      {“id”:10,”password”:”myPassword”,”userName”:”myUserName”}
      在這裡我們需要的是需將請求頭的contentType設定為”application/json;UTF-8“。這樣spring才能找到對應的json解析器對我們的json字串進行解析。否則會報錯誤:415 Unsupported Media Type
      程式中方法呼叫User的toString()在控制檯列印欄位:
      User [id=10, userName=asd, password=qwe]
    2. 對於以上的getUser2()和getUser3()方法,我們訪問如:
      http://localhost:8080/springMVC/user/getUser3?id=10&password=qwe&userName=asd。然後spring會幫我們自動將引數對應User物件的屬性名繫結到方法入參的user物件中(關於複雜物件、集合繫結可參考我後面系列的文章)。根據上面url傳入的引數,spring自動將我們的User物件轉換為json格式字串輸出,內容如下:
      {"id":10,"userName":"asd","password":"qwe"}

選擇合適的資料轉換器

在前面講解中,我們通過AnnotationMethodHandlerAdapter註冊了眾多的資料轉換器,而spring會針對不同的請求響應媒體型別,spring會為我們選擇最恰當的資料轉換器,它是按以下流程進行尋找的:

  1. 首先獲取註冊的所有HttpMessageConverter集合
  2. 然後客戶端的請求header中尋找客戶端可接收的型別,比如 Accept application/json,application/xml等,組成一個集合
  3. 所有的HttpMessageConverter 都有canRead和canWrite方法 返回值都是boolean,看這個HttpMessageConverter是否支援當前請求的讀與寫,讀對應@RequestBody註解, 寫對應@ResponseBody註解
  4. 遍歷HttpMessageConverter集合與前面獲取可接受型別進行匹配,如果匹配直接使用當前第一個匹配的HttpMessageConverter,然後return(一般是通過Accept和返回值物件的型別進行匹配)

原始碼下載