一、概念
Ajax是Web开发一个流行的词汇,全称Asynchronous JavaScript and XML,异步的JavaScript和XML。是几种技术的强强联合。
Ajax如何工作?
Ajax(既异步 JavaScript 和XML)是一种Web 应用程序开发的手段,它采用客户端脚本和Web服务器交换数据。
为什么要学习Ajax?
使用Ajax的最大优点,就是能在不更新整个页面的前提下维护数据。这使用Web应用程序更为迅捷地回应用户动作,并避免了在网络上发送那些没有改变过的信息。
二、发送Ajax请求XMLHttpRequest对象简介
XMLHttpRequest对象是整个Ajax开发的基础(它是一个js对象,不是java对象)
它为我们提供如下功能:
1.提供客户端和服务器异步通信的能力
2.能够向服务器发出请求
3.能够接受服务器的返回页面
为了应对所有的现代浏览器,包括IE5和IE6,请检查浏览器是否支持XMLHttpRequest对象。如果支持,则创建HXLHttpRequest对象。如果不支持则创建ActiveXObject
创建:
// 创建xmlhttp对象
var xmlhttp;if (window.XMLHttpRequest) { // code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp = new XMLHttpRequest();
} else { // code for IE6, IE5
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
}
发送请求:
示例:
<!DOCTYPE>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>局部刷新</title>
<script type="text/javascript">
function ajax() {
// 创建xmlhttp对象
var xmlhttp;
if (window.XMLHttpRequest) {// code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp = new XMLHttpRequest();
} else {// code for IE6, IE5
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
}
/*
回调函数,方法体中接收JSON字符并解析成JSON对象,
创建节点插入数据一系列操作都在此方法中实现。
*/
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
// 接收JSON字符串
var jsonStr = xmlhttp.responseText;
// 转换成Json对象
var jsonObj = JSON.parse(jsonStr);
// 获取table
var table = document.getElementById("tb");
// 清除所有数据行,重新渲染table
var dataTr = document.getElementsByName("dataTr");
// 需要先获取长度,再去遍历删除。
var dataTrLength = dataTr.length;
for (var i = 0; i < dataTrLength; i++) {
table.removeChild(dataTr[0]);
}
// 生成dom节点(tr td)插入到table中
for ( var i = 0; i < jsonObj.length; i++) {
var foodName = document.createElement("td");
foodName.innerHTML=jsonObj[i].foodName;
var price = document.createElement("td");
price.innerHTML = jsonObj[i].price;
var foodId = document.createElement("td");
foodId.innerHTML = jsonObj[i].foodId;
var tr = document.createElement("tr");
tr.setAttribute("name" , "dataTr");
tr.appendChild(foodName);
tr.appendChild(price);
tr.appendChild(foodId);
// 插入table
table.appendChild(tr);
}
}
}
// 发送请求
var foodName = document.getElementsByName("foodName")[0].value;
xmlhttp.open("GET","${pageContext.request.contextPath}/query?foodName="+ foodName, true);
xmlhttp.send();
}
</script>
<style type="text/css">
body {
margin: 10 10;
}
table {
margin-top: 10px; width : 500px;
border: 1px solid black;
width: 500px;
}
td {
border: 1px solid black;
padding-left: 5px;
}
th {
border: 1px solid black;
}
</style>
</head>
<body>
<input type="text" name="foodName" placeholder="请输入菜品名...">
<input type="button" value="搜索" onclick="ajax()">
<table id="tb">
<tr>
<th>菜名</th>
<th>价格</th>
<th>编号</th>
</tr>
</table>
</body>
</html>
注意:AJAX的意义在于局部刷新,所以搜索框不能是表单+submit按钮了,而是文本框+button,然后在JS中直接获取DOM节点中值往服务器提交。
这里还涉及到很重要的一个知识点:onreadystatechange 事件 W3School解释很清楚:
这个方法会在一次请求中被触发5次,分别对应(0 -4)五个状态码。一次Ajax请求是否执行完成,就可以通过onreadystatechange事件来判断。
0:请求末初始化(没有调用send方法)
1:服务器连接已建立(socket已建立)
2:请求已接收(获取到了参数,服务器还没有执行action)
3:请求处理中(服务器在执行action方法,未执行完)
4:请求已完成,且相应已就绪(已经响应,并且能够获取到最终的数据)。
AJAX异步同步的区别?
异步:类似多线程一样,send方法执行完了之后,不会等待onreadystatechange结束。而是使用另外一条线程继续执行send下面的脚本,或者继续渲染页面。
同步:会等待onreadystatechange事件结束之后才继续往下执行或者渲染页面,期间页面会进入假死状态,当然,如果执行的速度很快,也感受不到假死。
注意:但是AJAX的精髓就在于局部刷新,异步请求。所以尽量使用异步模式(true),防假死。尽量将获取数据后的逻辑处理(页面渲染等)放在回调函数中(xmlhttp.onreadystatechange=function()).
action方法:
/**
* 1.原始的输出json方式
* OutputStream os;
* os.write(通过第三方json-lib转换的json字符串.getByte())
*/
@RequestMapping(value="/queryFood",method=RequestMethod.GET)
public String queryFood(String foodname,OutputStream os) throws Exception{
List<Map<String,Object>> queryAllFood = mdi.queryAllFood(foodname);
JSONArray arry = JSONArray.fromObject(queryAllFood);
String jsonStr = arry.toString();
os.write(jsonStr.getBytes("UTF-8"));
return null;
}
/**
* 2.直接返回 字符数组 + @ResponseBody
* 减少流的输出动作代码
* os.write(jsonStr.getBytes("UTF-8"));
*/
@ResponseBody
@RequestMapping(value="/queryFoodReturn",method={RequestMethod.GET})
public byte[] queryFoodReturn(String foodname) throws Exception{
List<Map<String, Object>> queryAllFood = mdi.queryAllFood(foodname);
JSONArray arry=JSONArray.fromObject(queryAllFood);
String jsonStr=arry.toString();
return jsonStr.getBytes("UTF-8");
}
/**
* 3.直接返回对象 springmvc自动转换成json
*/
@ResponseBody
@RequestMapping(value="/queryFoodList",method={RequestMethod.GET})
public List<Map<String, Object>> queryFoodList(String foodname) throws Exception{
List<Map<String, Object>> queryAllFood = mdi.queryAllFood(foodname);
return queryAllFood;
}
如果使用第三种直接返回对象需要配置消息转换器
<!-- 将springmvc注解的action交给springmvc处理 -->
<mvc:annotation-driven validator="localValidatorFactoryBean">
<mvc:message-converters>
<!-- 配置byte解析成json的消息转换器 -->
<bean class="org.springframework.http.converter.ByteArrayHttpMessageConverter">
<property name="supportedMediaTypes">
<list>
<value>text/html</value>
<value>application/x-www-form-urlencoded</value>
</list>
</property>
</bean>
<!-- 配置返回对象解析成json的消息转换器 -->
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="supportedMediaTypes">
<list>
<!-- 设置响应支持的类型 -->
<value>text/html</value>
<!-- 设置请求body支持的类型 -->
<value>application/x-www-form-urlencoded</value>
</list>
</property>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
service方法:
/**
* 根据菜品名模糊查询菜品信息,dao层返回List<Food>结构的结果集,
* 此方法负责将结果集转换成JSONString,返回给Controller层
* @param foodName
* @return
*/
public String queryFoodsByName(String foodName){
List<Food> list = dao.queryFoodsByName(foodName);
JSONArray array = JSONArray.fromObject(list);
return array.toString();
}
现在绝大部分使用AJAX实现都是用JSON作为数据载体了,XML文件确定很明显:体积过于庞大。
dao层方法:
/**
* 根据菜品名模糊查询
* @param foodName
* @return
*/
public List<Food> queryFoodsByName(String foodName){
String sql = "select foodid , foodname , price from food where foodname like '%" + foodName + "%'";
List<Food> list = template.query(sql, new Food());
return list;
}
所需依赖
<!-- Springmvc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>4.2.0.RELEASE</version>
</dependency>
<!-- jdbc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>4.2.0.RELEASE</version>
</dependency>
<!-- mysql数据库 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.26</version>
</dependency>
<!--jsr303验证框架 -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>4.3.2.Final</version>
</dependency>
<!-- json依赖 -->
<dependency>
<groupId>net.sf.json-lib</groupId>
<artifactId>json-lib</artifactId>
<version>2.4</version>
<classifier>jdk15</classifier>
</dependency>
<!-- 添加jackson的json解析器 -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.8.9</version>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
<version>1.9.13</version>
</dependency>
运行结果( 点击搜索按钮后 ):
至此,就用AJAX技术实现了搜索功能,无论怎么搜索,页面都不会全部刷新。