??xml version="1.0" encoding="utf-8" standalone="yes"?> 未用AJAX之前 目前大多数的Struts应用都是标准?#8220;如同一个^面文档的web面”的结构。如果你x仿一些桌面应用程?比如那些使用Java SwingQVisual BasicQ或者Delphi建立的应用程?Q那么你有两个选择:你可以发送所有的可能作ؓ(f)面的一部分被请求的信息Q用大量的JavaScript来操作其动态的昄(一个很慢ƈ且非企业UJava的方?;或者你可以不改变Ş式地提交到后台服务器(一U有效的Ҏ(gu)) 。AJAX提高l你了融合前面的最佌x?动态的面Q但是大多数的应用是在你的web服务器的JavaE序来处理的?/p>
AJAX 101 AJAX和现有的动态HTML技术非常相|q在其上增加了一个发送到“后台”服务器的h来获取需要的新的或者更新的信息。AJAX的机制在其他地方已经有详l的说明――请查看本文后的Resources来获取更多。但是你臛_需要知? 在你的Struts应用中用AJAX 你阅M本文Q然后你?x)对使用AJAX来创建动态的web面感兴,q且想知道如何将它加入到你的Struts应用中。这只是选择之一。那么你?x)如何选择? 我们选择在Struts应用中增加AJAX的优势是: 实现Ҏ(gu) 我们如何真正的诏L们的选择?我们首先应该注意一?#8220;标准?#8221;(没有AJAX)Struts应用是如何工作的。在此应用中Q一个一般的事g程如下: 现有的Struts应用 一个演CZ件流E的单Struts应用可以在以下地址下蝲: struts-non-ajax.zip。此ZStruts的应用,是基于用L(fng)输入昄或者隐藏蓝色和l色的表根{图1昄了蝲入初始页面的画面。图2昄了用戯入值ƈ点击了提交后的画面。虽然简单,但它已经以表示一个Struts的工作流E?/p>
?1. 没有AJAX的例?初始屏幕 ?2. 没有AJAX的例?输入值ƈ点击了提?/p>
服务器端的代码是:一个Struts Action使用struts-config.xml 中定义的D{发到(相同?JSP。这个例子代码中一些需要注意的地方?
该应用ƈ没有M“错误”。类似的Struts目好多q都是这样做的。但是,我们如何在不d复杂的JavaScript或者频J的表单提交的前提下Qؓ(f)此应用增加动态的元素? 我们的第一个Struts AJAX应用 观察下下面的?和图4。第一眼看上去Q它们和前面的例子没有说明区别。它们的不同之处在于Q页面蝲入后(?)然后文本框中的值改变了Q窗体自动提交而不昄I白的,然后在图4中显C结果。普通的提交按钮仍然在,你也可以选择使用它?/p>
?3. 面载入后的AJAX例子 ?4. AJAX调用后的AJAX例子 dAJAX是出奇的Ҏ(gu)。服务器端的代码和前面的例子是一L(fng): 一个Struts的ActionForm来后L据,一个Struts的Action来执行需要的d(例如Q存储数据库)然后转发到适当的JSP面来显C结果?/p>
l箋 如果你希望就此停止阅?跌q个例子的工作说?Q但是这里的是和你需要{换你的Struts应用C个Struts-AJAX应用同样的风? JavaScriptҎ(gu)retrieveURL()调用服务器的Struts(通过URL)Q获取JSP响应Q然后更新显C页面中?标签中的部分。就是这么简? AJAX解决Ҏ(gu)的细?/p>
我们例子变为AJAX-Struts应用的时候,需要三个变? 我们详l的说明上面的每一步?/p>
发送AJAXh到服务器
有两个方?在下面列?用于发送请求到服务器?/p>
· retrieveURL()Ҏ(gu)获得服务器的URL和Struts form。URL用于使用AJAXQform的值用于传递到服务器?/p>
· getFormAsString()Ҏ(gu)用于retrieveURL()中form命名的值组装成查询字符Ԍq发送到服务器?/p>
使用Ҏ(gu)很简单,使用onclick()/onChange()事g来触发retrieveURL()更新昄?/p>
在这两个Ҏ(gu)中有一些有的东西?/p>
在retrieveURL()Ҏ(gu)中,req.onreadystatechange = processStateChange (注意Q没有括?q一行来告诉览器在服务器响应到辄时候调用processStateChange()Ҏ(gu)(该方法将在后面介l?。retrieveURL()Ҏ(gu)?现在已经是AJAX的标准了)同样军_是用IE览?ActiveX)q是使用Netscape/Mozilla (XmlHttpRequest) 来实现跨览器兼宏V?/p>
getFormAsString()Ҏ(gu)HTML form转换成字W串q接在URL后面(q样允许我们发送HTTP GETh)。这个字W串是经q{换的(比如Q空D{换成%20{?Qƈ且是一个Struts能将其组装成ActionForm的格?q不需要Struts清楚的明白这个是来之AJAX的请?。注意,在本例中我们使用HTTP GETQ用HTTP POST的方法也是类似的?/p>
function retrieveURL(url,nameOfFormToPost) { //url转换成字W串 //调用AJAX // 非IE览?br>req = new XMLHttpRequest(); req = new ActiveXObject("Microsoft.XMLHTTP"); getFormAsString() 是一?#8220;U有” Ҏ(gu)Q在retrieveURL()中用?/p>
function getFormAsString(formName){ //讄q回字符?br>returnString =""; //取得表单的?br>formElements=document.forms[formName].elements; //循环数组Q组装url for(var i=formElements.length-1;i>=0; --i ){ //q回字符?br>return returnString; 到现在ؓ(f)止,我们学习(fn)q了使用JavaScript来完成AJAX调用(前面列出)QStruts ActionQActionForm以及(qing)JSP(基本没有变化Q只是增加了标签)。ؓ(f)了完善我们对Struts-AJAX目的了解,我们需要了解三个用于根据服务器q回的结果而更新页面的JavaScriptҎ(gu)?/p>
function processStateChange() { if (req.readyState == 4) { // 完成 //响应的文本分割成Span元素 //使用q些Span元素更新面 } else { function replaceExistingWithNewHtml //循环newTextElements //判断是否?if(newTextElements[i]. //获得span的名? 讄在第一和第二个引号之间 //获得内容Q在W一?gt;标记后的所有内?br>startContentPos=newTextElements[i]. //现在更新现有的Document中的元素Q? //分割文档 //处理每个元素 //删除掉第一个span后面的元?br>spanPos = returnElements[i]. //如果扑ֈ匚w的,获得span前的内容 新的控制?/p>
d以下的JavaScript代码到我们的应用中,以下的步骤将在服务器和浏览器中执行?/p>
在你的应用中设计AJAX 以上描述的JavaScriptҎ(gu)能在大多数的应用中用,包括比我们的例子复杂得多的。但是,在用之前,你需要注意以下几? · 避免复制代码Q最好在初始化请?如,昄完整的页?和AJAX(更新部分面)h中用相同的Struts Action和JSP?/p>
·在公qAction(控制?中,军_JSP面(所有的JSP面或者其中的一部分)中的一个区域需要传送到览器。通过在web服务器的session或者ActionForm中设定标记来让JSP面知道哪些部分需要提交?/p>
· 在JSP中,使用Struts 或者JSTL标签来决定提交的HTML区域?/p>
使用AJAX的本例子Q可以在以下下蝲: struts-Ajax.zip l语 AJAX技术允许我们在创徏和用web应用的时候完全的改变。本文介l了一个简单的技术,在现有的Struts应用中增加Struts的处理。它允许我们利用我们已有的东西,不仅仅是代码Q还包括了开发的技能。作Z个好的品,它同样允许我们写出更清晰Q更L(fng)植性的Java Struts应用?/p>
版权声明QTechtarget获Matrix授权发布,如需转蝲误pMatrix 2。不l意使用的无M的标讎ͼ如web 服务器解析时当作一个无M的标讎ͼ随后使用的标记都被认为是在这个标C外的 4。property必须和所要提交的action对应的formbean中的某个属性相匚wQ必L一个formbean)
当Action的valueStack中有该属性的值时Q只需直接使用该属性的名字卛_Q?
当Action的valueStack中没有该属性的值时Q比如在session,application范围中的属性值时Q需要加#或?attr.Q?
例子Q?
假设某Action中有person成员变量Q在application中存在company属?
那么我们可以通过以下Ҏ(gu)取|(x)
<s:property value="person.name" />
<s:property value="#person.name" />
<s:property value="company.name" /> //无法取到Q因为company不在action的valueStack?
<s:property value="#company.name" />
<s:textfield name="person.name" value="person.name" /> //错误Qvalue?x)直接显Cperson.name字样
<s:textfield name="person.name" value="%{person.name}" />
<s:textfield name="person.company.name" value="%{#company.name}" />
<s:textfield name="person.company.name" value="%{#attr.company.name}" />
]]>
很显然这是一个没有找到对应的cL件的异常?br />
q有两个包commons-pool.jar和commons-dbcp-1.2.1.jar需要引入到工程中?/span>
]]>
AJAX?#8220;异步的JavaScript和XML”的羃写。这是一Ҏ(gu)术,而不是一个如Struts一L(fng)框架。ؓ(f)什么在AJAX周围?x)有q么多的x?q是因ؓ(f)AJAX使web面看v来ƈ不像一个^面的文档Q而更像用h期望的如桌面应用的动态GUI应用E序。AJAX技术能在很多的览器上使用(包括IE和Netscape/Mozilla)。它已经为Microsoft(用于Outlook的web客户?和Google(用户Google Maps和Gmail)所使用?
url=url+getFormAsString(nameOfFormToPost);
if (window.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
if (req) {
req.onreadystatechange=processStateChange;
req.open("GET", url, true);
req.send();
}
}
}
//?/strutsaction.do&name=value'q样的格?/p>
//转化每一个?br>returnString+="&"
+escape(formElements[i].name)+"="
+escape(formElements[i].value);
}
}
if (req.status == 200) { // 响应正常
spanElements =
splitTextIntoSpan(req.responseText);
replaceExistingWithNewHtml(spanElements);
alert("Problem with server response:\n "
+ req.statusText);
}
}
}
replaceExistingWithNewHtml() 是ؓ(f)processStateChange()使用?#8220;U有”Ҏ(gu)?/p>
(newTextElements){
for(var i=newTextElements.length-1;i>=0;--i){
indexOf("-1){
//认span元素是以下的格式
//NewContent
startNamePos=newTextElements[i].
indexOf('"')+1;
endNamePos=newTextElements[i].
indexOf('"',startNamePos);
name=newTextElements[i].
substring(startNamePos,endNamePos);
indexOf('>')+1;
content=newTextElements[i].
substring(startContentPos);
// 保文档存在该元?br>if(document.getElementById(name)){
document.getElementById(name).
innerHTML = content;
}
}
}
splitTextIntoSpan() 是ؓ(f)processStateChange() 使用?#8220;U有”Ҏ(gu)?br>function splitTextIntoSpan(textToSplit){
returnElements=textToSplit.
split("")
for(var i=returnElements.length-1;i>=0;--i){
indexOf("
if(spanPos>0){
subString=returnElements[i].
substring(spanPos);
returnElements[i]=subString;
}
}
return returnElements;
}
作?作?Paul Browne;pawenwen(作者的blog:http://blog.matrix.org.cn/page/pawenwen)
译文:点击
]]>
3。还有就是在使用taglib引入HTML标记库时Q你使用的prefix的g是html
5。要使用标签Q外层必M用标{,不能使用html?/font>
]]>
原因Q?action参数配置不全
解决Ҏ(gu)Q在 config文g?d parameter="method"{?
错误Q?表单数据验证p|时发生错误,“No input attribute for mapping path”
原因Qaction中表单验?validate="true" Q如果validate()q回非空的ActionErrorsQ将?x)被转到input属性指定的URIQ而action中未指定input时会(x)报此?
解决Ҏ(gu)Q添?input="url" 或?validate="false"