### AJAX(json)
#### 1. 响应正文
在SpringMVC中,处理完请求之后,默认的响应方式是转发或重定向,这种操作会导致用户看到的界面会发生变化(将看到另一个页面),这种做法的缺陷在于:
1. 用户体验较差,例如操作失败时,不能直接在当前页面提示错误,只能用另一个页面来提示,当用户尝试再次操作时,需要先返回到原有页面,才可以进行下一次操作;
2. 产生的流量消耗较大,用于提示错误的页面,也是一个完整的页面,相对于只响应正文而言,流量的消耗会大很多,直接导致用户体验较差,并且流量费会增加;
3. 对多平台设备的兼容较差,如果服务器端响应的是一个html页面(含JSP),可能不适用于在手机端、平板电脑等其它设备上直接显示。
目前,主流的开发模式是**服务器端处理完请求之后,只向客户端响应正文(客户端应该得到的数据),由客户端(前端页面、Android APP、iOS APP及其它客户端软件)组织并呈现这些数据。**
如果需要服务器端处理请求时能响应正文,需要在处理请求的方法之前添加`@ResponseBody`注解,并在Spring的配置文件中,添加注解驱动`<mvc:annotation-driven />`。
添加了`@ResponseBody`注解的方法,其返回值就是将响应到客户端的数据。
#### 2. 响应正文的数据格式
服务器端响应给客户的数据应该是有数据格式的,否则,当客户端接收到响应结果时,可能无法分析出其中的数据意义,例如当客户端请求的是某个用户的资料,其中应该包含用户的名称、年龄、手机号码、电子邮箱等,这些数据如果组织在1个字符串中,没有特定的数据格式的话,客户端将无从解析,从中得到哪些是用户的名称,哪些是年龄等。
早期推荐使用XML组织数据的格式,例如:
<data>
<username>root</username>
<age>16</age>
<email>[email protected]</email>
</data>
当客户端接收到以上XML格式的字符串时,通过XML解析技术,就可以得到其中的用户名、年龄、邮箱。
目前推荐使用更加轻量级的JSON格式的数据,例如:
{
"username":"root",
"age":16,
"email":"[email protected]"
}
相比下之,JSON数据的优点在于:
1. 数据量较小;
2. 解析方便;
#### 3. JSON数据格式
**1. 整个JSON数据是1个对象,必须使用 {} 框住**
**2. JSON对象中可以有多个属性,每个属性的名称使用引号框住,属性值根据类型决定是否需要添加引号,数值型和布尔型的不需要添加引号,属性名与属性值之间使用冒号分隔,多个属性之间使用逗号分隔**
{
"username":"root",
"age":16,
"email":"[email protected]",
"is_delete":false
}
**3. 整个JSON中无视多余的空白(含若干数量的空格、换行、空白制表位等)**
**4. JSON数据中,某个属性的值可以是另一个对象,任何对象都使用大括号框住**
{
"username":"root",
"age":16,
"email":"[email protected]",
"is_delete":false,
"department": {
"id":9527,
"name":"UI"
}
}
**5. JSON数据中,某个属性的值可以是一系列的数据,即数组,都使用中括号框住**
{
"username":"root",
"age":16,
"email":"[email protected]",
"is_delete":false,
"department": {
"id":9527,
"name":"UI"
},
"phones": ["13800138000","13800138001","13800138002"]
}
**6. 各种复合类型的值可以互相嵌套,例如数组的元素也可以是对象,对象中再包含数组等**
#### 4. 在HTML页面中处理JSON
JavaScript语言支持读取JSON数据,例如:
<script type="text/javascript">
var json = {
"username":"root",
"age":18,
"hobby":["game","coding","run"],
"department":{
"id":7,
"name":"RD"
}
};
var username = json.username;
var age = json.age;
console.log("username=" + username);
console.log("age=" + age);
for (var i = 0; i < json.hobby.length; i++) {
console.log("hobby=" + json.hobby[i]);
}
console.log("department name=" + json.department.name)
</script>
对于客户端而言,往往得到的并不一定是JSON对象,而是服务器给回的JSON格式的字符串!通过`JSON.parse(str)`就可以把字符串类型的`str`数据转换回JSON对象。
#### 5. 在服务器端向客户端响应JSON数据
在服务器端添加`jackson-databind`依赖:
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.8</version>
</dependency>
当服务器端的控制器处理请求时,添加了`@ResponseBody`,即表示响应正文,则SpringMVC框架会根据匹配的converter将处理请求的方法的返回值转换为正文,如果返回值是`String`类型,则会自动使用`StringHttpMessageConverter`,还有一些其它内置的converter,如果方法的返回值类型不是SpringMVC默认就支持的(例如自定义的数据类型),则会自动使用jackson框架中的converter,而jackson框架中的converter就会将返回的对象组织为JSON格式。
应用jackson框架并不需要编写任何代码,也不需要添加任何配置。
通常,某个应用中,向客户端响应的数据格式应该是相对固定的,也就是说,无论是用户登录成功、登录失败、注册成功、注册失败、发表文章成功等任何操作,服务器向客户端响应的JSON的格式是相对固定的,都会包含某些特定的属性,表达特定的意义,以便于客户端处理。
所以,通常会在服务器端创建一个类,专门用于表示向客户端响应的数据的类型:
public class ResponseResult {
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;
}
}
#### 6. 异步请求
在页面中引用jQuery,然后,调用`$.ajax()`函数,即可发出请求,并获取响应结果!
$("#btn-reg").click(function(){
// 发出异常请求,并处理结果
// url:将请求提交到哪里去
// data:提交的请求参数,例如 username=root&password=1234
// type:提交方式
// dataType:服务器端即将响应的数据的类型,取值可以是"json"、"xml"、"text",例如服务器端响应的可能是application/json,该属性值应该是"json"
// success:当服务器成功响应时(Http响应码是2xx)的回调函数
$.ajax({
"url":"user/reg.do",
"data":"username=" + $("#username").val(),
"type":"POST",
"dataType":"json",
"success":function(json) {
alert(json.message);
}
});
});