Ajax实例讲解与技术原理
林炳文Evankaka原创作品。转载请注明出处http://www.52php.cn/tag/http://blog.csdn.net/evankaka 摘要:AJAX即“Asynchronous Javascript And XML”(异步JavaScript和XML),是指一种创建交互式网页应用的网页开发技术。AJAX 是一种用于创建快速动态网页的技术。通过在后台与服务器进行少量数据交换,AJAX 可以使网页实现异步更新。这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新。解决传统的网页(不使用 AJAX)如果需要更新内容,必须重载整个网页页面。 一、Ajax技术与原理
1.1、AjaxAJAX = Asynchronous JavaScript and XML(异步的 JavaScript 和 XML)。AJAX 不是新的编程语言,而是一种使用现有标准的新方法。 AJAX 是与服务器交换数据并更新部分网页的艺术,在不重新加载整个页面的情况下。 1.2、Ajax所包含的技术
大家都知道ajax并非一种新的技术,而是几种原有技术的结合体。它由下列技术组合而成。 1.使用CSS和XHTML来表示。 2. 使用DOM模型来交互和动态显示。 3.使用XMLHttpRequest来和服务器进行异步通信。 4.使用javascript来绑定和调用。 AJAX 的要点是 XMLHttpRequest 对象。 不同的浏览器创建 XMLHttpRequest 对象的方法是有差异的。 IE 浏览器使用 ActiveXObject,而其他的浏览器使用名为 XMLHttpRequest 的 JavaScript 内建对象1.3、Ajax的工作原理Ajax的核心是JavaScript对象XmlHttpRequest。该对象在Internet Explorer 5中首次引入,它是一种支持异步请求的技术。简而言之,XmlHttpRequest使您可以使用JavaScript向服务器提出请求并处理响应,而不阻塞用户。 来看看和传统方式的区别 再来看看它们各自的交互 浏览器的普通交互方式 浏览器的Ajax交互方式 在创建Web站点时,在客户端执行屏幕更新为用户提供了很大的灵活性。下面是使用Ajax可以完成的功能: 1.4、XMLHttpRequest 对象的三个常用的属性1. onreadystatechange 属性 xmlHttp.onreadystatechange=function() { // 我们需要在这里写一些代码 }2.readyState 属性 readyState 属性存有服务器响应的状态信息。每当 readyState 改变时,onreadystatechange 函数就会被执行。 readyState 属性可能的值: 状态 描述 0 请求未初始化(在调用 open() 之前) 1 请求已提出(调用 send() 之前) 2 请求已发送(这里通常可以从响应得到内容头部) 3 请求处理中(响应中通常有部分数据可用,但是服务器还没有完成响应) 4 请求已完成(可以访问服务器响应并使用它) 我们要向这个 onreadystatechange 函数添加一条 If 语句,来测试我们的响应是否已完成(意味着可获得数据): xmlHttp.onreadystatechange=function() { if(xmlHttp.readyState==4) { // 从服务器的response获得数据 } }3.responseText 属性 可以通过 responseText 属性来取回由服务器返回的数据。 在我们的代码中,我们将把时间文本框的值设置为等于 responseText: xmlHttp.onreadystatechange=function() { if(xmlHttp.readyState==4) { document.myForm.time.value=xmlHttp.responseText; } } 其它属性如下: 1.5、xmlhttprequst的方法1.open() 方法 xmlHttp.open("GET","test.php",true);2.send() 方法 send() 方法将请求送往服务器。如果我们假设 HTML 文件和 PHP 文件位于相同的目录,那么代码是这样的: xmlHttp.send(null); 具体看博文后面还有细讲。 其它方法如下: 二、Ajax编程步骤为了方便理解,我给AJAX统一了一个流程,要想实现AJAX,就要按照以后步骤走: (1)创建XMLHttp对象。 (2)设置请求方式。 (3)调用回调函数。 (4)发送请求。 下面来看下具体步骤: 2.1、创建XMLHttp对象创建XMLHttp对象的语法是: var xmlHttp=new XMLHttpRequest(); 如果是IE5或者IE6浏览器,则使用ActiveX对象,创建方法是: var xmlHttp=new ActiveXObject("Microsoft.XMLHTTP");一般我们手写AJAX的时候,首先要判断该浏览器是否支持XMLHttpRequest对象,如果支持则创建该对象,如果不支持则创建ActiveX对象。JS代码如下: //第一步:创建XMLHttpRequest对象 var xmlHttp; if (window.XMLHttpRequest) {//分浏览器创建XMLHttp对象 xmlHttp = new XMLHttpRequest(); } else if (window.ActiveXObject) { xmlHttp = new ActiveXObject("Microsoft.XMLHTTP") } 2.2、设置请求方式在WEB开发中,请求有两种形式,一个是get 一个是post,所以在这里需要设置一下具体使用哪个请求,XMLHttpRequest对象的open()方法就是来设置请求方式的。 如下: //第二步:设置和服务器端交互的相应参数 ,向路徑http://localhost:8080/JsLearning3/getAjax准备发送数据 var url="http://localhost:8080/JsLearning3/getAjax"; xmlHttp.open("POST",url,true); open方法如下: GET 还是 POST? 2.3、调用回调函数
如果在上一步中open方法的第三个参数选择的是true,那么当前就是异步请求,这个时候需要写一个回调函数,xmlHttp对象有一个onreadystatechange属性,这个属性返回的是一个匿名的方法,所以回调函数就在这里写xmlHttp.onreadystatechange=function{},function{}内部就是回调函数的内容。所谓回调函数,就是请求在后台处理完,再返回到前台所实现的功能。在这个例子里,我们的回调函数要实现的功能就是接收后台处理后反馈给前台的数据,然后将这个数据显示到指定的div上。因为从后台返回的数据可能是错误的,所以在回调函数中首先要判断后台返回的信息是否正确,如果正确才可以继续执行。代码如下: //第三步:注册回调方法 xmlHttp.onreadystatechange = function(){ if (xmlHttp.readyState == 4) { if (xmlHttp.status == 200) { var obj=document.getElementById(id); obj.innerHTML = xmlHttp.responseText; } else { alert("AJAX服务器返回错误!"); } } } 在上面代码中,xmlHttp.readyState是存有XMLHttpRequest 的状态。从 0 到 4 发生变化。0: 请求未初始化。1: 服务器连接已建立。2: 请求已接收。3: 请求处理中。4: 请求已完成,且响应已就绪。所以这里我们判断只有当xmlHttp.readyState为4的时候才可以继续执行。 xmlHttp.status是服务器返回的结果,其中200代表正确。404代表未找到页面,所以这里我们判断只有当xmlHttp.status等于200的时候才可以继续执行。 var obj=document.getElementById("testid"); obj.innerHTML = xmlHttp.responseText;这段代码就是回调函数的核心内容,就是获取后台返回的数据,然后将这个数据赋值给id为testid的div。xmlHttp对象有两个属性都可以获取后台返回的数据,分别是:responseText和responseXML,其中responseText是用来获得字符串形式的响应数据,responseXML是用来获得 XML 形式的响应数据。至于选择哪一个是取决于后台给返回的数据的,这个例子里我们只是显示一条字符串数据所以选择的是responseText。responseXML将会在以后的例子中介绍。 AJAX状态值与状态码区别 if(ajax.readyState == 4 && ajax.status == 200) {。。。。);}AJAX运行步骤与状态值说明 在AJAX实际运行当中,对于访问XMLHttpRequest(XHR)时并不是一次完成的,而是分别经历了多种状态后取得的结果,对于这种状态在AJAX中共有5种,分别是。 0 - (未初始化)还没有调用send()方法 1 - (载入)已调用send()方法,正在发送请求 2 - (载入完成)send()方法执行完成, 3 - (交互)正在解析响应内容 4 - (完成)响应内容解析完成,可以在客户端调用了 对于上面的状态,其中“0”状态是在定义后自动具有的状态值,而对于成功访问的状态(得到信息)我们大多数采用“4”进行判断。 AJAX状态码说明 1**:请求收到,继续处理 2**:操作成功收到,分析、接受 3**:完成此请求必须进一步处理 4**:请求包含一个错误语法或不能完成 5**:服务器执行一个完全有效请求失败 再具体就如下: 100——客户必须继续发出请求 2.4、发送请求//第四步:设置发送请求的内容和发送报送。然后发送请求 var params ="userName="+document.getElementsByName("userName")[0].value+"&userPass="+document.getElementsByName("userPass")[0].value+"&time="+ Math.random(); // 增加time随机参数,防止读取缓存 xmlHttp.setRequestHeader("Content-type","application/x-www-form-urlencoded;charset=UTF-8"); // 向请求添加 HTTP 头,POST如果有数据一定加加!!!! xmlHttp.send(params); 如果需要像 HTML 表单那样 POST 数据,请使用 setRequestHeader() 来添加 HTTP 头。然后在 send() 方法中规定您希望发送的数据: 三、应用实例Ajax+SpringMVC来实现实时数据的传递 工程免费下载 整个工程目录如下: 用到的JAR包如下: 下面再来具体讲清楚 1、首先是web.xml的配置,放在WEB-INF文件夹下 <?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0"> <display-name>JsLearning3</display-name> <welcome-file-list> <welcome-file>index.html</welcome-file> <welcome-file>index.htm</welcome-file> <welcome-file>index.jsp</welcome-file> <welcome-file>default.html</welcome-file> <welcome-file>default.htm</welcome-file> <welcome-file>default.jsp</welcome-file> </welcome-file-list> <!-- 统一设置编码,防止出现中文乱码 --> <filter> <filter-name>Set Character Encoding</filter-name> <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> <init-param> <param-name>encoding</param-name> <param-value>UTF-8</param-value> </init-param> </filter> <filter-mapping> <filter-name>Set Character Encoding</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <!-- SpringMVC的前端控制器 --> <servlet> <servlet-name>dispatcherServlet</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <!-- 设置自己定义的控制器xml文件 --> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath*:spring-servlet.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <!-- Spring MVC配置文件结束 --> <!-- 拦截设置 --> <servlet-mapping> <servlet-name>dispatcherServlet</servlet-name> <!-- 由SpringMVC拦截所有请求 --> <url-pattern>/</url-pattern> </servlet-mapping> <!-- webAppRootKey:值缺省为webapp.root,当tomcat下部署多个应用时(每个都用到了log4j), 每个应用的web.xml中都要配置该参数,该参数与Log4j.xml文件中的${webapp.root} 否则每个应用的webAppRootKey值都相同,就会引起冲突 --> <context-param> <param-name>webAppRootKey</param-name> <param-value>webApp.root</param-value> </context-param> <!-- log4jConfigLocation:log4j配置文件存放路径 --> <context-param> <param-name>log4jConfigLocation</param-name> <param-value>classpath:log4j.properties</param-value> </context-param> <!-- 3000表示 开一条watchdog线程每60秒扫描一下配置文件的变化;这样便于日志存放位置的改变 --> <context-param> <param-name>log4jRefreshInterval</param-name> <param-value>3000</param-value> </context-param> <listener> <listener-class>org.springframework.web.util.Log4jConfigListener</listener-class> </listener> </web-app> 2、接着配置SpringMVC的拦截规则spring-servlet.xml,放在src文件夹下 <beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xsi:schemaLocation=" http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd"> <!-- 把标记了@Controller注解的类转换为bean --> <context:component-scan base-package="com.lin.controller" /> <!-- 启动Spring MVC的注解功能,完成请求和注解POJO的映射 --> <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter" /> <!-- 对模型视图名称的解析,即在模型视图名称添加前后缀 --> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" p:prefix="/WEB-INF/views/" p:suffix=".jsp"/> </beans>3、使用是日记打印功能log4j,在src文件夹下新建log4j.properties,如果不需要,这一步也可以跳过 内容如下: log4j.rootLogger =DEBEG,stdout log4j.appender.stdout = org.apache.log4j.ConsoleAppender log4j.appender.stdout.Target = System.out log4j.appender.stdout.layout = org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern = [%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS} method:%l%n%m%n 4、Ajax的使用 在WEB-INF下新建view文件夹,然后新建一个first.jsp文件,内容如下: <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Insert title here</title> <script language="javascript"> /* *获取工程的路径 */ function getRootPath() { var pathName = window.location.pathname.substring(1); var webName = pathName == '' ? '' : pathName.substring(0,pathName .indexOf('/')); return window.location.protocol + '//' + window.location.host + '/' + webName + '/'; } /* *提交Ajax请求并处理返回数据 */ function sendAjax(id) { //第一步:创建XMLHttpRequest对象 var xmlHttp; if (window.XMLHttpRequest) {//分浏览器创建XMLHttp对象 xmlHttp = new XMLHttpRequest(); } else if (window.ActiveXObject) { xmlHttp = new ActiveXObject("Microsoft.XMLHTTP") } //第二步:设置和服务器端交互的相应参数 ,向路徑http://localhost:8080/JsLearning3/getAjax准备发送数据 var url=getRootPath()+"getAjax"; xmlHttp.open("POST",true); //第三步:注册回调方法 xmlHttp.onreadystatechange = function(){ if (xmlHttp.readyState == 4) { if (xmlHttp.status == 200) { var obj=document.getElementById(id); obj.innerHTML = xmlHttp.responseText; } else { alert("AJAX服务器返回错误!"); } } } //第四步:设置发送请求的内容和发送报送。然后发送请求 var params ="userName="+document.getElementsByName("userName")[0].value+"&userPass="+document.getElementsByName("userPass")[0].value+"&time="+ Math.random(); // 增加time随机参数,防止读取缓存 xmlHttp.setRequestHeader("Content-type","application/x-www-form-urlencoded;charset=UTF-8"); // 向请求添加 HTTP 头,POST如果有数据一定加加!!!! xmlHttp.send(params); } </script> </head> <body> <h3>用户注册</h3> 名称<input type="text" name="userName" id="" onblur="sendAjax('txtHintName')"/>你输入的用户名是:<span id="txtHintName"></span><br> 密码<input type="password" name="userPass" onblur="sendAjax('txtHintPass')"/> 你输入的密码是:<span id="txtHintPass"></span><br> </body> </html> 5、Controler控制器 package com.lin.controller; import java.io.IOException; import java.util.ArrayList; import java.util.List; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import net.sf.json.JSONArray; import org.apache.log4j.Logger; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; @Controller public class firstController { private static Logger logger = Logger.getLogger(firstController.class); @RequestMapping({"/first","/"}) public String getFirst(){ return "first"; } @RequestMapping({"/getAjax/**"}) public String getAjax(HttpServletRequest request,HttpServletResponse response) throws IOException{ String userName=(String)request.getParameter("userName"); String userPass=(String)request.getParameter("userPass"); System.out.println(userName); System.out.println(userPass); List<String> list=new ArrayList<String>(); list.add(userName); list.add(userPass); JSONArray json = JSONArray.fromObject(list); response.setCharacterEncoding("UTF-8"); response.flushBuffer(); response.getWriter().write(json.toString()); return null; } }这里用到了将提交过来的数据转到Json中去保存,处理各种请求,并设置Ajax的返回参数。 这里设置成了名称或密码输入栏只要一失去焦点事件,立马向服务端发送一个请求。 看到效果了没,传过来的是Json数组,第一个是用户名,第二个是密码。 我们可以看到,只要输入框一失去焦点事件,它就会立刻把数据提交,然后服务器再返回结果。这里我直接招原值返回了。想想看,其实很多注册时,用户名的重复验证就是这样做的,只不过是在Controller层中,加了对数据库的查询,以此来判断用户输入 的名称是否存在。然后再将结果返回。这个下一讲我们将来说明。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |