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. 編寫測試檔案
下面是我們的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方法 }
下面是我們的控制層測試檔案:
@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的基礎上進一步對相應資訊進行封裝,如修改一些相應頭資訊等
- 關於以上的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] - 對於以上的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"}
- 關於以上的getUser()getUser1()能將我們的json字串轉換為相應的物件,我們可以任何引數名輸入:
選擇合適的資料轉換器
在前面講解中,我們通過AnnotationMethodHandlerAdapter註冊了眾多的資料轉換器,而spring會針對不同的請求響應媒體型別,spring會為我們選擇最恰當的資料轉換器,它是按以下流程進行尋找的:
- 首先獲取註冊的所有HttpMessageConverter集合
- 然後客戶端的請求header中尋找客戶端可接收的型別,比如 Accept application/json,application/xml等,組成一個集合
- 所有的HttpMessageConverter 都有canRead和canWrite方法 返回值都是boolean,看這個HttpMessageConverter是否支援當前請求的讀與寫,讀對應@RequestBody註解, 寫對應@ResponseBody註解
- 遍歷HttpMessageConverter集合與前面獲取可接受型別進行匹配,如果匹配直接使用當前第一個匹配的HttpMessageConverter,然後return(一般是通過Accept和返回值物件的型別進行匹配)