AJAX

一、概念

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技术实现了搜索功能,无论怎么搜索,页面都不会全部刷新。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值