470 likes | 556 Views
第十三章. Ajax 基础. Ajax 定义. Ajax (Asynchronous JavaScript and XML)不是一个新的技术,事实上,它是一些旧有的成熟的技术以一种全新的更加强大的方式整合在一起 Ajax的关键技术: 使用XHTML(HTML)和CSS构建标准化的展示层 使用DOM进行动态显示和交互 使用XML和XSLT进行数据交换和操纵 使用XMLHttpRequest异步获取数据 使用JavaScript将所有元素绑定在一起. 传统 Web 应用与 Ajax 应用的比较. 传统 Web 应用与 Ajax 应用的比较 (cont.).
E N D
第十三章 Ajax基础
Ajax定义 • Ajax (Asynchronous JavaScript and XML)不是一个新的技术,事实上,它是一些旧有的成熟的技术以一种全新的更加强大的方式整合在一起 • Ajax的关键技术: 使用XHTML(HTML)和CSS构建标准化的展示层 使用DOM进行动态显示和交互 使用XML和XSLT进行数据交换和操纵 使用XMLHttpRequest异步获取数据 使用JavaScript将所有元素绑定在一起
传统Web应用与Ajax应用的比较(cont.) • 在传统的Web应用模型下,大部分的用户操作都会发送一个HTTP请求给服务器,然后服务器开始处理(接收数据,执行业务逻辑,访问数据库等),最后向浏览器返回HTML页面。当服务器处理请求时,用户能够做什么呢?只有等待!
传统Web应用与Ajax应用的比较(cont.) • 在传统的Web应用模型下,客户机 (浏览器或者本地机器上运行的代码)向服务器发出请求。该请求是同步的,客户机等待服务器的响应。当客户机等待的时候,会用某种形式通知您正在处理: 沙漏(特别是 Windows 上) 旋转皮球(通常在 Mac 机器上) 应用程序基本上冻结了,然后过一段时间光标变化了 • 这正是传统Web 应用程序让人感到笨拙或缓慢的原因 ——缺乏真正的交互性。按下按钮时,应用程序实际上变得不能使用,直到刚刚触发的请求得到响应。如果请求需要大量服务器处理,那么等待的时间可能很长
传统Web应用与Ajax应用的比较(cont.) • Ajax应用通过在用户和服务器之间引入一个媒介(Ajax engine)来异步发送请求,消除了传统的发送请求-等待-发送请求-等待的特性,极大的提高了用户体验。
使用Ajax发送异步请求示例 考虑以下情景: 当用户输入邮编后,系统自动填充相应的城市和省份
创建XMLHttpRequest 要实现这种功能,必须非常熟悉一个 JavaScript 对象,即 XMLHttpRequest(简称XHR)。该对象的几个常用方法和属性: • open():建立到服务器的新请求 • send():向服务器发送请求
XMLHttpRequest方法 • void open(string method, string url, boolean asynch, string username, string password) 这个方法会建立对服务器的调用。它有两个必要的参数,还有三个可选参数。 method:提供调用的特定方法(GET、POST或PUT)。 POST-用“POST”方式发送数据,可以大到4MBGET-用“GET”方式发送数据,只能256KB如果请求带有参数则使用POST方式,POST方式将参数放置在页面的隐藏控件内;没有参数使用GET方式。 对于请求的页面在中途可能发生更改的,也最好用POST方式用GET方式可能会拿不到最新的信息。 url:提供所调用资源的URL ,url参数可以是相对URL或绝对URL asynch:指示这个调用是异步的还是同步的。默认值为true,表示请求本质上是异步的。如果这个参数为false,处理就会等待,直到从服务器返回响应为止。
XMLHttpRequest方法 • void send(content):这个方法具体向服务器发出请求。如果请求声明为异步的,这个方法就会立即返回,否则它会等待直到接收到响应为止。可选参数可以是DOM对象的实例、输入流,或者串。传入这个方法的内容会作为请求体的一部分发送。
XMLHttpRequest属性 • 标准XMLHttpRequest属性
创建XMLHttpRequest • 创建跨浏览器的XMLHttpRequest对象:
创建XMLHttpRequest • 下面分别介绍每一步: • 创建一个新变量 request 并赋值 false。使用 false 作为判断条件,表示还没有创建 XMLHttpRequest 对象 • 增加try/catch块: • 尝试创建 XMLHttpRequest 对象 • 如果失败,先尝试使用较新版本的Microsoft浏览器创建 Microsoft 兼容的对象(Msxml2.XMLHTTP),如果失败(尝试使用较老版本的Microsoft浏览器创建 Microsoft兼容的对象(Microsoft.XMLHTTP) • 如果全部失败,则保证request的值仍然为false • 检查request是否仍然为false(如果一切顺利就不会是false) • 如果出现问题则使用JavaScript警告通知用户出现了问题
建立到服务器的请求 • 准备好XMLHttpRequest对象,就可以建立到服务器的请求了。 • 首先结合一些表单中的数据来构造URL: • 注:escape() 方法用于转义不能用明文正确发送的任何字符。比如,空格将被转换成字符 %20,从而能够在 URL 中传递这些字符。 • 然后建立请求:
使用XMLHttpRequest发送请求 • 一旦请求用 open() 配置好之后,就可以使用send()方法发送请求了,send() 方法只有一个参数,就是要发送的内容 • 但是我们前面通过URL本身已经发送了zipcode的值,所以这里不需要通过 send() 传递数据,只要传递 null 作为该方法的参数即可:
设置回调函数 • 由于是异步请求,请求发出后JavaScript 方法不会等待服务器处理完成,因此代码将继续执行,就是说,将退出该方法而把控制返回给表单。用户可以继续输入信息,应用程序不会等待服务器 • 当服务器完成请求之后,需要指定该如何处理响应。XMLHttpRequest对象的onreadystatechange属性允许指定一个回调函数反向调用Web页面中的代码 • 当服务器完成请求之后,会查看XMLHttpRequest对象,特别是 onreadystatechange属性。然后调用该属性指定的任何方法。之所以称为回调是因为由服务器向网页发起调用,无论网页本身正在做什么。这就是称之为异步的原因:用户在一层上操作表单,而在另一层上服务器响应请求并触发onreadystatechange属性指定的回调方法
设置回调函数 需要特别注意的是该属性在代码中设置的位置 ——它是在调用send()之前设置的。发送请求之前必须设置该属性,这样服务器在回答完成请求之后能够查看该属性!
处理服务器响应 • 请求发送后,用户可以继续使用Web表单(同时服务器在处理请求)。而当服务器完成了请求处理,服务器查看onreadystatechange属性确定要调用的方法。除此以外,可以将应用程序看作其他应用程序一样,无论是否异步。换句话说,不一定要采取特殊的动作编写响应服务器的方法,只需要改变表单或其它的页面结构,让用户访问另一个 URL 或者做响应服务器需要的任何事情。 • 处理函数(仅弹出简单的警告):
处理服务器响应 • 运行以上代码,根据浏览器的不同,在表单停止弹出警告之前会看到两次、三次甚至四次警告。原因在于还没有考虑HTTP就绪状态,这是请求/响应循环中的一个重要部分 • HTTP就绪状态(readyState)表示请求的状态或情形。它用于确定该请求是否已经开始、是否得到了响应或者请求/响应模型是否已经完成。它还可以帮助确定读取服务器提供的响应文本或数据是否安全。在Ajax应用程序中需要了解五种就绪状态: • 0:请求没有发出(在调用 open() 之前) • 1:请求已经建立但还没有发出(调用 send() 之前) • 2:请求已经发出正在处理之中(这里通常可以从响应得到内容头部) • 3:请求已经处理,响应中通常有部分数据可用,但是服务器还没有完成响应 • 4:响应已完成,可以访问服务器响应并使用它
处理服务器响应 • 与大多数跨浏览器问题一样,这些就绪状态的使用也不尽一致。实际上很少出现就绪状态从0到1、2、3再到4,一些浏览器从不报告0或1而直接从2开始,然后是3和4,其他浏览器则报告所有的状态。还有一些则多次报告就绪状态1 • 对于Ajax编程,需要直接处理的惟一状态就是就绪状态4,它表示服务器响应已经完成,可以安全地使用响应数据了。基于此,回调函数做如下调整: 修改后就可以保证服务器的处理已经完成,现在就会看到只显示一次警告信息了。
处理服务器响应 • 以上代码看起来似乎不错,但是还有一个问题 ——如果服务器响应请求并完成了处理但是报告了一个错误怎么办?服务器端代码应该是由Ajax、JSP、普通HTML表单或其他类型的代码调用的,但只能使用传统的Web专用方法报告信息。而在 Web 世界中,HTTP状态码(status)可以处理请求中可能发生的各种问题,比如: • 输入了错误的URL请求将得到404错误码,它表示该页面不存在 • 403和401错误码表示所访问的数据受到保护或者禁止访问 • 无论哪种情况,这些错误码都是从完成的响应 中得到的。换句话说,服务器执行了请求(即HTTP就绪状态是4)但是没有返回客户机预期的数据。因此除了就绪状态外,还需要检查HTTP状态。我们期望的状态码是200,它表示一切顺利。如果就绪状态是4而且状态码是200,就可以处理服务器的数据了,而且这些数据应该就是要求的数据(而不是错误或者其他有问题的信息)
处理服务器响应 • 在回调函数中增加HTTP状态(status)检查: • 现在可以确保请求已经处理完成(通过就绪状态),服务器给出了正常的响应(通过状态码),最后可以处理服务器返回的数据了。返回的数据(文本形式)保存在XMLHttpRequest对象的responseText属性中。(如果服务器选择使用XML响应,则也可以使用在responseXML属性获取)
处理服务器响应 • 在本例中,服务器返回邮编相应的城市和省份,中间用逗号分开: • Tangshan,Hebei • 得到responseText并使用JavaScript的split()函数从逗号分开,得到的数组放到response中,然后更新表单中的相应值
连接Web表单 • 最后使用JavaScript事件函数触发Ajax调用: • 输入框的onblur属性指定的函数当焦点离开时触发,Ajax开始运行了。结果就会看到填完邮编后焦点移开时,表单的城市和省份信息突然更新了!
编写服务器端组件 • 服务器端使用JSP(当然可以使用Servlet)根据传递的邮编,返回相应的城市和省份: • 注意:JSP中除了JSP标签和Java代码不要出现任何HTML标签,也不要出现换行和空白字符,仅返回需要的响应结果,否则这些HTML标签和空白字符也会作为响应文本的一部分传递回客户端
小结 • Ajax应用的开发确实有些繁琐,实际上,现在有很多成熟稳定的Ajax工具葙封装了以上诸多细节,是的Ajax编程更加容易。但是如果不知道应用程序在做什么,就很难发现其中的问题 • XMLHttpRequest对象是Ajax应用的核心,必须非常熟悉 • Ajax应用的基本流程: • 创建XMLHttpRequest对象 • 从Web表单中获取需要的数据 • 设置要连接的URL • 建立到服务器的连接 • 设置服务器在完成后要运行的回调函数 • 发送请求
发送XML格式的请求 • XMLHttpRequest是Ajax应用程序中使用的基本对象。看起来它似乎是为通过HTTP请求发送XML或者以某种XML格式发出HTTP请求而设计的,但实际上它要做的只不过是为客户机代码(在网页中通常是JavaScript)提供一种发送HTTP请求的方式,并不要求必须使用XML请求或响应 • 注意:虽然XML可以通过HTTP发送,但XML是一种数据格式而不是传输协议
从客户机发送的XML数据格式 • 修改上一个邮编的例子,使用XML传递数据。将名/值对转化为XML数据格式: • <zipcode>063000</zipcode> • XML要求有一个根元素;如果使用文档片段(XML文档的一部分)的话则需要一个封闭元素,将上面的XML改为以下方式(同时便于传递等多信息): • <location> <zipcode>063000</zipcode> • </location>
向服务器发送XML • 请求中的数据必须手工格式化为XML • 对于XML最好使用POST请求,因为有些浏览器限制了 GET 请求字符串的长度,而XML可能很长 • 告诉服务器要发送的是XML而不是一般的名/值对 • XML通过send()方法发送,而不是附加在请求URL最后的参数
发送XML和普通文本的比较 • XML不是一种简洁、快速和节省空间的格式,和普通文本相比,XML通常总会占用更多的空间,速度也更慢,因为需要在消息中增加 XML 所需要的标签和语义,同时解析XML也比处理普通文本慢 • 构造和维护XML不是简单的事情 • XML没有为请求增加任何东西,除了复杂性的问题之外,和普通文本以及名/值对相比,在请求中使用 XML实际上没有多少好处(如果有的话)。实际上没有任何东西可用XML而不能用普通文本发送 • 一般地,只有当服务器仅接受XML时才需要发送XML
什么是JSON? • JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,易于人阅读和编写,同时也易于机器解析和生成,而且它是基于JavaScript的。 JSON采用完全独立于语言的文本格式,但是也使用了类似于C语言家族的习惯(包括C, C++, C#, Java, JavaScript等)。这些特性使JSON成为理想的数据交换语言
什么是JSON? • JSON有两种结构: • “名/值”对的集合(A collection of name/value pairs)。在不同的语言中,它被理解为对象,结构,关联数组等 • 值的有序列表(An ordered list of values)。在大部分语言中,它被理解为数组 • 这些都是常见的数据结构。事实上大部分现代计算机语言都以某种形式支持它们。这使得一种数据格式在同样基于这些结构的编程语言之间交换成为可能
JSON的基本形式 • 对象是一个无序的“名/值”对集合。一个对象以“{”开始,“}”结束。每个“名称”后跟一个“:”;“名/值”对之间使用“,”分隔: • 数组是值(value)的有序集合。一个数组以“[”开始,“]”结束。值之间使用“,”分隔:
JSON示例 • 下面的JSON表示名称/值对: • { "firstName": "Brett" } • 多个名称/值对串在一起: • { "firstName": "Brett", "lastName":"McLaughlin", "email": "brett@newInstance.com" } 从语法方面来看,这与名称/值对相比并没有很大的优势,但是在这种情况下 JSON更容易使用,而且可读性更好
JSON示例 • 当需要表示一组值时,JSON 不但能够提高可读性,而且可以减少复杂性: { “employees": [ { "firstName": "Brett", "lastName":"McLaughlin", "email": "brett@newInstance.com" }, { "firstName": "Jason", "lastName":"Hunter", "email": "jason@servlets.com" }, { "firstName": "Elliotte", "lastName":"Harold", "email": "elharo@macfaq.com" } ] } 这比相应的XML格式表示的数据更加简洁:
JSON示例 • 相应的XML格式: <employees> < employee > <firstName>Brett</firstName> <lastName>McLaughlin</lastName> <email>brett@newInstance.com</email> </ employee > < employee > <firstName>Jason</firstName> <lastName>Hunter</lastName> <email>jason@servlets.com</email> </ employee > < employee > <firstName>Elliotte</firstName> <lastName>Harold</lastName> <email>elharo@macfaq.com</email> </employee> </ employees >
JSON vs. XML • 可读性 • JSON和XML的可读性可谓不相上下,XML略占上风 • 可扩展性 • XML天生有很好的扩展性,JSON当然也有,没有什么是XML能扩展,JSON不能的。 • 编码难度 • XML有丰富的编码工具,比如Dom4j、JDom等,JSON也有json.org提供的工具,但是JSON的编码明显比XML容易许多,即使不借助工具也能写出JSON的代码,可是要写好XML就不太容易了
JSON vs. XML • 解码难度 • XML的解析得考虑子节点父节点关系,让人头昏眼花,而JSON的解析难度几乎为零。 • 流行度 • XML已经被业界广泛的使用,而JSON才刚刚开始,但在Ajax领域,JSON凭借自身的优势有可能最终取代XML
在JavaScript中使用JSON • JSON是JavaScript原生格式,这意味着在JavaScript中处理JSON数据不需要任何特殊的 API 或工具包。 • 将JSON数据赋值给变量: var company = { “employees": [ { "firstName": "Brett", "lastName":"McLaughlin", "email": brett@newInstance.com" }, { "firstName": "Jason", "lastName":"Hunter", "email": "jason@servlets.com" }, { "firstName": "Elliotte", "lastName":"Harold", "email": "elharo@macfaq.com" } ] };
在JavaScript中使用JSON • 以JavaScript对象的方式访问数据,如获取第一个雇员的firstName信息: • company.employees[0].fristName • 正如可以用点号和括号访问数据,也可以按照同样的方式轻松地修改数据: • company.employees[0].fristName=“Vincent”
客户端处理JSON响应 • 服务器端返回JSON相应的文本表示,如: • {“city” : “Hefei”, “province” : “Anhui”} • 客户端使用eval()函数将JSON文本转化为JavaScript对象 • 注意,使用额外的圆括号可使eval()函数将来源输入无条件地视为表达式进行解析。 • 然后从JavaScript对象中取得相应的值: