选择显示字体大小

在struts应用中施展ajax魔法

ajax是最近在web开发流程中一次革命,它允许在一个普通的web浏览器中配置大量的动态效果。多年前struts 都已经是java-web开发中的一个事实上的标准,在大量的应用中都已经使用了它。本文将告诉你,如何在你已经存在struts应用中结合丰富的ajax没ы涌凇?

本文将介绍在jsp页面中包含一些javascript这样一个简单而有效的方法来结合ajaxstruts。在此我们介绍如何重新使用已经存在的struts actions,但此技术同样可用于你选择的其他java-web 框架。本方法同样可平移到struts或者jsf的下一个版本。

版权声明:任何获得授权的网站,转载时请务必保留以下作者信息和链接
作者:paul browne;pawenwen(作者的blog:http://blog.matrix.org.cn/page/pawenwen)
原文:原文链接
关键字:struts;ajax

什么是ajax

ajax是“异步的javascriptxml”的缩写。这是一项技术,而不是一个如struts一样的框架。为什么在ajax周围会有这么多的关注呢?这是因为ajax使web页面看起来并不像一个平面的文档,而更像用户所期望的如桌面应用的动态gui应用程序。ajax技术能在很多的浏览器上使用(包括ie.netscape/mozilla)。它已经为microsoft(用于outlook的web客户端)和google(用户google maps和gmail)所使用。

未使用ajax之前

目前大多数的struts应用都是标准的“如同一个平面文档的web页面”的结构。如果你想模仿一些桌面应用程序(比如那些使用java swing,visual basic,或者delphi建立的应用程序),那么你有两个选择:你可以发送所有的可能作为页面的一部分被请求的信息,使用大量的javascript来操作其动态的显示(一个很慢并且非企业级java的方法);或者你可以不改变形式地提交到后台服务器(一种有效的方法) 。ajax提高给你了融合前面的最佳解决方案:动态的页面,但是大多数的应用是在你的web服务器java程序来处理的。

ajax 101

ajax和现有的动态html技术非常相似,并在其上增加了一个发送到“后台”服务器的请求来获取需要的新的或者更新的信息。ajax的机制在其他地方已经有详细的说明――请查看本文后的resources来获取更多。但是你至少需要知道:
1. xmlhttprequest (如果你使用的是ie浏览器的话,则是microsoft.xmlhttp的activex的对象)。这些对象,你可以在web页面中使用javascript调用。他们允许你作为后台的调用方式来请求web服务器的内容(例如,在表单提交后,屏幕并不像平时一样显示“空白”)。
2. xmlhttprequest 和microsoft.xmlhttp 返回的内容可以作为xml或者文本来处理。javascript(在你页面上的)可以使用请求的新内容来更新页面。
3. 整个处理过程可以由普通的javascript事件来触发:onclick,onchange,onblur,等。

在你的struts应用中使用ajax

你阅读了本文,然后你会对使用ajax来创建动态的web页面感兴趣,并且想知道如何将它加入到你的struts应用中。这只是选择之一。那么你会如何选择呢?

· 等待,知道struts的下一个版本融合了ajax技术。如果struts开发者准备开发一个新的应用,这或许会是一个好的选择。再后面,可能会是要求jsf也这样做――对其本身并不一件坏事,但是对于已经存在的系统这将会带来最根本的改变。
· 你也可以直接采用新的方法,比如direct web remoting (dwr) 和ruby on rails,这些都是专为建立ajax应用的。如果你考虑不使用struts来开发web的话,那么这些都是很又用的框架,并且值得一试。但是,这也同时意味着你必须要重写你的应用。
· 在你已经存在的struts应用中增加ajax。既然ajax只是一项技术而并非框架,那么它就很容易融入到struts中。作为现有的系统,其稳定性(如,保持现有的库文件)是相当重要的。所以这个方法被推荐,并且我们将在后面详细介绍。

我们选择在struts应用中增加ajax的优势是:
1. 它并不需要任何新的库文件或者服务器代码;只需要使用现有的struts库文件和action。
2. 解决方案中所有部分――javascriptxmljavastruts――早已为广泛所知。
3. 此应用可以一块一块地移植到ajax;我们可以确定哪些部分对用户有益,并首先将它们更新到动态ajax显示。
实现方案

我们如何真正的贯彻我们的选择呢?我们首先应该注意一个“标准的”(没有ajaxstruts应用是如何工作的。在此应用中,一个一般的事件流程如下:
1. 使用点击超链接或者表单的提交按钮,用户发送请求。
2. web服务器运行处理请求的struts action来生成一个web页面。
3. 浏览器显示web页面。
4. 当用户点击保存的时候,信息由struts框架中一个actionform类来转换并发送到服务器
5. 然后,struts框架调用struts action来出来请求(如,保存数据到数据库中)。
6. 页面再一次回传,处理流程继续。

现有的struts应用

一个演示事件流程的简单struts应用可以在以下地址下载: struts-non-ajax.zip。此基于struts的应用,是基于用户的输入显示或者隐藏蓝色和绿色的表格。图1显示了载入初始页面的画面。图2显示了用户输入值并点击了提交后的画面。虽然简单,但它已经足以表示一个struts的工作流程。


图 1. 没有ajax的例子:初始屏幕


图 2. 没有ajax的例子:输入值并点击了提交

服务器端的代码是:一个struts action使用struts-config.xml 中定义的值转发到(相同的)jsp。这个例子代码中一些需要注意的地方是:
·struts-config.xml文件将所有的请求重定向到http://localhost:8080/struts-non-ajax/(或者和你自己的服务器相同)的index.jsp
· index.jsp 包含了一个两个文本框的struts form(showblue和showgreen)。该页面同样包含了标签,但是如同两个文本框被初始化为空,标签之间的内容并不显示。
· 用户输入值(true或者false)并点击提交按钮,处理控制(经过struts框架,读取struts-config.xml)提交到sampleaction类中。
·sampleaction记录下值,然后转发到index.jsp。一个成熟的struts应用可能会处理更多的事情,不如保存或者查询数据库等。
· index.jsp 现在重新处理请求;如果showblue或者showgreen的值是true,这些表格就显示出来。
该应用并没有任何“错误”。类似的struts项目好多年都是这样做的。但是,我们如何在不添加复杂的javascript或者频繁的表单提交的前提下,为此应用增加动态的元素呢?

我们的第一个struts ajax应用

观察下下面的图3和图4。第一眼看上去,它们和前面的例子没有说明区别。它们的不同之处在于,页面载入后(图3)然后文本框中的值改变了,窗体自动提交而不显示空白的,然后在图4中显示结果。普通的提交按钮仍然在,你也可以选择使用它。


图 3. 页面载入后的ajax例子


图 4. ajax调用后的ajax例子

添加ajax是出奇的容易。服务器端的代码和前面的例子是一样的: 一个struts的actionform来后去数据,一个struts的action来执行需要的任务(例如,存储数据库)然后转发到适当的jsp页面来显示结果。
继续

如果你希望就此停止阅读(跳过这个例子的工作说明),但是这里的是和你需要转换你的struts应用到一个strutsajax应用同样的风格:
1. 在你的web页面中引入一个ajax.js (该文件是struts-ajax.zip 例文件中的一部分)。ajax.js 包含了所有需要发送和接收ajax调用的javascript方法。
2. 确保你希望在ajax调用中更新的web页面的部分包含在标签中,并且给每个标签一个id。
3. 当一些事件触发的时候就更新页面(例如,文本框的the onchange()方法),调用retrieveurl()方法,通过url传递到需要执行服务器端处理的struts action。
4. 为了页面的显示/更新,最简单的方法是struts action转发回同样的页面。在本例中,showgreen/showblue 文本框中的onchange()方法来触发ajax调用。

javascript方法retrieveurl()调用服务器struts(通过url),获取jsp响应,然后更新显示页面中的 标签中的部分。就是这么简单!

ajax解决方案的细节

我们将例子变为ajaxstruts应用的时候,需要三个变化:
1. 增加一个javascript方法来完成到服务器的“背后的”ajax调用。
2. 增加javascript代码来接收服务器的响应并更新页面。
3. 在jsp页面增加标签标签,这个标签中内容将在ajax调用中更新。

我们将详细的说明上面的每一步。

发送ajax请求到服务器

有两个方法(在下面列出)用于发送请求到服务器
· retrieveurl()方法获得服务器的url和struts form。url用于使用ajax,form的值用于传递到服务器
· getformasstring()方法用于将retrieveurl()中form命名的值组装成查询字符串,并发送到服务器

使用方法很简单,使用onclick()/onchange()事件来触发retrieveurl()更新显示。

在这两个方法中有一些有趣的东西。

在retrieveurl()方法中,req.onreadystatechange = processstatechange (注意,没有括号)这一行来告诉浏览器在服务器响应到达的时候调用processstatechange()方法(该方法将在后面介绍)。retrieveurl()方法中(现在已经是ajax的标准了)同样决定是使用ie浏览器(activex)还是使.netscape/mozilla (xmlhttprequest) 来实现跨浏览器兼容。

getformasstring()方法将html form转换成字符串连接在url后面(这样就允许我们发送http get请求)。这个字符串是经过转换的(比如,空格转换成%20等),并且是一个struts能将其组装成actionform的格式(并不需要struts清楚的明白这个是来之ajax的请求)。注意,在本例中我们使用http get,使用http post的方法也是类似的。

function retrieveurl(url,nameofformtopost) {

//将url转换成字符串
url=url+getformasstring(nameofformtopost);

//调用ajax
if (window.xmlhttprequest) {

// 非ie浏览器
req = new xmlhttprequest();
req.onreadystatechange = processstatechange;
try {
req.open("get", url, true);
} catch (e) {
alert("server communication problem\n"+e);
}
req.send(null);
} else if (window.activexobject) {
// ie

req = new activexobject("microsoft.xmlhttp");
if (req) {
req.onreadystatechange=processstatechange;
req.open("get", url, true);
req.send();
}
}
}

getformasstring() 是一个“私有” 方法,在retrieveurl()中使用。

function getformasstring(formname){

//设置返回字符串
returnstring ="";

//取得表单的值
formelements=document.forms[formname].elements;

//循环数组,组装url
//像'/strutsaction.do&name=value'这样的格式

for(var i=formelements.length-1;i>=0; --i ){
//转化每一个值
returnstring+="&"
+escape(formelements[i].name)+"="
+escape(formelements[i].value);
}

//返回字符串
return returnstring;
}


根据ajax的响应更新web页面

到现在为止,我们学习过了使用javascript来完成ajax调用(前面列出),struts action,actionform以及jsp(基本没有变化,只是增加了标签)。为了完善我们对strutsajax项目的了解,我们需要了解三个用于根据服务器返回的结果而更新页面的javascript方法。

· processstatechange(): 该方法在ajax调用前设定。它在服务器响应到达后由xmlhttprequest/microsoft.xmlhttp 对象调用。
·splittextintospan(): 根据响应,循环取出数组中的元素组装成newcontent。
·replaceexistingwithnewhtml(): 根据span元素数组,循环搜索,将里面的元素调换掉页面中和它的'somename'相同的中的内容。注意,我们使用的是req.responsetext 方法来获得返回的内容(它允许我们操作任何文本的响应)。与此相对于的是req.responsexml (它的作用更大,但是要求服务器返回是xhtml或者xml)。

function processstatechange() {

if (req.readystate == 4) { // 完成
if (req.status == 200) { // 响应正常

//将响应的文本分割成span元素
spanelements =
splittextintospan(req.responsetext);

//使用这些span元素更新页面
replaceexistingwithnewhtml(spanelements);

} else {
alert("problem with server response:\n "
+ req.statustext);
}
}
}
replaceexistingwithnewhtml() 是为processstatechange()使用的“私有”方法。

function replaceexistingwithnewhtml
(newtextelements){

//循环newtextelements
for(var i=newtextelements.length-1;i>=0;--i){

//判断是否以 if(newtextelements[i].
indexof("-1){

//获得span的名字- 设置在第一和第二个引号之间
//确认span元素是以下的格式
//newcontent
startnamepos=newtextelements[i].
indexof('"')+1;
endnamepos=newtextelements[i].
indexof('"',startnamepos);
name=newtextelements[i].
substring(startnamepos,endnamepos);

//获得内容-在第一个>标记后的所有内容
startcontentpos=newtextelements[i].
indexof('>')+1;
content=newtextelements[i].
substring(startcontentpos);

//现在更新现有的document中的元素,
// 确保文档存在该元素
if(document.getelementbyid(name)){
document.getelementbyid(name).
innerhtml = content;
}
}
}
splittextintospan() 是为processstatechange() 使用的“私有”方法。
function splittextintospan(texttosplit){

//分割文档
returnelements=texttosplit.
split("")

//处理每个元素
for(var i=returnelements.length-1;i>=0;--i){

//删除掉第一个span后面的元素
spanpos = returnelements[i].
indexof("

//如果找到匹配的,获得span前的内容
if(spanpos>0){
substring=returnelements[i].
substring(spanpos);
returnelements[i]=substring;
}
}
return returnelements;
}


新的控制流

添加以下的javascript代码到我们的应用中,以下的步骤将在服务器和浏览器中执行。
1. 如同一个普通struts应用装载页面。
2. 用户改变文本框的值,触发一个onchange() 事件,调用retrieveurl() 方法。
3. 该javascript方法通过发送struts明白的表单变量(后台)请求到服务器struts action。
4. 该javascript方法同样设定了第二个javascript方法的名字,此方法将到服务器响应完毕后调用。本例子中,设定为processstatechange() 方法。
5. 如我们所预期的,服务器响应完毕,调用processstatechange() 方法。
6. javascript在(新的)服务器响应中循环取出所有元素。将页面上存在与获得元素名字相同的 中的元素替换掉。

在你的应用中设计ajax

以上描述的javascript方法能在大多数的应用中使用,包括比我们的例子复杂得多的。但是,在使用之前,你需要注意以下几点:
· 避免复制代码,最好在初始化请求(如,显示完整的页面)和ajax(更新部分页面)请求中使用相同的struts action和jsp
·在公共的action(控制器)中,决定jsp页面(所有的jsp页面或者其中的一部分)中的一个区域需要传送到浏览器。通过在web服务器的session或者actionform中设定标记来让jsp页面知道哪些部分需要提交。
· 在jsp中,使用struts 或者jstl标签来决定提交的html区域。

使用ajax的本例子,可以在以下下载: struts-ajax.zip

结语
ajax技术允许我们在创建和使用web应用的时候完全的改变。本文介绍了一个简单的技术,在现有的struts应用中增加struts的处理。它允许我们利用我们已有的东西,不仅仅是代码,还包括了开发的技能。作为一个好的产品,它同样允许我们写出更清晰,更具移植性的java struts应用。

资源
·作者的blog:http://blog.matrix.org.cn/page/pawenwen
· sample code for this article
· definition of ajax
· "using ajax to catch javascript errors" (xml.com文章)
· "developing ajax applications the easy way" (java.net文章)
· "an introduction to ajax" (dev2dev文章)
·"ajax on rails" (onlamp.com文章)
· dwr: direct web remoting project
· struts framework project
·jsf: java server faces project

paul browne 作为企业级java顾问为firstpartners.net 工作已有7年了。


 


关键字 本文所属关键字

相关 与本文相关文章

分类 所有文章关键字导航

源码编程相关

Java   Asp   PHP   .Net   XML   C/C++   CGI   VB   Jsp   J2ee   J2se   J2me   EJB   Servlet   Tomcat   Resin   Struts   Weblogic   Eclipse   ANT   GUI   JMS   Web servise   IDEA   Webphere   Hibernate   Spring   Jboss   Applet   Swing   Socket   Javamail   Perl   Ajax   P2P   安全   模式   框架   测试   开源   游戏

SQL数据库相关

My-SQL   Ms-SQL   Access   DB2   Oracle   Sybase   SQLserver   索引   存储过程   加密   数据库   分页   视图  

手机无线相关

3G   Wap   CDMA   GRPS   GSM   IVR   彩信   短信   无线   增值业务

网页设计制作相关

HTML   CSS   网页配色   网页特效   Javascript   VBscript   Dreamweaver   Frontpage   JS   Web   网站设计

网站建设推广相关

建站经验   网站优化   网站排名   推广   Alexa

操作系统/服务器相关

Windows XP   Windows 2000   Windows 2003   Windows Me   Windows 9.x   Linux   UNIX   注册表   操作系统   服务器   应用服务器

图形图像多媒体相关

Photoshop   Fireworks   Flash   Coreldraw   Illustrator   Freehand   Photoimpact   多媒体   图形图像

标准 网站致力的规范

Valid CSS!

无不良内容,无不良广告,无恶意代码

Valid XHTML 1.0 Transitional

creativecommons