Spring MVC 實現(xiàn) JSON 序列化
1. 前言
WEB 項目,后端使用 JAVA 語言系,前端使用 JS 語言系。兩種語言有各自的語法和數(shù)據(jù)類型,不能直接進行數(shù)據(jù)交換,這便是所謂的異構化系統(tǒng)數(shù)據(jù)通信的問題。
異構化系統(tǒng)中數(shù)據(jù)通信的基本解決思路是:借助所有語言都能識別的中間語言,如 XML、JSON…… 進行數(shù)據(jù)交換。
本節(jié)課就和大家聊聊控制器是如何把數(shù)據(jù)以 JSON 的格式傳遞給瀏覽器。本節(jié)課程,需要重點理解并掌握 @ResponseBody 注解的作用。
2. @ResponseBody
WEB 應用程序中,控制器處理過的數(shù)據(jù),一般都是通過視圖技術渲染成 HTML 后交給瀏覽器進行解析。最近幾年,項目整體結構流行采用前后端分離模式。
什么是前后端分離結構?
傳統(tǒng)項目,數(shù)據(jù)由后臺完全處理,前端頁面僅僅用來顯示結果數(shù)據(jù)。
所謂前后端分離,會把一部分數(shù)據(jù)邏輯交給前端處理。也就意味著,交給前端的數(shù)據(jù)僅僅只是半成品數(shù)據(jù),需要前端語言如 JS 進一步處理后再交給 HTML 顯示。
后端一般選擇以 JSON 的格式向前端進行數(shù)據(jù)傳遞。Spriing MVC 可以使用 @ResponseBody 完成這個操作。@ResponseBody 是 Spring MVC 提供的一個很有意思的注解,一般放置在控制器方法的前面。
2.1 返回字符串
給出一個控制器的實例代碼,這個代碼很普通,不同之處在于方法前面使用了 @ResponseBody 注解。 于是,這個方法的命運被改變了。
@Controller
@RequestMapping("/json")
public class JsonAction {
@RequestMapping("/test01")
@ResponseBody
public String testJson() {
return "Hello";
}
}
控制器方法有 @ResponseBody 注解和沒有此注解,Spring MVC 對控制器方法的返回值的理解迥然不同。
- 沒有 @ResponseBody 注解:Spring MVC 會把返回值 “hello” 理解為視圖邏輯名,通過視圖解析器找到視圖物理位置;
- 有 @ResponseBody 注解: Spring MVC 會把返回值直接寫入響應包后交給瀏覽器。意味著不需要視圖解析器的參與。
測試一下上面實例。
打開瀏覽器,在地址欄上輸入:http://localhost:8888/sm-demo/json/test01 。
你在瀏覽器將看到如下圖所示結果:
2.2 返回對象
JAVA 中的數(shù)據(jù)很多時候都是以 OOP 的形式存在的,如學生對象數(shù)據(jù)、老師對象數(shù)據(jù)、用戶對象數(shù)據(jù)……
那么,控制器中的方法能不能直接把數(shù)據(jù)以對象為單位寫入響應包后返回給瀏覽器了?
如下面的實例:
@RequestMapping("/test02")
@ResponseBody
public User testJson01() {
return new User("mk", "123");
}
打開瀏覽器,在地址欄上輸入:http://localhost:8888/sm-demo/json/test02 。
在瀏覽器你將看到如下圖所示結果:
拋異常了。對于出錯,大家應該有預感。User 是 JAVA 語言中的類類型,對于瀏覽器而言對它的了解是一片空白。但是,為什么前面返回字符串時卻可以了?
那是因為字符串也是一種通用類型,瀏覽器沒有不認識的道理,但是,User 類型,瀏覽器只能摸后腦勺了。
如果想讓瀏覽器識別出 User 類型數(shù)據(jù)。想想也簡單,自己編碼,把對象數(shù)據(jù)轉(zhuǎn)換成字符串格式。
@RequestMapping("/test03")
@ResponseBody
public String testJson03() {
User user=new User("mk", "123");
return user.getUserName()+","+user.getUserPassword();
}
經(jīng)過上面的修改后,瀏覽器中能顯示出數(shù)據(jù)。但是,這里會有 2 個問題需要思考一下:
- 如前所述,前后端分離最主要的思想是讓前端承擔一部分數(shù)據(jù)業(yè)務邏輯。一串沒有特定格式的字符串傳遞給前端,真要交給 JS 處理,你還真不怕 JS 煩心,你叫它如何從中識別出誰是誰;
- 直接返回值給瀏覽器之前,需要通過手工編碼的方式把 OOP 數(shù)據(jù)格式轉(zhuǎn)換成字符串,這番折騰,勞心勞力。
好!先解決第一個問題。字符串數(shù)據(jù)類型是非結構化的,但是,可以把它轉(zhuǎn)換成具有特定結構格式的 JSON 字符串。
@RequestMapping("/test04")
@ResponseBody
public String testJson04() {
User user = new User("mk", "123");
String json = "{\"userName\":\"" + user.getUserName() + "\",\"userPassWord\":" + "\""
+ user.getUserPassword() + "\"" + "}";
return json;
}
打開瀏覽器,地址欄中輸入 http://localhost:8888/sm-demo/json/test04 。
瀏覽器中將顯示如下信息:
傳遞給瀏覽器的雖然還是字符串,但是是具有特定格式的 JSON 字符串,如果要交給 JS 處理,JS 表示很開心。
是的,數(shù)據(jù)格式的問題解決了,但是,編碼的工作量增加了很多。
其實,你所想要的結果,Spring MVC 能輕松幫你實現(xiàn)。
3. Spring MVC 和 JSON
使用 JAVA 作為開發(fā)語言,Spring MVC 自然知道數(shù)據(jù)以對象的形式存在是正道。對于如何把后端的對象數(shù)據(jù)傳遞給前端,Spring MVC 有一套優(yōu)雅的解決方案。
只需要簡簡單單的 2 步操作,便可以讓開發(fā)者省心省力的把 OOP 數(shù)據(jù)序列化成 JSON 格式后響應給瀏覽器。
- 打開項目中的 WebConfig 類文件,在其中添加如下代碼;
@Bean
public MappingJackson2HttpMessageConverter mappConverter() {
MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter=new MappingJackson2HttpMessageConverter();
return mappingJackson2HttpMessageConverter;
}
Tips: 顧名思義,MappingJackson2HttpMessageConverter 就是一個消息轉(zhuǎn)換器,其作用就是把數(shù)據(jù)映射成 JSON 格式。
- Spring MVC 默認情況下使用的是 jackson 插件完成具體的 JSON 格式序列化。打開 pom.xml 文件,在其中添加 jackson 依賴。
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.10.0</version>
</dependency>
有了上面配置后,幾乎不需要再做任何多余的事情,便能夠把控制器中的 OOP 數(shù)據(jù)以 JOSN 方式序列化給瀏覽器。
測試下面的控制器方法實例:
@RequestMapping("/test02")
@ResponseBody
public User testJson02() {
return new User("mk", "123");
}
控制器方法中直接返回一個對象,不用擔心,Spring MVC 會自動轉(zhuǎn)換成 JOSN 格式后發(fā)送給瀏覽器,不信,可以試一下。
再查看瀏覽器中的結果。
是不是顯示的很漂亮。
4. 小結
本節(jié)課程和大家一起講解了如何在控制器中把 OOP 數(shù)據(jù)轉(zhuǎn)換成 JSON 格式后傳遞給瀏覽器。開發(fā)者可以自己編碼把對象數(shù)據(jù)轉(zhuǎn)換成特定格式的字符串后響應給瀏覽器,但是,這個過程很勞心勞力。
使用 Spring MVC 框架提供的 JSON 序列化轉(zhuǎn)換組件,開發(fā)者不用關心底層具體轉(zhuǎn)換過程便能達到目的??蚣軒烷_發(fā)者解決了很多共性的問題,讓開發(fā)者可以有更多時間關注自己的核心邏輯。
記??!@ResponseBody 注解很重要。