﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-一切都是高科技-文章分类-JavaEE</title><link>http://www.blogjava.net/zhangxy/category/20802.html</link><description /><language>zh-cn</language><lastBuildDate>Wed, 04 Apr 2007 08:03:39 GMT</lastBuildDate><pubDate>Wed, 04 Apr 2007 08:03:39 GMT</pubDate><ttl>60</ttl><item><title>Ajax以及DWR应用初步</title><link>http://www.blogjava.net/zhangxy/articles/104915.html</link><dc:creator>张孝勇</dc:creator><author>张孝勇</author><pubDate>Tue, 20 Mar 2007 04:07:00 GMT</pubDate><guid>http://www.blogjava.net/zhangxy/articles/104915.html</guid><wfw:comment>http://www.blogjava.net/zhangxy/comments/104915.html</wfw:comment><comments>http://www.blogjava.net/zhangxy/articles/104915.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/zhangxy/comments/commentRss/104915.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/zhangxy/services/trackbacks/104915.html</trackback:ping><description><![CDATA[          Ajax （Asynchronous Javascript and XML）是一项综合技术，使用它可以构建更为动态和响应更灵敏的Web应用程序。该方法的关键在于对浏览器端的JavaScript、DHTML和与服务器异步通信的组合。能方便的利用一个Ajax框架（DWR）构造一个应用程序，它直接从浏览器与后端服务进行通信。<br /><br /><strong>简介</strong><br /><br />         Ajax提供与服务器异步通信的能力，从而使用户从请求/响应的循环中解脱出来。借助于Ajax，可以在用户单击按钮时，使用JavaScript和DHTML立即更新UI，并向服务器发出异步请求，以执行更新或查询数据库。当请求返回时，就可以使用JavaScript和CSS来相应地更新UI，而不是刷新整个页面。它能允许开发人员和设计人员使用标准的HTML/CSS/JavaScript堆栈创建“桌面风格的（desktop-like）”Web应用。<br /><br />下面是几个具体的应用：<br /><ul><li><a href="http://backpackit.com/" target="_blank"><font color="#002c99">BackPack</font></a></li><li><a href="http://www.google.com/webhp?complete=1&amp;hl=en" target="_blank"><font color="#002c99">Google Suggest</font></a></li><li><a href="http://maps.google.com/" target="_blank"><font color="#002c99">Google Maps</font></a></li></ul><p>　　所有这些Web站点都告诉我们，Web应用程序不必完全依赖于从服务器重新载入页面来向用户呈现更改。<br /></p><p><strong>定义Ajax</strong></p><p>　　Ajax不是一种技术。实际上，它由几种技术以新的强大方式组合而成。Ajax包含：</p><ul><li>基于<a href="http://www.w3.org/TR/xhtml1/" target="_blank"><font color="#002c99">XHTML</font></a>和<a href="http://www.w3.org/Style/CSS/" target="_blank"><font color="#002c99">CSS</font></a>标准的表示； 
</li><li>使用<a href="http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407/introduction.html" target="_blank"><font color="#002c99">Document Object Model</font></a>进行动态显示和交互； 
</li><li>使用XMLHttpRequest与服务器进行异步通信； 
</li><li>使用JavaScript绑定一切。</li></ul><p><strong>Ajax的工作原理</strong></p><p>　　Ajax的核心是JavaScript对象XmlHttpRequest。该对象在Internet Explorer 5中首次引入，它是一种支持异步请求的技术。XmlHttpRequest使您可以使用JavaScript向服务器提出请求并处理响应，而不阻塞用户。</p><p>　　下面是使用Ajax可以完成的功能：</p><ul><li>动态更新购物车的物品总数，无需用户单击Update并等待服务器重新发送整个页面。 
</li><li>提升站点的性能，这是通过减少从服务器下载的数据量而实现的。 
</li><li>消除了每次用户输入时的页面刷新。 
</li><li>直接编辑表格数据，而不是要求用户导航到新的页面来编辑数据。</li></ul><p>　　<br />      我们利用Ajax实现自己的基本投票系统。</p><p><strong>原始的Ajax：直接使用XmlHttpRequest</strong></p><p><br /></p><p>浏览应用程序，参与投票，并亲眼看它如何运转。熟悉了该应用程序之后，进一步了解其工作原理细节。</p><p>　　首先，您拥有一些简单的定位点标记，它连接到一个JavaScriptcastVote(rank)函数。 </p><pre class="code">function castVote(rank) {
  var url = "/ajax-demo/static-article-ranking.html";
  var callback = processAjaxResponse;
  executeXhr(callback, url);
}
</pre><p>　　该函数为您想要与之通信的服务器资源创建一个URL并调用内部函数executeXhr，提供一个回调JavaScript函数，一旦服务器响应可用，该函数就被执行。由于我希望它运行在一个简单的Apache环境中，“cast vote URL”只是一个简单的HTML页面。在实际情况中，被调用的URL将记录票数并动态地呈现包含投票总数的响应。</p><p>　　下一步是发出一个XmlHttpRequest请求： </p><pre class="code">function executeXhr(callback, url) {
    if (window.XMLHttpRequest) {
    req = new XMLHttpRequest();
    req.onreadystatechange = callback;
    req.open("GET", url, true);
    req.send(null);<br />
  } else if (window.ActiveXObject) {<br />
    req = new ActiveXObject("Microsoft.XMLHTTP");
    if (req) {
      req.onreadystatechange = callback;
      req.open("GET", url, true);
      req.send();
    }
  }
}

</pre><p>　　执行一个XmlHttpRequest并不简单，但非常直观。在JavaScript领域，大部分的工作量都花在确保浏览器兼容方面。在这种情况下，首先要确定XmlHttpRequest是否可用。如果不能用，很可能要使用Internet Explorer，这样就要使用所提供的ActiveX实现。</p><p>executeXhr()方法中最关键的部分是这两行： </p><pre class="code">req.onreadystatechange = callback;
req.open("GET", url, true);
</pre><p>　　第一行定义了JavaScript回调函数，您希望一旦响应就绪它就自动执行，而req.open()方法中所指定的“true”标志说明您想要异步执行该请求。</p><p>　　一旦服务器处理完XmlHttpRequest并返回给浏览器，使用req.onreadystatechange指派所设置的回调方法将被自动调用。 </p><pre class="code">function processAjaxResponse() {
    if (req.readyState == 4) {
      if (req.status == 200) {
      $('votes').innerHTML = req.responseText;
    } else {
      alert("There was a problem retrieving the XML data:\n" +
      req.statusText);
    }
  }
} 
</pre><p>　　该代码相当简洁，并且使用了几个数字，这使得难以一下子看出发生了什么。为了弄清楚这一点，下面的表格 列举了常用的XmlHttpRequest对象属性。</p><p></p><table cellspacing="1" cellpadding="0" width="80%" bgcolor="#cccccc" border="0"><tbody><tr bgcolor="#ffffff"><td height="22"><p><strong>属性</strong></p></td><td><p><strong>描述</strong></p></td></tr><tr bgcolor="#ffffff"><td valign="top" height="22"><p>onreadystatechange</p></td><td valign="top"><p>每次状态改变所触发事件的事件处理程序</p></td></tr><tr bgcolor="#ffffff"><td valign="top" height="22"><p>readyState</p></td><td valign="top"><p>对象状态值： </p><ul><li>0 = 未初始化（uninitialized） 
</li><li>1 = 正在加载（loading） 
</li><li>2 = 加载完毕（loaded） 
</li><li>3 = 交互（interactive） 
</li><li>4 = 完成（complete） </li></ul></td></tr><tr bgcolor="#ffffff"><td valign="top" height="22"><p>responseText</p></td><td valign="top"><p>从服务器进程返回的数据的字符串形式</p></td></tr><tr bgcolor="#ffffff"><td valign="top" height="22"><p>responseXML</p></td><td valign="top"><p>从服务器进程返回的DOM兼容的文档数据对象</p></td></tr><tr bgcolor="#ffffff"><td valign="top" height="22"><p>status</p></td><td valign="top"><p>从服务器返回的数字代码，比如404（未找到）或200（就绪）</p></td></tr><tr bgcolor="#ffffff"><td valign="top" height="22"><p>statusText</p></td><td valign="top"><p>伴随状态码的字符串信息</p></td></tr></tbody></table><p>　　现在processVoteResponse()函数开始显示出其意义了。它首先检查XmlHttpRequest的整体状态以保证它已经完成（readyStatus == 4），然后根据服务器的设定询问请求状态。如果一切正常（status == 200）,就使用innerHTML属性重写DOM的“votes”节点的内容。</p><p>　　我们利用一个简化JavaScript与Java应用程序之间的异步通信的框架来对具体的细节进行抽象。</p><p><strong>Ajax: DWR方式</strong></p><p>　　我们使用Direct Web Remoting（DWR）框架实现同样的功能。</p><p>　　假定文章和投票结果存储在一个数据库中，使用某种对象/关系映射技术来完成抽取工作。为了部署起来尽可能地简单，我们不会使用数据库进行持久性存储。此外，为使应用程序尽可能通用，也不使用Web框架。相反，应用程序将从一个静态HTML文件开始，可以认为它由服务器动态地呈现。除了这些简化措施，应用程序还应该使用Spring Framework关联一切，以便轻松看出如何在一个“真实的”应用程序中使用DWR。</p><p>　　下载示例应用程序并熟悉它。该应用程序被压缩为标准的WAR文件，因此您可以把它放置到任何一个Web容器中——无需进行配置。部署完毕之后，就可以导航到<a href="http://localhost:7001/ajax-demo/dwr-ajax.html" target="_blank"><font color="#002c99">http://localhost:7001/ajax_demo/dwr-ajax.html</font></a>来运行程序。</p><p>　　可以查看<a href="http://dev2dev.bea.com/2005/08/source.html" target="_blank"><font color="#002c99">HTML 源代码</font></a>，了解它如何工作。给人印象最深的是，代码如此简单——所有与服务器的交互都隐藏在JavaScript对象ajaxSampleSvc的后面。更加令人惊讶的是，ajaxSampleSvc服务不是由手工编写而是完全自动生成的！让我们继续，看看这是如何做到的。</p><p><strong>引入DWR</strong></p><p>　     直接使用XmlHttpRequest创建异步请求非常麻烦。不仅JavaScript代码冗长，而且必须考虑服务器端为定位Ajax请求到适当的服务所需做的工作，并将结果封送到浏览器。</p><p>　　设计DWR的目的是要处理将Web页面安装到后端服务上所需的所有信息管道。它是一个Java框架，可以很轻松地将它插入到Web应用程序中，以便JavaScript代码可以调用服务器上的服务。它甚至直接与Spring Framework集成，从而允许用户直接向Web客户机公开bean。</p><p>　　DWR真正的巧妙之处是，在用户配置了要向客户机公开的服务之后，它使用反射来生成JavaScript对象，以便Web页面能够使用这些对象来访问该服务。然后Web页面只需接合到生成的JavaScript对象，就像它们是直接使用服务一样；DWR无缝地处理所有有关Ajax和请求定位的琐碎细节。</p><p>　　让我们仔细分析一下示例代码，弄清它是如何工作的。<br /></p><p><strong>应用程序细节：DWR分析</strong></p><p>　　它是一个标准的Java应用程序，使用分层架构（Layered Architecture）设计模式。使用DWR通过JavaScript公开一些服务并不影响您的设计。 </p><p><img height="344" src="http://dev2dev.bea.com.cn/images/051101/0511010102.jpg" width="209" /></p><p>　　下面是一个简单的Java服务，我们将使用DWR框架直接将其向JavaScript代码公开：</p><pre class="code">package com.tearesolutions.service;

public interface AjaxSampleSvc { 
  Article castVote(int rank);
}
</pre><p>　　这是一个被简化到几乎不可能的程度的例子，其中只有一篇文章可以投票。该服务由Spring管理，它使用的bean名是ajaxSampleSvc，它的持久性需求则依赖于ArticleDao。详情请参见applicationContext.xml。<br /></p><p>　为了把该服务公开为JavaScript对象，需要配置DWR，添加dwr.xml文件到WEB-INF目录下： </p><pre class="code">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;!DOCTYPE dwr PUBLIC
 "-//GetAhead Limited//DTD Direct Web Remoting 0.4//EN"
 "http://www.getahead.ltd.uk/dwr/dwr.dtd"&gt;
	
&lt;dwr&gt;
 &lt;allow&gt;
  &lt;create creator="spring" javascript="ajaxSampleSvc"&gt;
   &lt;param name="beanName" value="ajaxSampleSvc" /&gt;
  &lt;/create&gt;
  &lt;convert converter="bean" match="com.tearesolutions.model.Article"/&gt;
  &lt;exclude method="toString"/&gt;
  &lt;exclude method="setArticleDao"/&gt;
 &lt;/allow&gt;
&lt;/dwr&gt;
</pre><p>　　dwr.xml文件告诉DWR哪些服务是要直接向JavaScript代码公开的。注意，已经要求公开Spring bean ajaxSampleSvc。DWR将自动找到由应用程序设置的SpringApplicationContext。为此，必须使用标准的servlet过滤器ContextLoaderListener来初始化Spring ApplicationContext。</p><p>　　DWR被设置为一个servlet，所以把它的定义添加到web.xml： </p><pre class="code">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD 
 Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd"&gt;

&lt;web-app&gt;
 &lt;display-name&gt;Ajax Examples&lt;/display-name&gt;

 &lt;listener&gt;
  &lt;listener-class&gt;
      org.springframework.web.context.ContextLoaderListener
  &lt;/listener-class&gt;
 &lt;/listener&gt;
	
 &lt;servlet&gt;
  &lt;servlet-name&gt;ajax_sample&lt;/servlet-name&gt;
  &lt;servlet-class&gt;com.tearesolutions.web.AjaxSampleServlet&lt;/servlet-class&gt;
  &lt;load-on-startup&gt;1&lt;/load-on-startup&gt;
 &lt;/servlet&gt;

 &lt;servlet&gt;
  &lt;servlet-name&gt;dwr-invoker&lt;/servlet-name&gt;
  &lt;display-name&gt;DWR Servlet&lt;/display-name&gt;
  &lt;description&gt;Direct Web Remoter Servlet&lt;/description&gt;
  &lt;servlet-class&gt;uk.ltd.getahead.dwr.DWRServlet&lt;/servlet-class&gt;
  &lt;init-param&gt;
   &lt;param-name&gt;debug&lt;/param-name&gt;
   &lt;param-value&gt;true&lt;/param-value&gt;
  &lt;/init-param&gt;
 &lt;/servlet&gt;

 &lt;servlet-mapping&gt;
  &lt;servlet-name&gt;ajax_sample&lt;/servlet-name&gt;
  &lt;url-pattern&gt;/ajax_sample&lt;/url-pattern&gt;
 &lt;/servlet-mapping&gt;

 &lt;servlet-mapping&gt;
  &lt;servlet-name&gt;dwr-invoker&lt;/servlet-name&gt;
  &lt;url-pattern&gt;/dwr/*&lt;/url-pattern&gt;
 &lt;/servlet-mapping&gt;
&lt;/web-app&gt;
</pre><p>　　做完这些之后，可以加载<a href="http://localhost:7001/ajax-demo/dwr" target="_blank"><font color="#002c99">http://localhost:7001/ajax-demo/dwr</font></a>，看看哪些服务可用。结果如下：</p><p><img height="102" src="http://dev2dev.bea.com.cn/images/051101/0511010103.jpg" width="305" /></p><p>图3. 可用的服务</p><p>　　单击ajaxSampleSvc链接，查看有关如何在HTML页面内直接使用服务的示例实现。其中包含的两个JavaScript文件完成了大部分的功能： </p><pre class="code">&lt;script type='text/javascript' 
   src='/ajax-demo/dwr/interface/ajaxSampleSvc.js'&gt;&lt;/script&gt;
&lt;script type='text/javascript' 
   src='/ajax-demo/dwr/engine.js'&gt;&lt;/script&gt;
</pre><p>ajaxSampleSvc.js是动态生成的：</p><pre class="code">function ajaxSampleSvc() { }

ajaxSampleSvc.castVote = function(callback, p0)
{ 
  DWREngine._execute(callback, '/ajax-demo/dwr', 
 'ajaxSampleSvc', 'castVote', p0);
}
</pre><p>　　现在可以使用JavaScript对象ajaxSampleSvc替换所有的XmlHttpRequest代码，从而重构raw-ajax.html文件。可以在dwr-ajax.html文件中看到改动的结果；下面是新的JavaScript函数：</p><pre class="code">function castVote(rank) {
  ajaxSampleSvc.castVote(processResponse, rank);
}
function processResponse(data) {
 var voteText = "<p><strong>Thanks for Voting!</strong></p>"
    + "<p>Current ranking: " + data.voteAverage 
    + " out of 5</p>" 
    + "<p>Number of votes placed: " 
    + data.numberOfVotes + "</p>";
 $('votes').innerHTML = voteText;       
}
</pre><p>　　惊人地简单，不是吗？由ajaxSampleSvc对象返回的Article域对象序列化为一个JavaScript对象，允许在它上面调用诸如numberOfVotes()和voteAverage()之类的方法。在动态生成并插入到DIV元素“votes”中的HTML代码内使用这些数据。</p><strong><p><strong>《完》<br /><br />下载</strong></p><p>　　本文中演示的应用程序源代码可供下载：<a href="http://dev2dev.bea.com/2005/08/ajax-demo.war" target="_blank"><font color="#002c99">ajax-demo.war</font></a>。</p><p></p></strong><br /> <img src ="http://www.blogjava.net/zhangxy/aggbug/104915.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/zhangxy/" target="_blank">张孝勇</a> 2007-03-20 12:07 <a href="http://www.blogjava.net/zhangxy/articles/104915.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>