服務器響應的正文格式--JSON格式
JSON是一種輕量級的數據交換格式。它基於 ECMAScript (歐洲計算機協會制定的js規範)的一個子集,採用完全獨立於編程語言的文本格式來存儲和表示數據。簡潔和清晰的層次結構使得 JSON成爲理想的數據交換語言。易於人閱讀和編寫,同時也易於機器解析和生成,並有效地提升網絡傳輸效率。
通常,服務器向客戶端響應的數據可能不只是1個數據,以登錄操作爲例,也許可以響應爲1
表示登錄成功,使用2
表示登錄失敗且是因爲用戶名錯誤,使用3
表示密碼錯誤,則客戶端就可以通過對這個值的判斷,得知當前操作結果,但是,其它操作可能會需要更多的數據,例如“客戶端嘗試獲取當前登錄的用戶信息”,需要響應的數據可能包括:用戶名、手機號碼、電子郵箱、年齡等一系列數據,由於響應結果只是1個字符串,就需要把這些數據很好的組織起來,纔可以方便客戶端從這1個字符串中獲取其中某部分的數據,否則,如果只是響應爲"[email protected]"
這樣,客戶端就無法處理這個響應結果。
早期會使用XML語法來組織這些數據,如:
<user>
<username>Tom</username>
<age>26</age>
<address>BieJing</address>
<email>[email protected]</email>
</user>
使用XML會存在的問題:
1.解析難度較大 2.數據量略大,傳輸略慢,響應略慢,流量消耗略大,用戶體驗略差。
目前推薦使用組織數據的格式爲【Json】格式,那麼以上數據表示形式變爲:
{
"username":"Tom",
"age":26,
"address":"BeiJing",
"email":"[email protected]"
"skill":["Java","JS","JQ","SSM"],//加入數組
"department":{//加入Json對象
"id":"304",
"deptname":"HR",
}
}
Json是JavaScript默認識別的對象,可以直接得到其屬性
var json = {
"username":"Tom",
"age":26,
"address":"BeiJing",
"skill":["JAVA","JS","JQ","SSM"]
}
console.log(json.address);//BeiJing
console.log(json.skill[2]);//JQ
Json的格式
-
使用
{ }
表示對象,整個JSON數據就是1個對象; -
所有的屬性名都是【字符串】類型的,在JavaScript中,可以使用單引號或者雙引號包含,因爲Json數據可能在多種不同的編程語言中都出現,一般推薦使用雙引號,屬性值如果是字符串,也需要使用雙引號包含,如果是數值或者布爾值,則可以不用雙引號框柱,屬性名和屬性值使用【冒號】分隔,多個屬性的配置之間使用【逗號】分隔;
-
屬性值的類型還可以是數組,使用中括號
[]
框柱數組的各元素,各元素之間使用逗號,
分隔,在JavaScript中處理時,使用例如【json.skill
】就可以獲取到整個數組,使用【json.skill.length
】就可以獲取數組的長度,使用【json.skill[0]
】就可以獲取數組中下標爲0的元素,也可以使用循環語法進行循環; -
屬性值的類型還可以是另一個對象,使用
{ }
表示對象。
如果在JavaScript中,得到是一個使用Json語法組織的字符串,而不是Json對象,可以調用【JSON.parse(str)
】函數,將字符串轉換爲JSON對象。
var js = '{"username":"Tom"}';
console.log(js.username);//undefined
var jsn = JSON.parse(js);
console.log(jsn.username);//Tom
服務端如何實現響應Json格式數據
1.添加【jackson】依賴
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.8</version>
</dependency>
2.自定義響應結果類
public class JsonResult {
private Integer state;
private String message;
public Integer getState() {
return state;
}
public void setState(Integer state) {
this.state = state;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
3.修改返回值方法,返回上述自定義響應類型
@RequestMapping("login.do")
@ResponseBody
public JsonResult login(
@RequestParam("username") String username,
@RequestParam("password") String password) {
Integer state;
String message = null;
if ("root".equals(username)) {
if ("1234".equals(password)) {
state = 1;
} else {
state = 3;
message = "密碼錯誤!";
}
} else {
state = 2;
message = "用戶名不存在!";
}
JsonResult jsonResult = new JsonResult();
jsonResult.setState(state);
jsonResult.setMessage(message);
return jsonResult;
}
如果直接運行,會提示406錯誤:
HTTP Status 406 – Not Acceptable
需要在spring.xml中添加配置:
<!-- 註解驅動 -->
<mvc:annotation-driven />
然後,控制器中處理請求的方法響應的正文就是Json格式的字符串了。
在控制器中響應正文時,需要添加【@ResponseBody
】註解,SpringMVC框架內置了一系列的【轉換器Converter】,用於將方法的返回值轉換爲響應的正文,在這一系列的轉換器中,SpringMVC設計了對應關係和優先級,例如,當方法的返回值類型是【String
】時,就會自動調用【StringHttpMessageConverter
】,當項目中添加了【jackson-databind
】依賴時,如果方法的返回值類型是SpringMVC默認不識別的,就會自動使用Jackson
依賴中的轉換器!Jackson
依賴還會將響應頭(Response Headers)中的【Content-Type
】設置爲【application/json,charset=utf-8
】。
另外,介紹一個註解【@JsonInclude(value=Include.NON_NULL)】,針對響應的json字符串中包括許多爲【null】的屬性,可以在ui應的抒情之前添加該註解,則當屬性值爲null時,該屬性不會被序列化到Json字符串中,也可以將該註解添加在類的聲明之前,則該類中所有屬性均有對應的效果,如果希望項目中所有序列化json的過程都有這樣的效果,則可以在配置文件【application.properties】中添加如下配置:
spring.jackson.default-property-inclusion = NON_NULL
AJAX
AJAX = Asynchronous JavaScript and XML(異步的JavaScript和XML)。AJAX不是新的編程語言,而是一種使用現有標準的新方法。AJAX是與服務器交換數據並更新部分網頁的技術,在不重新加載整個頁面的情況下,實現局部數據刷新,如更換頁面驗證碼。在不重新加載整個頁面的情況下,重置登錄數據等。
在實際實現時,通常是基於jQuery框架實現AJAX訪問,主要是因爲原生技術的代碼比較繁瑣,且存在瀏覽器的兼容性問題,在jQuery中,定義了【$ajax()】函數,用於處理AJAX請求,調用該函數即可實現異步訪問:
<script type="text/javascript" src="jquery-3.4.1.min.js"></script>
<script type="text/javascript">
$("#btn-login").click(function(){
// $.ajax()函數的參數是1個JSON對象
// url:請求提交到哪裏
// data:需要提交的請求參數
// type:請求類型
// dataType:服務器端響應的數據類型,可以是text/xml/json,取值取決於Response Headers中的Content-Type
// success:服務器端HTTP響應碼是2xx時的回調(callback)函數,函數的參數就是服務器端響應的正文結果
$.ajax({
"url":"user/login.do",
"data":$("#form-login").serialize(),
"type":"post",
"dataType":"json",
"success":function(result) {
if (result.state == 1) {
alert("登錄成功!");
} else {
alert(result.message);
}
}
});
});
</script>
$("#form-login").serialize()方法要求,form表單中,各個提交的參數,名字要與服務器端保持一致,如input框的【name】屬性,服務器端要求傳入參數【username】,則name屬性也必須爲【name = “username”】。