??xml version="1.0" encoding="utf-8" standalone="yes"?> AjaxQ即异步 JavaScript ?
XMLQ是一U?Web 应用E序开发的手段Q它采用客户端脚本与 Web
服务器交换数据。所以,不必采用会中断交互的完整面hQ就可以动态地更新 Web 面。?AjaxQ可以创建更加丰富、更加动态的 Web
应用E序用户界面Q其x性与可用性甚臌够接q本机桌面应用程序?/p>
Ajax 不是一Ҏ术,而更像是一?模式 —?
一U识别和描述有用的设计技术的方式。Ajax 是新颖的Q因多开发h员才刚刚开始知道它Q但是所有实?Ajax
应用E序的组仉已经存在若干q了。它目前受到重视是因为在 2004 ?2005 q出C一些基?Ajax 技术的非常的动?Web
UIQ最著名的就?Google ?GMail ?Maps 应用E序Q以及照片共享站?
Flickr。这些用L面具有够的开创性,有些开发h员称之ؓ“Web 2.0”,因此?Ajax 应用E序的兴飞速上升?/p>
在这?
pd中,提供?Ajax 开发应用程序需要的全部工具 。在W一文章中Q将解释 Ajax 背后的概念,演示为基?Java ?Web
应用E序创徏 Ajax 界面的基本步骤。我用代码示例演C Ajax 应用E序如此动态的服务器端 Java 代码和客L
JavaScript。最后,指?Ajax 方式的一些不I以及在创?Ajax 应用E序时应当考虑的一些更q的可用性和讉K性问题?/p>
?
以用 Ajax 增强传统?Web
应用E序Q通过消除面装入从而简化交互。ؓ了演C一点,采用一个简单的购物车示例,在向里面d目Ӟ它会动态更新。这Ҏ术如果整合到在线?
店,那么用户可以持箋地浏览和向购物R中添加项目,而不必在每次点击之后都等候完整的面更新。虽然这文章中的有些代码特定于购物车示例,但是演示的技
术可以应用于M Ajax 应用E序。清?1 昄了购物RCZ使用的有?HTML 代码Q整文章中都会使用q个 HTML?/p>
Ajax 交互开始于叫作 现在Q您q记?Ajax 的第一?a 是代?异步QasynchronousQ?/i> 吗?在发?HTTP hӞ不想让浏览器挂着{候服务器响应。相反,您想让浏览器l箋对用户与面的交互进行响应,q在服务器响应到达时再进行处理。ؓ了实现这个要求,可以? ?Java Web 服务器上Q请求同其他 回到客户端时Q现在调用注册在 现在您对 Ajax 往q过E有了一个高层面的认识。下面我放大其中的每一步骤Q进行更详细的观察。如果过E中q了路,请回头看?1 —?׃ Ajax 方式的异步性质Q所以顺序ƈ非十分简单?/p>
我将?Ajax 序列的v点开始:创徏和分z来自浏览器? E后讨论处理那些不支持 q回CZ的购物R场景Q想要当用户在目录项目上点击 Add to Cart 时启?Ajax 交互。名? 因ؓh会修Ҏ务器上的状态,所以将?HTTP 清单 3 把这些步骤放在了一赗?/p>
q就是徏?Ajax 往q过E的W一部分Q即创徏和分z来自客h?HTTP h。接下来是用来处理请求的 Java servlet 代码?/p>
?servlet 处理 清单 4 是处?Ajax h、更新购物R的简?servlet 的一部分?code>Cart bean 是从用户会话中获得的QƈҎh参数更新它的状态。然? 清单 5 昄? 如果查看应用E序源代码(可以?下蝲 一节得刎ͼ中的 Cart.javaQ可以看到生?XML 的方式只是把字符串添加在一赗虽然对q个CZ来说_了,但是对于?Java 代码生成 XML 来说则是最差的方式。这个系列的下一期中介绍一些更好的方式?/p>
现在您已l知道了 ?清单 3 中已l看C如何调用 在清?6 中,? ?清单 3 中看C 清单 7 ? 到此Q整?Ajax 往q过E完成了Q但是您可能惌 Web 应用E序q行一下查看实际效果(请参?下蝲 一节)。这个示例非常简单,有很多需要改q之处。例如,我包含了从购物R中清除项目的服务器端代码Q但是无法从 UI 讉K它。作Z个好的练习,误着在应用程序现有的 JavaScript 代码之上构徏够实现这个功能的代码?/p>
像M技术一P使用 Ajax 也有许多出错的可能性。我目前在这里讨论的问题q缺乏容易的解决ҎQ但是会随着 Ajax 的成熟而改q。随着开发h员社区增加开?Ajax 应用E序的经验,会记录下最佛_践和指南?/p>
Ajax 开发h员面临的一个最大问题是Q在没有 所以,您应当努力让应用E序“^E降U”,在没? 关于 Ajax 应用E序的某些可用性问题比较普遍。例如,让用L道他们的输入已经注册了可能是重要的,因ؓ沙漏光标?spinning 览器的常用反馈机制“throbber”对 ?
一个问题是Q用户可能没有注意到他们正在查看的页面的某一部分已经更新了。可以用不同的可视技术,把用L眼球带到面的更新区域,从而缓解这个问题?
?Ajax 更新面造成的其他问题还包括Q“破坏了”浏览器的后退按钮Q地址栏中?URL 也无法反映页面的整个状态,妨碍了设|书{。请参阅 参考资?/a> 一节,获得专门解决 Ajax 应用E序可用性问题的文章?/p>
?
Ajax 实现代替普通的Z表单?UIQ会大大提高Ҏ务器发出的请求数量。例如,一个普通的 Google Web
搜烦Ҏ务器只有一个请求,是在用户提交搜烦表单时出现的。?Google Suggest
试图自动完成搜烦术语Q它要在用户输入时向服务器发送多个请求。在开?Ajax
应用E序Ӟ要注意将要发送给服务器的h数量以及由此造成的服务器负荷。降低服务器负蝲的办法是Q在客户Z对请求进行缓冲ƈ且缓存服务器响应Q如果可
能的话)。还应该试?Ajax Web 应用E序设计为在客户Z执行可能多的逻辑Q而不必联l服务器?/p>
非常重要的是Q要理解无法保证 在这个系列的 W一文?/a> 中,我介l了 Ajax 的构造块Q?/p>
q一ơ,l讨?Ajax 开发的基础知识Q但是将侧重于许?Java Web 开发h员最兛_的问题:为客h生成数据?/p>
?
?Java 开发h员已l把模型-视图-控制器(MVCQ模式应用在他们?Web 应用E序上。在传统?Web 应用E序中,视图lg?JSP
或者其他表C技术(例如 Velocity 模板Q构成。这些表C组件动态地生成全新?HTML
面Q替代用户以前正在查看的面Q从而更新用L面。但是,?Java Web 应用E序使用 Ajax UI 的情况下Q基于从 q?
文章侧重于可以用来生成 Java 对象以数据ؓ中心的视囄技术。我演C可以把 JavaBeans 变成 XML
文档的各U方法,q且讨论每种Ҏ的优劣。您看Cؓ什?XML q不L最好的途径Q对于简单的 Ajax
h来说Q传输纯文本更好。最后,我将介绍 JavaScript 对象标注QJSONQ。JSON 允许数据以序列化?JavaScript
对象囄形式传输Q在客户端代码中处理序列化的 JavaScript 对象图极为容易?/p>
使用一个示例应用程序和几个用例来演C里讨论的技术特性和技术。图 1 昄的极为简单的数据模型可以表示CZ用例。这个模型代表在U商店中的顾客帐戗顾客拥有以前订单的集合Q每个订单包含几个商品?/p>
虽然 ?
Ajax 响应作ؓ XML 来传递有许多原因Q每个支?Ajax 的浏览器都有D XML 文档的方法,也有许多服务器端技术可以处?XML
数据。通过制定一个方案,描述要交换的文档cdQ在 Ajax
客户端和服务器端之间很容易定义合U,而且如果服务器端架构采用面向服务的方式,那么使用 XML 也可以允讔R Ajax 客户Z用您提供的数据?/p>
我们?Java 对象产生 XML 数据的三U方法,q讨论每U方法的优劣?/p>
首先Q可以从对象图以~程的方式生?XML。这U方式可以简单到只是在每?JavaBean cM实现 前一文?/a> 的示例代码中Q把 XML 标记字符串连接在一P实现? 在这里可以看到用 JDOM 创徏元素、用属性和d元素内容有多么简单。递归地调用复?JavaBean ? 一旦所有的 JavaBean 都实C JDOM 再次把工作变得非常简单。只需要在对象图返回的 XML 元素外面包装一? 有趣的是Q清?3 中的代码展示了让 JavaBean 把自己序列化?XML 的一个主要不뀂假设要用这个文档表C顾客的订单历史视图。在q种情况下,不太可能要显C每个历史订单中每个商品的完整说明,或者告诉顾客他或她自己的姓名。但是如果应用程序有一? ?
设计的角度来看,q是数据模型与视囄成耦合的经兔R题。每?bean 只能用一U途径序列化自己,一成不变的方式意味着 Ajax
交互最l要交换它们不需要交换的数据Q因此造成客户端代码要从文档中扑ֈ需要的信息更加困难Q而且也会增加带宽消耗和客户端的 XML
解析旉。这U耦合的另一个后果就?XML 的语法不能脱?Java cȝ立变化。例如,寚w客文档的Ҏ做修改,可能会媄响多?Java
c,造成它们也不得不做修改和重新~译?/p>
E后会解册些问题,但是首先来看一个对自行序列化方式的可~性问题的解决ҎQXML l定框架?/p>
q?
些年来,已经开发了多个 Java API 来简?XML 文档?Java 对象囄l定q程。多数都提供?XML
~排和拆解;也就是说Q它们可以在 Java 对象囑֒ XML 之间执行双向会话。这些框架封装了 XML
处理的全部工作,q意味着应用E序代码只需要处理普通的 Java
cR它们还希望提供有用的辅助功能,例如文档验证。笼l来_q些框架采用了两U不同的方式Q代码生成和对象?XML 映射。我分别解释这两种方式?/p>
?
用代码生成的框架包括 XMLBeans、JAXB、Zeus ?JBind。Castor 也能使用q项技术。这cL架的L是描q文档数据类型的
XML Ҏ。用框架提供的工具Q就可以生成代表q些Ҏ定义cd?Java
cR最后,用这些生成的cȝ写应用程序,表示自己的模型数据,q过框架提供的一些辅助机制把数据序列化成 XML?/p>
如果应用E序要用大
?XML 语法Q那么代码生成方式是个很好的Ҏ。在数十个类上编写定?XML
序列化代码的可~性问题由此消除。另一斚wQ也不再需要定义自q JavaBean。框架生成的 Java c通常非常W合 XML
的结构,所以对它们q行~码很难。而且Q生成的cd成哑数据容器Q因Z般不能向它们d行ؓ。一般来_在应用程序代码中要做些妥协,才能很好地处理方
案生成的cd。另一个缺h如果修改ҎQ会造成生成的类也要修改Q所以也׃对围l它们编写的代码带来相应的媄响?/p>
q种cd?XML l定框架在数据拆解时最有用Q例如,使用 XML 文档q把它们转化?Java 对象Q。除非拥有大型数据模型而且有可能从生成的类中获益,否则Z代码生成的框架对?Ajax 应用E序来说可能有很大的杀伤力?/p>
?
用映方式的框架包括 Castor ?Apache Commons
Betwixt。映通常是比代码生成更灵zd更轻量的解决Ҏ。首先,可以像通常一L?
JavaBeanQ包括Q何行Z及Q何自己喜Ƣ的方便的方法。然后,在运行时Q调用框架中Z内省的编排器QƈҎ对象成员的类型、名U和值生?
XML 文档。通过定义cȝ映射文gQ可以覆盖默认的l定{略Qƈq?XML 中的表示方式对编排器提出?/p>
q种Ҏ是在可~性与
灉|性之间的良好折中。可以按照自己喜Ƣ的方式~写 Java c,~排器负责处?
XML。虽然映定义文件编写v来简单,可~性也_好,但是映射规则最多只能改变标准的l定行ؓQ而且在对象结构和它们?XML
表示之间总要D留一些耦合。最l,可能不得不在 Java 表示?XML 格式之间任选一个做些折中,才能让映方法v作用?/p>
Dennis Sosnoski ?XML 数据l定 API 的主题,在代码生成和代码映射两个斚w写了深入的文章。如果想q一步研I这个领域,我推荐他?Castor 和代码生成框架方面的_ֽ文章Q请参阅 参考资?/a> 中的链接Q?/p>
MQ代码生成方式损׃q多的灵zL和方便性,对于典型?Ajax 应用E序用处不大。另一斚wQ基于映的框架可能工作得很好,但是要恰到好处地调整它们的映策略,以便从对象生成需要的 XML?/p>
所
有的 XML l定 API 都具有手工序列化技术的一个主要不I模型和视囄耦合。被限制Z个类型一?XML
表示Q就意味着在网l上总要有冗余数据传输。更严重的问题是Q在情况要求客户端代码用专门视图时Q客L代码却无法得到它Q所以可能要费力地处理给定对
象图的一成不变的视图?/p>
在传l的 Web 应用E序开发中Q采用页面模板系l把视图生成与控制器逻辑和模型数据干净地分R这U方法在 Ajax 场景中也会有帮助?/p>
M通用目的的页面模板技术都可以用来生成 XMLQ从而 Ajax 应用E序Ҏ自己的数据模型生成Q?XML 响应文档。额外收hQ模板可以用单的、表现力强的标记语言~写Q而不是用一行行?Java 代码~写。清?5 是一?JSP 面Q采用了 q个z的模板只输单历史视N要的数据Q不输出不相关的资料Q例如商品说明)。创Z品搜索视囄定制 XML 应当同样单,q个视图包含每个商品的完整说明和库存水^?/p>
?
一斚wQ现在我需要ؓ每个不同视图创徏一个新
JSPQ而不能仅仅把需要的对象囄lv来ƈ序列化它。从设计的角度来_许多人可能会有争议,认ؓq无论如何是件好事,因ؓq意味着正式地考虑服务器要
生成的文档类型。而且Q因为我现在要处理通用的模板环境,而不是特定于 XML ?APIQ所以确保标记匹配、元素和属性的序正确以及 XML
实体Q例? q?
今ؓ止,我介l的所有技术都?XML 文档的Ş式生成服务器响应。但是,XML 有一些问题。其中一个就是gq。浏览器不能立即解析 XML
文档q生?DOM 模型Q所以这会降低某?Ajax
lg需要的“迅捷”感Q特别是在较慢的机器上解析大型文档的时候更是如此。“现场搜索”就是一个示例,在这U搜索中Q当用户输入搜烦术语Ӟ׃从服务器
提取搜烦l果q显C给用户。对于现场搜索组件来_q速地响应输入是非帔R要的Q但是同时它q需要迅速而持l地解析服务器的响应?/p>
延迟是一个重要的考虑因素Q但是避免?XML 的最大原因是差劲的客L DOM API。清?5 昄了用跨览器兼容的方式通过 DOM 得到某个值的时候,通常不得不面对的困难?/p>
当元素中间存在空白时Q情况就变得更加复杂Q因为每个元素的 但是Q想x代方案还是值得的。除? 当服务器需要向客户机发送非常简单的值时Q?code>responseText
特别方便Q它可以避免 XML D的带宽支出和处理支出。例如,单的 true/false
响应可以由服务器以纯文本方式q回Q可以是逗号分隔的简单的名称或数字列表。但是,一般来_最好不要在同一个应用程序中?XML
响应和纯文本响应混合使用Q保持单一数据格式可以让代码抽象和重用更加单?/p>
在某些情况下Q采用即时方式? ?
际上QJavaScript 对象的大部分都由联合数组、数字烦引数l、字W串、数字或者这些类型的嵌套l合而成。因为所有类型都可以?
JavaScript 直接声明Q所以可以在一条语句中静态地定义对象图。清?7 使用 JSON
语法声明了一个对象,q演CZ如何讉Kq个对象。大括号表示联合数组Q即对象Q,它的?-值组合由逗号分隔。方括号表示数字索引数组?/p>
既然 JSON 是一个有的语言Ҏ,那么它对
Ajax 有什么意义呢Q妙处在于可以用 JSON ?Ajax 服务器响应中通过|络发?JavaScript
对象图。这意味着在客L可以避免使用W拙?DOM API ?XML q行D —?只需要分?JSON 响应Q就会立卛_到可以访问的
JavaScript 对象图。但是,首先需要把 JavaBean 变成 JSON?/p>
不同 XML 生成技术所h的优~点也适用?JSON 的生。而且可以证明Q存在需要再ơ用表C模板技术的情况。但是,使用 JSON 在理念上更接q于在应用层之间传递序列化的对象,而不是创建应用程序状态的视图。我介l如何用 可以看到Q?code>org.json API 非常单? 清单 9 昄了如何序列化 可以看到Q它实际上什么也没有做。在q里隐式调用? 处理的最后一步是把在客户端把 JSON 数据变成 JavaScript 对象。这可以通过? 比较清单 11 ?清单 5 可以发现使用 JSON 的客L的优ѝ如果在 Ajax 目中要在客L对许多复杂的服务器响应进行导航,那么 JSON 可能适合您的需要。JSON ? JSON 也有它的不。用这里介l的 JSON 方式Q就没有办法针对每个h对对象的序列化进行裁剪,所以不需要的字段可能l常会在|络上发送。另外,d ?
在已l看C?Java 状态传输到 Ajax 客户端的五种不同技术。我讨论了自行手工编?XML 序列化、通过代码生成?XML
l定、通过映射机制?XML l定、基于模板的 XML 生成以及手工~码?JSON
的序列化。每U技术都有自q优势和不I分别适用于不同的应用E序架构?
Zȝ每种方式的优势与不Q表 1 从六个方面进行了_略的评分: ?
1
中的数据q不表明某项序列化技术比其他的技术好。毕竟,六种标准的相寚w要性取决于目的具体情c例如,如果要处理数癄数据cdQ这时想要的是可伸羃
性,那么代码生成可能是最好的选择。如果需要ؓ同一数据模型生成多个不同视图Q那么就应当使用面模板。如果处理的是小规模目Q想降低需要编写的
JavaScript 代码数量Q那么请考虑 JSON?/p>
希望q篇文章为您提供了选择适合自己应用E序的序列化技术所需要的信息?/p>
1.前言 Internet的高速发展,lh们的工作和生zd来了极大的便利,对Internet的服务品质和讉K速度要求来高Q虽然带宽不断增加,
用户数量也在不断增加Q受Web服务器的负荷和传输距ȝ因数的媄响,响应速度慢还是经常抱怨和困扰。解x案就是在|络传输上利用缓存技术得Web?
务数据流能就q访问,是优化网l数据传输非常有效的技术,从而获得高速的体验和品质保证?/p>
|络~存技术,其目的就是减网l中冗余数据的重复传输,使之最化Q将q域传输转ؓ本地或就q访问。互联网上传递的内容Q大部分为重复的
Web/FTP数据QCache服务器及应用Caching技术的|络讑֤Q可大大优化数据链\性能Q消除数据峰D问造成的结点设备阻塞。Cache?
务器h~存功能Q所以大部分|页对象QWeb page objectQ?如html, htm,
php{页面文Ӟgif,tif,png,bmp{图片文Ӟ以及其他格式的文Ӟ在有效期QTTLQ内Q对于重复的讉KQ不必从原始|站重新传送文?
实体, 只需通过单的认证QFreshness ValidationQ?
传送几十字节的HeaderQ即可将本地的副本直接传送给讉K者。由于缓存服务器通常部v在靠q用LQ所以能获得q似局域网的响应速度Qƈ有效减少q域
带宽的消耗。据l计QInternet上超q?0%的用户重复访?0%的信息资源,l缓存技术的应用提供了先决的条g。缓存服务器的体pȝ构与Web?
务器不同Q缓存服务器能比Web服务器获得更高的性能Q缓存服务器不仅能提高响应速度Q节U带宽,对于加速Web服务器,有效减轻源服务器的负h非常?
效的?/p>
高速缓存服务器QCache
ServerQ是软硬仉度集成的专业功能服务器,主要做高速缓存加速服务,一般部|在|络边缘。根据加速对象不同,分ؓ客户端加速和服务器加速,客户?
加速Cache部v在网l出口处Q把常访问的内容~存在本圎ͼ提高响应速度和节U带宽;服务器加速,Cache部v在服务器前端Q作为Web服务器的前置
机,提高Web服务器的性能Q加速访问速度。如果多台Cache加速服务器且分布在不同地域Q需要通过有效地机制管理Cache|络Q引导用户就q访问,
全局负蝲均衡量Q这是CDN内容传输|络的基本思想?br>
2Q什么是CDNQ?/b> CDN的全U是Content Delivery
NetworkQ即内容分发|络。其目的是通过在现有的Internet中增加一层新的网l架构,网站的内容发布到最接近用户的网l?边缘"Q用户?
以就q取得所需的内容,解决Internet|络拥塞状况Q提高用戯问网站的响应速度。从技术上全面解决׃|络带宽、用戯问量大、网点分布不均等
原因Q解决用戯问网站的响应速度慢的Ҏ原因?/p>
狭义地讲Q内容分发布|络(CDN)是一U新型的|络构徏方式Q它是ؓ能在传统的IP|发布宽带丰富媒体而特别优化的|络覆盖层;而从q义的角
度,CDN代表了一U基于质量与U序的网l服务模式。简单地_内容发布|?CDN)是一个经{略性部|的整体pȝQ包括分布式存储、负载均衡、网l请?
的重定向和内容管理4个要Ӟ而内容管理和全局的网l流量管?Traffic
Management)是CDN的核心所在。通过用户p性和服务器负载的判断QCDN保内容以一U极为高效的方式为用Lh提供服务。ȝ来说Q内
Ҏ务基于缓存服务器Q也UC代理~存(Surrogate)Q它位于|络的边~,距用户仅?一?(Single
Hop)之遥。同Ӟ代理~存是内Ҏ供商源服务器Q通常位于CDN服务提供商的数据中心Q的一个透明镜像。这L架构使得CDN服务提供商能够代表他?
客户Q即内容供应商,向最l用h供尽可能好的体验Q而这些用h不能容忍h响应旉有Q何gq的。据l计Q采用CDN技术,能处理整个网站页面的
70%?5Q的内容讉K量,减轻服务器的压力Q提升了|站的性能和可扩展性?/p>
与目前现有的内容发布模式相比较,CDN了网l在内容发布中的重要性。通过引入d的内容管理层的和全局负蝲均衡QCDN从根本上区别于传
l的内容发布模式。在传统的内容发布模式中Q内容的发布由ICP的应用服务器完成Q而网l只表现Z个透明的数据传输通道Q这U透明性表现在|络的质量保
证仅仅停留在数据包的层面Q而不能根据内容对象的不同区分服务质量。此外,׃IP|的"力而ؓ"的特性得其质量保证是依靠在用户和应用服务器之间?
到端地提供充分的、远大于实际所需的带宽通量来实现的。在q样的内容发布模式下Q不仅大量宝늚骨干带宽被占用,同时ICP的应用服务器的负载也变得非常
重,而且不可预计。当发生一些热点事件和出现涌量Ӟ会生局部热Ҏ应,从而应用服务器过载退出服务。这U基于中心的应用服务器的内容发布模式?
另外一个缺陷在于个性化服务的缺失和对宽带服务h值链的扭Ԍ内容提供商承担了他们不该q也q不好的内容发布服务?/p>
U观整个宽带服务的h值链Q内Ҏ供商和用户位于整个h值链的两端,中间依靠|络服务提供商将其串接v来。随着互联|工业的成熟和商业模式的?
革,在这条h值链上的角色来多也越来越l分。比如内容/应用的运营商、托服务提供商、骨q网l服务提供商、接入服务提供商{等。在q一条h值链上的
每一个角色都要分工合作、各司其职才能ؓ客户提供良好的服务,从而带来多赢的局面。从内容与网l的l合模式上看Q内容的发布已经走过了ICP的内容(?
用)服务器和IDCq两个阶DcIDC的热潮也催生了托服务提供商q一角色。但是,IDCq不能解军_容的有效发布问题。内容位于网l的中心q不能解?
骨干带宽的占用和建立IP|络上的量U序。因此将内容推到|络的边~,为用h供就q性的边缘服务Q从而保证服务的质量和整个网l上的访问秩序就成了一
U显而易见的选择。而这是内容发布|?CDN)服务模式。CDN的徏立解决了困扰内容q营商的内容"集中与分?的两N择。无疑对于构好的互联|?
价值链是有价值的Q也是不可或~的?span class="contentblk">
3QCDN新应用和客户 目前的CDN服务主要应用于证券、金融保险、ISP、ICP、网上交易、门L站、大中型公司、网l教学等领域。另外在行业专网、互联网中都?
以用刎ͼ甚至可以对局域网q行|络优化。利用CDNQ这些网站无需投资昂贵的各cL务器、设立分站点Q特别是媒体信息的q泛应用、远E教学课件等消耗带
宽资源多的媒体信息,应用CDN|络Q把内容复制到网l的最边缘Q内容h点和交付点之间的距离~至最,从而促qWeb站点性能的提高,h重要的意
义。CDN|络的徏设主要有企业的CDN|络Qؓ企业服务QIDC的CDN|络Q主要服务于IDC和增值服务;|络q营上主建的CDN|络Q主要提?
内容推送服务;CDN|络服务商,专门的CDN用于做服务,用户通过与CDN机构q行合作QCDN负责信息传递工作,保证信息正常传输Q维护传送网
l,而网站只需要内容维护,不再需要考虑量问题?/p>
CDN能够为网l的快速、安全、稳定、可扩展{方面提供保障?/p>
IDC建立CDN|络QIDCq营商一般需要有分部各地的多个IDC中心Q服务对象是托管在IDC中心的客P利用现有的网l资源,投资较少Q?
Ҏ。例如某IDC全国?0个机房,加入IDC的CDN|络Q托在一个节点的Web服务器,相当于有?0个镜像服务器Q就q供客户讉K。宽带城
域网Q域内网l速度很快Q出城带宽一般就会瓶颈,Z体现城域|的高速体验,解决Ҏ是Internet|上内容高速缓存到本地Q将Cache部v?
城域|各POP点上Q这样Ş成高效有序的|络Q用户仅一跛_能访问大部分的内容,q也是一U加速所有网站CDN的应用?br>
4QCDN 的工作原?/b> 在描qCDN的实现原理,让我们先看传l的未加~存服务的访问过E,以便了解CDN~存讉K方式与未加缓存访问方式的差别Q?/p>
׃囑֏见,用户讉K未用CDN~存|站的过Eؓ: 1)、用户向览器提供要讉K的域名; 2)、浏览器调用域名解析函数库对域名q行解析Q以得到此域名对应的IP地址Q?/p>
3)、浏览器使用所得到的IP地址Q域名的服务L发出数据讉KhQ?/p>
4)、浏览器Ҏ域名Lq回的数据显C网늚内容?/p>
通过以上四个步骤Q浏览器完成从用户处接收用户要访问的域名C域名服务L处获取数据的整个q程。CDN|络是在用户和服务器之间增加
Cache层,如何用Lh引导到Cache上获得源服务器的数据Q主要是通过接管DNS实现Q下面让我们看看讉K使用CDN~存后的|站的过E: 通过上图Q我们可以了解到Q用了CDN~存后的|站的访问过E变为: 1)、用户向览器提供要讉K的域名; 2)、浏览器调用域名解析库对域名q行解析Q由于CDN对域名解析过E进行了调整Q所以解析函数库一般得到的是该域名对应的CNAME记录Qؓ
了得到实际IP地址Q浏览器需要再ơ对获得的CNAME域名q行解析以得到实际的IP地址Q在此过E中Q用的全局负蝲均衡DNS解析Q如Ҏ地理位置?
息解析对应的IP地址Q得用戯p讉K?/p>
3)、此ơ解析得到CDN~存服务器的IP地址Q浏览器在得到实际的IP地址以后Q向~存服务器发问请求; 4)、缓存服务器Ҏ览器提供的要访问的域名Q通过Cache内部专用DNS解析得到此域名的实际IP地址Q再q存服务器向此实际IP地址提交讉KhQ?/p>
5)、缓存服务器从实际IP地址得得到内容以后,一斚w在本地进行保存,以备以后使用Q二斚w把获取的数据q回l客LQ完成数据服务过E; 6)、客L得到q存服务器q回的数据以后显C出来ƈ完成整个览的数据请求过E?/p>
通过以上的分析我们可以得刎ͼZ实现既要Ҏ通用户透明(卛_入缓存以后用户客L无需q行M讄Q直接用被加速网站原有的域名卛_?
?Q又要在为指定的|站提供加速服务的同时降低对ICP的媄响,只要修改整个讉Kq程中的域名解析部分Q以实现透明的加速服务,下面是CDN|络实现?
具体操作q程?/p>
1)、作为ICPQ只需要把域名解释权交lCDNq营商,其他斚w不需要进行Q何的修改Q操作时QICP修改自己域名的解析记录,一般用cname方式指向CDN|络Cache服务器的地址?/p>
2)、作为CDNq营商,首先需要ؓICP的域名提供公开的解析,Z实现sortlistQ一般是把ICP的域名解释结果指向一个CNAME记录Q?/p>
3)、当需要进行sorlistӞCDNq营商可以利用DNS对CNAME指向的域名解析过E进行特D处理,使DNS服务器在接收到客Lh时可以根据客L的IP地址Q返回相同域名的不同IP地址Q?/p>
4)、由于从cname获得的IP地址Qƈ且带有hostname信息Q请求到达Cache之后QCache必须知道源服务器的IP地址Q所以在CDNq营商内部维护一个内部DNS服务器,用于解释用户所讉K的域名的真实IP地址Q?/p>
5)、在l护内部DNS服务器时Q还需要维护一台授权服务器Q控制哪些域名可以进行缓存,而哪些又不进行缓存,以免发生开放代理的情况?/p>
5QCDN的技术手D?/b> 实现CDN的主要技术手D|高速缓存、镜像服务器。可工作于DNS解析或HTTP重定向两U方式,通过Cache服务器,或异地的镜像站点
完成内容的传送与同步更新。DNS方式用户位置判断准确率大?5%QHTTP方式准确率ؓ99%以上Q一般情况,各Cache服务器群的用戯问流入数
据量与Cache服务器到原始|站取内容的数据量之比在2Q??Q?之间Q即分担50%?0%的到原始|站重复讉K数据量(主要是图片,媒体文件等
内容Q;对于镜像Q除数据同步的流量,其余均在本地完成Q不讉K原始服务器?/p>
镜像站点QMirror
SiteQ服务器是我们经常可以看到的Q它让内容直截了当地q行分布Q适用于静态和准动态的数据同步。但是购买和l护新服务器的费用较高,另外q必d?
个地|镜像服务器Q配备专业技术h员进行管理与l护。大型网站在随时更新各地服务器的同时Q对带宽的需求也会显著增加,因此一般的互联|公怸会徏?
太多的镜像服务器?/p>
高速缓存手D늚成本较低Q适用于静态内宏VInternet的统计表明,过80%的用L常访问的?0%的网站的内容Q在q个规律下,~存
服务器可以处理大部分客户的静态请求,而原始的WWW服务器只需处理U?0%左右的非~存h和动态请求,于是大大加快了客戯求的响应旉Qƈ降低了原
始WWW服务器的负蝲。根据美国IDC公司的调查,作ؓCDN的一w要指?~存的市场正在以每年q?00%的速度增长Q全球的营业额在2004q将?
?5
6QCDN的网l架?/b> CDN|络架构主要׃大部分,分ؓ中心和边~两部分Q中心指CDN|管中心和DNS重定向解析中心,负责全局负蝲均衡Q设备系l安装在理中心机房Q边~主要指异地节点QCDN分发的蝲体,主要由Cache和负载均衡器{组成?/p>
当用戯问加入CDN服务的网站时Q域名解析请求将最l交l全局负蝲均衡DNSq行处理。全局负蝲均衡DNS通过一l预先定义好的策略,当?
最接近用户的节点地址提供l用P使用戯够得到快速的服务。同Ӟ它还与分布在世界各地的所有CDNC节点保持通信Q搜集各节点的通信状态,保不将?
Lh分配C可用的CDN节点上,实际上是通过DNS做全局负蝲均衡?/p>
对于普通的Internet用户来讲Q每个CDN节点q当于一个放|在它周围的WEB。通过全局负蝲均衡DNS的控Ӟ用户的请求被透明地指向离他最q的节点Q节点中CDN服务器会像网站的原始服务器一P响应用户的请求。由于它ȝhq,因而响应时间必然更快?/p>
每个CDN节点׃部分l成Q负载均衡设备和高速缓存服务器 负蝲均衡讑֤负责每个节点中各个Cache的负载均衡,保证节点的工作效率;同时Q负载均衡设备还负责攉节点与周围环境的信息Q保持与全局负蝲DNS的通信Q实现整个系l的负蝲均衡?/p>
高速缓存服务器QCacheQ负责存储客L站的大量信息Q就像一个靠q用L|站服务器一样响应本地用L讉Kh?/p>
CDN的管理系l是整个pȝ能够正常q{的保证。它不仅能对pȝ中的各个子系l和讑֤q行实时监控Q对各种故障产生相应的告警,q可以实时监?
到系l中ȝ量和各节点的流量,q保存在pȝ的数据库中,使网h员能够方便地q行q一步分析。通过完善的网系l,用户可以对系l配|进行修攏V?/p>
理论上,最单的CDN|络有一个负责全局负蝲均衡的DNS和各节点一台CacheQ即可运行。DNS支持Ҏ用户源IP地址解析不同的IPQ?
实现p讉K。ؓ了保证高可用性等Q需要监视各节点的流量、健L늭。一个节点的单台Cache承蝲数量不够Ӟ才需要多台CacheQ多台Cache
同时工作Q才需要负载均衡器QCache协同工作?/p>
清单1. 购物车示例的有关片断
<!-- Table of products from store's catalog, one row per item -->
<th>Name</th> <th>Description</th> <th>Price</th> <th></th>
...
<tr>
<!-- Item details -->
<td>Hat</td> <td>Stylish bowler hat</td> <td>$19.99</td>
<td>
<!-- Click button to add item to cart via Ajax request -->
<button onclick="addToCart('hat001')">Add to Cart</button>
</td>
</tr>
...
<!-- Representation of shopping cart, updated asynchronously -->
<ul id="cart-contents">
<!-- List-items will be added here for each item in the cart -->
</ul>
<!-- Total cost of items in cart displayed inside span element -->
Total cost: <span id="total">$0.00</span>
XMLHttpRequest
?JavaScript 对象。顾名思义Q它允许客户端脚本执?HTTP hQƈ解析 XML 服务器响应。Ajax 往q过E的W一步是创徏 XMLHttpRequest
的实例。在 XMLHttpRequest
对象上设|请求用的 HTTP ҎQ?code>GET ?POST
Q以及目?URL?/p>
XMLHttpRequest
上注册一个回调函敎ͼ然后异步地分z?XMLHttpRequest
。然后控制就会返回浏览器Q当服务器响应到达时Q会调用回调函数?/p>
HttpServletRequest
一样到达。在解析了请求参C后,servlet 调用必要的应用程序逻辑Q把响应序列化成 XMLQƈ?XML 写入 HttpServletResponse
?/p>
XMLHttpRequest
上的回调函数Q处理服务器q回?XML 文档。最后,Ҏ服务器返回的数据Q用 JavaScript 操纵面?HTML DOMQ把用户界面更新。图 1 ?Ajax 往q过E的序图?/p>
?1. Ajax 往q过E?/b>
XMLHttpRequest
。不q的是,不同的浏览器创徏 XMLHttpRequest
的方法各不相同。清?2 ?JavaScript 函数消除了这些依赖于览器的技巧,它可以检当前浏览器要用的正确方式Qƈq回一个可以用的 XMLHttpRequest
。最好是把它当作辅助代码Q只要把它拷贝到 JavaScript 库,q在需?XMLHttpRequest
的时候用它可以了?/p>
清单 2. 创徏跨浏览器?XMLHttpRequest
/*
* Returns a new XMLHttpRequest object, or false if this browser
* doesn't support it
*/
function newXMLHttpRequest() {
var xmlreq = false;
if (window.XMLHttpRequest) {
// Create XMLHttpRequest object in non-Microsoft browsers
xmlreq = new XMLHttpRequest();
} else if (window.ActiveXObject) {
// Create XMLHttpRequest via MS ActiveX
try {
// Try to create XMLHttpRequest in later versions
// of Internet Explorer
xmlreq = new ActiveXObject("Msxml2.XMLHTTP");
} catch (e1) {
// Failed to create required ActiveXObject
try {
// Try version supported by older versions
// of Internet Explorer
xmlreq = new ActiveXObject("Microsoft.XMLHTTP");
} catch (e2) {
// Unable to create an XMLHttpRequest with ActiveX
}
}
}
return xmlreq;
}
XMLHttpRequest
的浏览器的技术。目前,CZ假设清单 2 ?newXMLHttpRequest
函数总能q回 XMLHttpRequest
实例?/p>
addToCart()
?onclick
处理函数负责通过 Ajax 调用来更新购物R的状态(请参?清单 1Q。正如清?3 所C,addToCart()
需要做的第一件事是通过调用清单 2 ?newXMLHttpRequest()
函数得到 XMLHttpRequest
对象。接下来Q它注册一个回调函敎ͼ用来接收服务器响应(我稍后再详细解释q一步;请参?清单 6Q?/p>
POST
做这个工作。通过 POST
发送数据要求三个步骤。第一Q需要打开与要通信的服务器资源?POST
q接 —?在这个示例中Q服务器资源是一个映到 URL cart.do
?servlet。然后,我在 XMLHttpRequest
上设|一个头Q指明请求的内容是表?~码的数据。最后,用表单编码的数据作ؓh体发送请求?/p>
清单 3. 分派 Add to Cart XMLHttpRequest
/*
* Adds an item, identified by its product code, to the shopping cart
* itemCode - product code of the item to add.
*/
function addToCart(itemCode) {
// Obtain an XMLHttpRequest instance
var req = newXMLHttpRequest();
// Set the handler function to receive callback notifications
// from the request object
var handlerFunction = getReadyStateHandler(req, updateCart);
req.onreadystatechange = handlerFunction;
// Open an HTTP POST connection to the shopping cart servlet.
// Third parameter specifies request is asynchronous.
req.open("POST", "cart.do", true);
// Specify that the body of the request contains form data
req.setRequestHeader("Content-Type",
"application/x-www-form-urlencoded");
// Send form encoded data stating that I want to add the
// specified item to the cart.
req.send("action=add&item="+itemCode);
}
XMLHttpRequest
Q与处理普通的览?HTTP h一栗可以用 HttpServletRequest.getParameter()
得到?POST h体中发送的表单~码数据。Ajax h被放q与来自应用E序的常?Web h一L HttpSession
中。对于示例购物R场景来说Q这很有用,因ؓq可以把购物车状态封装在 JavaBean 中,q在h之间在会话中l持q个状态?/p>
Cart
被序列化?XMLQXML 又被写入 ServletResponse
。重要的是把响应的内容类型设|ؓ application/xml
Q否?XMLHttpRequest
不会把响应内容解析成 XML DOM?/p>
清单 4. 处理 Ajax h?servlet 代码
public void doPost(HttpServletRequest req, HttpServletResponse res)
throws java.io.IOException {
Cart cart = getCartFromSession(req);
String action = req.getParameter("action");
String item = req.getParameter("item");
if ((action != null)&&(item != null)) {
// Add or remove items from the Cart
if ("add".equals(action)) {
cart.addItem(item);
} else if ("remove".equals(action)) {
cart.removeItems(item);
}
}
// Serialize the Cart's state to XML
String cartXml = cart.toXml();
// Write XML to response.
res.setContentType("application/xml");
res.getWriter().write(cartXml);
}
Cart.toXml()
Ҏ生成的示?XML。它很简单。请注意 cart
元素?generated
属性,它是 System.currentTimeMillis()
生成的一个时间戳?/p>
清单 5. Cart 对象的XML 序列化示?
<?xml version="1.0"?>
<cart generated="1123969988414" total="$171.95">
<item code="hat001">
<name>Hat</name>
<quantity>2</quantity>
</item>
<item code="cha001">
<name>Chair</name>
<quantity>1</quantity>
</item>
<item code="dog001">
<name>Dog</name>
<quantity>1</quantity>
</item>
</cart>
CartServlet
响应 XMLHttpRequest
的方式。下一件事是q回客户端,查看如何?XML 响应更新面状态?/p>
XMLHttpRequest
?readyState
属性是一个数|它指求生命周期的状态。它?0Q代表“未初始化”)变化?4Q代表“完成”)。每?readyState
变化Ӟreadystatechange
事gp发,?onreadystatechange
属性指定的事g处理函数p调用?/p>
getReadyStateHandler()
函数创徏事g处理函数。然后把q个事g处理函数分配l?onreadystatechange
属性?code>getReadyStateHandler() 利用了这样一个事实:函数?JavaScript 中的一U对象。这意味着函数可以是其他函数的参数Q也可以创徏和返回其他函数?code>getReadyStateHandler() 的工作是q回一个函敎ͼ?XMLHttpRequest
是否已经完成Qƈ?XML 响应传递给调用者指定的事g处理函数。清?6 ?getReadyStateHandler()
的代码?/p>
清单 6. getReadyStateHandler() 函数
/*
* Returns a function that waits for the specified XMLHttpRequest
* to complete, then passes its XML response to the given handler function.
* req - The XMLHttpRequest whose state is changing
* responseXmlHandler - Function to pass the XML response to
*/
function getReadyStateHandler(req, responseXmlHandler) {
// Return an anonymous function that listens to the
// XMLHttpRequest instance
return function () {
// If the request's status is "complete"
if (req.readyState == 4) {
// Check that a successful server response was received
if (req.status == 200) {
// Pass the XML payload of the response to the
// handler function
responseXmlHandler(req.responseXML);
} else {
// An HTTP problem has occurred
alert("HTTP error: "+req.status);
}
}
}
}
HTTP 状态码 XMLHttpRequest
? status
属性以查看h是否成功完成?code>status 包含服务器响应的 HTTP 状态码。在执行单的 GET
?POST
hӞ可以假设M大于 200 QOKQ的码都是错误。如果服务器发送重定向响应Q例?301 ?302Q,览器会透明地进行重定向q从新的位置获取资源Q?code>XMLHttpRequest 看不到重定向状态码。而且Q浏览器会自动添?Cache-Control: no-cache
头到所?XMLHttpRequest
Q这样客户代码永q也不用处理 304Q未l修改)服务器响应?/p>getReadyStateHandler()
是段相对复杂的代码,特别是如果您不习惯阅?JavaScript 的话。但是通过把这个函数放?JavaScript 库中Q就可以处理 Ajax 服务器响应,而不必处?XMLHttpRequest
的内部细节。重要的是要理解如何在自q代码中?getReadyStateHandler()
?/p>
getReadyStateHandler()
像这栯调用Q?code>handlerFunction = getReadyStateHandler(req,
updateCart)。在q个CZ中,getReadyStateHandler()
q回的函数将查在 req
变量中的 XMLHttpRequest
是否已经完成Q然后用响应?XML 调用名ؓ updateCart
的函数?/p>
updateCart()
本n的代码。函数用 DOM 调用查购物R?XML 文档Q然后更?Web 面Q请参阅 清单 1Q,反映新的购物车内宏V这里的重点是用来从 XML DOM 提取数据的调用?code>cart 元素?generated
属性是?Cart
序列化ؓ XML 时生成的一个时间戳Q检查它可以保证新的购物车数据不会被旧的数据覆盖。Ajax h天生是异步的Q所以这个检查可以处理服务器响应未按ơ序到达的情c?/p>
清单 7. 更新面Q反映购物R?XML 文档
function updateCart(cartXML) {
// Get the root "cart" element from the document
var cart = cartXML.getElementsByTagName("cart")[0];
// Check that a more recent cart document hasn't been processed
// already
var generated = cart.getAttribute("generated");
if (generated > lastCartUpdate) {
lastCartUpdate = generated;
// Clear the HTML list used to display the cart contents
var contents = document.getElementById("cart-contents");
contents.innerHTML = "";
// Loop over the items in the cart
var items = cart.getElementsByTagName("item");
for (var I = 0 ; I < items.length ; I++) {
var item = items[I];
// Extract the text nodes from the name and quantity elements
var name = item.getElementsByTagName("name")[0]
.firstChild.nodeValue;
var quantity = item.getElementsByTagName("quantity")[0]
.firstChild.nodeValue;
// Create and add a list item HTML element for this cart item
var li = document.createElement("li");
li.appendChild(document.createTextNode(name+" x "+quantity));
contents.appendChild(li);
}
}
// Update the cart's total using the value from the cart document
document.getElementById("total").innerHTML =
cart.getAttribute("total");
}
XMLHttpRequest
可用时该如何响应Q虽然主要的C览器都支持 XMLHttpRequest
Q但仍然有少数用L览器不支持Q或者浏览器的安全设|阻止?XMLHttpRequest
。如果开发的 Web 应用E序要部|在企业内部|,那么可能拥有指定支持哪种览器的权力Q从而可以认?XMLHttpRequest
总能使用。但是,如果要部|在公共 Web 上,那么必d心,如果假设 XMLHttpRequest
可用Q那么就可能会阻止那些用旧的浏览器、残疾h专用览器和手持讑֤上的轻量U浏览器的用户用您的应用程序?/p>
XMLHttpRequest
支持的浏览器中也能够工作。在购物车的CZ中,把应用程序降U的最好方式可能是?Add to Cart 按钮执行一个常规的表单提交Q刷新页面来反映购物车更新后的状态。Ajax 的行为应当在面装入的时候就通过 JavaScript d到页面,只有?XMLHttpRequest
可用时才?JavaScript 事g处理函数附加到每?Add to Cart 按钮。另一U方式是在用L录时?XMLHttpRequest
是否可用Q然后相应地提供应用E序?Ajax 版本或基于表单的普通版本?/p>
XMLHttpRequest
不适用。一U技术是用“Now updating...”类型的信息替换 Submit 按钮Q这L户在{候响应期间就不会反复单击按钮了?/p>
XMLHttpRequest
会按照分z֮们的序完成。实际上Q应当假讑֮们不会按序完成Qƈ且在设计应用E序时把q一点记在心上。在购物车的CZ中,使用最后更新的旉x保新的购物车数据不会被旧的数据覆盖Q请参阅 清单 7Q。这个非常基本的方式可以用于购物车场景,但是可能不适合其他场景。所以在设计时请考虑如何处理异步的服务器响应?/p>
XMLHttpRequest
对象?Web 面向服务器发送异步请求?/li>XMLHttpRequest
的响应接收到的数据,JavaScript 客户端代码对于更新用L到的内容负有最l责仅R从服务器的角度来看Q视图成为它响应客户求而发送的数据表示?/p>
?1. 单的对象模型
XMLHttpRequest
对于发送数据用的格式没有做Q何限Ӟ但是对于多数目的来说Q只发送传l的表单数据是适合的,所以我的讨论集中在服务器的响应上。响应也可以有基于文本的格式Q但是正如它的名字表C的Q?code>XMLHttpRequest h内置的处?XML 响应数据的能力。这?XML 成ؓ Ajax 响应的默认选择Q所以我们从 XML 格式开始讨论?/p>
toXml()
Ҏ卛_。然后就可以选择合适的 XML APIQ让每个 bean
提供表示自己状态的元素Qƈ递归地对自己的成员调用对象图。显Ӟq种方式无法扩展到大量的c,因ؓ每个c都需要专门编写自q XML
生成代码。从好的斚w来看Q这是一个实现v来简单的方式Q没有额外的配置支出或者更复杂的构E支出,M JavaBean
N可以只用几个调用变?XML 文档?/p>
toXml()
Ҏ。上ơ我提到过Q这是个p糕的方法,因ؓ它把保标记配对、实体编码等工作的负担放在每?toXml()
Ҏ的代码中。在 Java q_上有几个 XML API 可以替您做这些工作,q样您就可以把精力集中在 XML 的内容上。清?1 ?JDOM API 实现了在U商店示例中表示订单的类中的 toXml()
Q请参阅 ?1Q?/p>
清单 1. Order cȝ toXml() ?JDOM 实现
public Element toXml() {
Element elOrder = new Element("order");
elOrder.setAttribute("id",id);
elOrder.setAttribute("cost",getFormattedCost());
Element elDate = new Element("date").addContent(date);
elOrder.addContent(elDate);
Element elItems = new Element("items");
for (Iterator
items.iterator() ; iter.hasNext() ; ) {
elItems.addContent(iter.next().toXml());
}
elOrder.addContent(elItems);
return elOrder;
}
toXml()
Ҏ是ؓ了取得它们子囄 Element
表示。例如,items
元素的内Ҏ通过调用 Order
聚合的每?Item
对象上的 toXml()
得到的?/p>
toXml()
ҎQ那么把L对象囑ֺ列化?XML 文档q返回给 Ajax 客户机就单了Q如清单 2 所C?/p>
清单 2. ?JDOM 元素生成 XML 响应
public void doGet(HttpServletRequest req, HttpServletResponse res)
throws java.io.IOException, ServletException {
String custId = req.getParameter("username");
Customer customer = getCustomer(custId);
Element responseElem = customer.toXml();
Document responseDoc = new Document(responseElem);
res.setContentType("application/xml");
new XMLOutputter().output(responseDoc,res.getWriter());
}
Document
Q然后用 XMLOutputter
把文档写?servlet 响应卛_。清?3 昄了用q种方式生成?XML CZQ用 JDOM Format.getPrettyFormat()
?XMLOutputter
q行初始化,格式化得非常好。在q个CZ中,֮只做了一个订单,包含两个商品?/p>
清单 3. 代表֮?XML 文档
Manufactured by Oolong Industries
shooting modes and 3x optical zoom. Silver.
ProductSearch
c,它就是以 Item
bean 列表的Ş式返回搜索结果,那么?Item
?XML 表示中包含说明可能会有帮助。而且Q?code>Item cM代表当前库存水^的额外字D,在品搜索视图中可能是需要显C的有用信息。但是,不管当前的库存水qx否与当前情况相关Q比如对֮的订单历史来_Q这个字D都会从包含 Item
的Q何对象图中序列化出来?/p>
Customer
bean q表C出定制?XML 视图Q适合客户端代码生成订单历史组件?/p>
清单 4. 生成订单历史文档?JSP
<%@ page contentType="application/xml" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<
?&
Q正{义就成了我的责Q。JSP 的核?out
标记使后面这工作变得很ҎQ但是不是所有的模板技术都提供了这L机制。最后,没有方便的途径可以在服务器端根据方案检验生成的 XML 文档的正性,但这毕竟不是要在生环境中做的事Q可以方便地在开发期间处理它?/p>
清单 5. ?JavaScript 中导?XML 响应文档
// Find name of first item in customer's last order
var orderHistoryDoc = req.responseXML;
var orders = orderHistoryDoc.getElementsByTagName("order");
var lastOrder = orders[orders.length - 1];
var firstItem = lastOrder.getElementsByTagName("item")[0];
var itemNameElement = firstItem.firstChild;
var itemNameText = itemNameElement.firstChild.data;
firstChild
l常是个I白文本节点。现在有 JavaScript 库可以缓解处?XML 文档的麻烦。这些库包括 Sarissa Q请参阅 参考资?/a>Q和 Google-ajaXSLTQ这两个库都?XPath 功能dC大多数浏览器中?/p>
responseXML
之外Q?code>XMLHttpRequest 对象q提供了名ؓ responseText
的属性,q个属性只是以字符串的方式提供服务器的响应体?/p>
responseText
?
XML 响应数据l合时也会有用。在只需要从响应文档中提取单一值的场景中,“欺骗性”地?XML
当作文本字符Ԍ而不把它当作l构化的文档对待Q会更方ѝ例如,清单 6
昄了如何用正则表达式从֮的订单历史中提取W一W订单的日期。不q,q实际是U花招,一般不应当依赖 XML 文档的词汇表达?/p>
清单 6. 用正则表辑ּ处理 XMLHttpRequest ?responseText 对象
var orderHistoryText = req.responseText;
var matches = orderHistoryText.match(/
var date = matches[1];
responseText
会比较方ѝ但是,理想情况下,应当有种途径Q可以用一U能够让 JavaScript LD、却没有 XML 处理支出的格式表C复杂的l构化数据。幸q的是,实存在q样一U格式?/p>
清单 7. ?JSON ?JavaScript 中直接声明一个简单对?/b>
var band = {
name: "The Beatles",
members: [
{
name: "John",
instruments: ["Vocals","Guitar","Piano"]
},
{
name: "Paul",
instruments: ["Vocals","Bass","Piano","Guitar"]
},
{
name: "George",
instruments: ["Guitar","Vocals"]
},
{
name: "Ringo",
instruments: ["Drums","Vocals"]
}
]
};
// Interrogate the band object
var musician = band.members[3];
alert( musician.name
+ " played " + musician.instruments[0]
+ " with " + band.name );
org.json
q个 Java API ?Java cM创徏 toJSONObject()
Ҏ。然后,可以把 JSONObject
单地序列化成 JSON。清?8 反映?清单 1 讨论?XMLQ显CZ Order
cȝ toJSONObject()
实现?/p>
清单 8. Order cȝ toJSONObject() Ҏ实现
public JSONObject toJSONObject() {
JSONObject json = new JSONObject();
json.put("id",id);
json.put("cost",getFormattedCost());
json.put("date",date);
JSONArray jsonItems = new JSONArray();
for (Iterator
items.iterator() ; iter.hasNext() ; ) {
jsonItems.put(iter.next().toJSONObject());
}
json.put("items",jsonItems);
return json;
}
JSONObject
代表 JavaScript 对象Q即联合数组Q,有不同的 put()
ҎQ方法接受的 String
键和值是原生cd?code>String cd或其?JSON cd?code>JSONArray 代表索引数组Q所以它?put()
Ҏ只接受一个倹{请注意在清?8 中,创徏 jsonItems
数组Q然后再?put()
把它附加?json
对象上;可以用另外一U方法做q项工作Q就是对每个目调用 json.accumulate("items",iter.next().toJSONObject());
?code>accumulate() Ҏ?put()
cMQ区别在于它把值添加到按照键进行识别的索引数组?/p>
JSONObject
q把它写?servlet 响应?/p>
清单 9. ?JSONObject 生成序列化的 JSON 响应
public void doGet(HttpServletRequest req, HttpServletResponse res)
throws java.io.IOException, ServletException {
String custId = req.getParameter("username");
Customer customer = getCustomer(custId);
res.setContentType("application/x-json");
res.getWriter().print(customer.toJSONObject());
}
JSONObject
?toString()
Ҏ做了所有工作。请注意Q?code>application/x-json 内容cdq有一点不定 —?在编写这文章的时候,关于 JSON 应当属于什?MIME cdq没有定论。但是,目前 application/x-json
是合理的选择。清?10 昄了这?servlet 代码的示例响应?/p>
清单 10. Customer bean ?JSON 表示
{
"orders": [
{
"items": [
{
"price": "$49.99",
"description": "512 Megabyte Type 1 CompactFlash card.
Manufactured by Oolong Industries",
"name": "Oolong 512MB CF Card",
"id": "i-55768"
},
{
"price": "$299.99",
"description": "7.2 Megapixel digital camera featuring six
shooting modes and 3x optical zoom. Silver.",
"name": "Fujak Superpix72 Camera",
"id": "i-74491"
}
],
"date": "08-26-2005",
"cost": "$349.98",
"id": "o-11123"
}
],
"realname": "James Hyrax",
"username": "jimmy66"
}
eval()
的简单调用实玎ͼq个函数可以x地解释包?JavaScript 表达式的字符丌Ӏ清?11 ?JSON 响应转变?JavaScript 对象图,然后执行清单 5 的Q务,从顾客的最后一ơ订单中得到W一个商品的名称?/p>
清单 11. 评估 JSON 响应
var jsonExpression = "(" + req.responseText + ")";
var customer = eval(jsonExpression);
// Find name of first item in customer's last order
var lastOrder = customer.orders[customer.orders.length-1];
var name = lastOrder.items[0].name;
XMLHttpRequest
l合q会?Ajax 交互看v来更?RPC 调用而不?SOA hQ这对应用程序的设计可能会有意义。在下一文章中Q我要研I的框架Q就是明地Z?JavaScript 代码Ҏ务器端对象进行远E方法调用而设计的?/p>
toJSONObject()
Ҏ到每?JavaBeanQ可伸羃性不太好Q虽然用内省和标注编写一个通用?JavaBean ?JSON
的序列化器可能很单。最后,如果服务器端代码是面向服务的Q没有单独针对处?Ajax 客户h调整q,那么׃?XML 一致的支持QXML
会是更好的选择?/p>
自行~写 XML 通过代码生成?XML l定 通过映射?XML l定 面模板 XML 手工~码?JSON 序列?/th> 可~?/td> ?/td> ?/td> 一?/td> 一?/td> ?/td> 易于集成 ?/td> ?/td> 一?/td> 一?/td> ?/td> Java c?API ?/td> ?/td> ?/td> ?/td> ?/td> 对输出的控制 ?/td> ?/td> 一?/td> ?/td> ?/td> 视图灉|?/td> ?/td> ?/td> ?/td> ?/td> ?/td> 客户端数据访?/td> ?/td> ?/td> ?/td> 一?/td> ?/td>
7. CDN CZ
商业化的CDN|络是用于服务性质的,高可用性等要求非常高,有专业品和CDN|络解决ҎQ本文主要从理论角度Q理解CDN的实现过E,q利用已有网l环境和开源Y件做实际配置Q更深刻理解CDN的具体工作过E?/p>
Linux 是开放源代码的免Ҏ作系l,已经成功应用于许多关键领域。Bind是Unix/FreeBSD/Linux{类unixq_上非常有名DNS服务E序Q? Internet上超q?0Q的DNSq行的是bind。Bind的最新版本是9.xQ用的比较多的是8.xQbind 9有很多新Ҏ,其中一ҎҎ用户端源地址对同一域名解析不同的IP地址Q有了这U特性,能把用户对同一域名的访问,引导C同地域节点的服务器上去访 问。Squid是Linux{操作系l上有名的Cache引擎Q与商业Cache引擎相比QSquid的性能比较低,基本功能工作原理与商业Cache? 品是一致的Q作验,是非常容易配|运行v来。以下简要介lCDN的配|流E?/p>
1、要加入CDN服务的网站,需要域?如www.linuxaid.com.cn,地址202.99.11.120)解析权提供给CDNq营 商,Linuxaid的域名解析记录只要把wwwL的A记录改ؓCNAMEq指向cache.cdn.com卛_。cache.cdn.com是CDN |络自定义的~存服务器的标识。在/var/named/linuxaid.com.cn域名解析记录中,由:
|
2、CDNq营商得到域名解析权以后Q得到域名的CNAME记录Q指向CDN|络属下~存服务器的域名Q如cache.cdn.comQCDN|络的全局负蝲均衡DNSQ需要把CNAME记录Ҏ{略解析出IP地址Q一般是l出p讉K的Cache地址?/p>
Bind 9的基本功能可以根据不同的源IP地址D解析对应的IPQ实现根据地域就q访问的负蝲均衡Q一般可以通过Bind 9的sortlist选项实现Ҏ用户端IP地址q回最q的节点IP地址Q具体的q程为:
1)为cache.cdn.com讄多个A记录Q?var/named/cdn.com 的内容如下:
|
2) /etc/named.conf中的内容为:
|
3、Cache在CDN|络中如果工作在服务器加速模式,因ؓ配置里已l写明加速服务器的urlQ所以Cache直接匚w用户hQ到源服务器 获得内容q缓存供下次使用Q如果Cache工作在客L加速模式,Cache需要知道源服务器的IP地址Q所以CDN|络l护和运行一个供Cache使用 的DNS服务器,解析域名的真实IP地址Q如202.99.11.120 Q各域名的解析记录与未加入CDN|络之前一栗?/p>
4、工作在CDN|络中缓存服务器必须工作在透明方式Q对于Squid来说Q需要设|以下参敎ͼ
|