ajaxanywhere 總結(jié):
1,簡介
AjaxAnywhere被設(shè)計成能夠把任何一套現(xiàn)存的JSP組件轉(zhuǎn)換成AJAX感知組件而不需要復(fù)雜的JavaScript編碼.它利用標簽把Web頁面簡單地劃分成幾個區(qū)域,然后使用AjaxAnywhere來刷新那些需要被更新地區(qū)域
2,ajaxanywhere學(xué)習有兩天了。ajaxanywhere與jsp,servlet,struts都能配合使用得很好。但是也有一些問題。
這幾天找了一些ajax的開源,感覺ajaxtags功能有限且實現(xiàn)復(fù)雜,很難和其他框架集成。strutstags
倒很對路但是提供的例子里竟然沒有strutsconfig.xml運行不起來,沒辦法,我只好轉(zhuǎn)向ajaxanywhere,用了一天的時間才把ajaxanywhere與servlet,struts框架分別結(jié)成起來,處理主要集中在aa.js,不是不用寫js,而是只要寫少量的js就可以實現(xiàn)復(fù)雜的調(diào)用。感覺很簡單。
但是它也有不足之處,Demo中deServerSide.jsp例子點14下后竟然死掉了,sourceforge論壇上
294條記錄竟然沒有一個人發(fā)現(xiàn),我和其他幾個同事使用他們提供的網(wǎng)上Demo也是一樣,提了這個
問題一時半會也沒有人解答??磥?,這也是js牛人才能真正玩的通的,為什么這么說呢?因為一旦出
了問題就要研究aa.js了。說是不用自己寫js,但實際上還是要把aa.js研究透了才敢用到項目中。
下面把我這兩天的所學(xué)做一下總結(jié):
2.1 從配置上來講:
ajaxanywhere沒有tld文件,但是他需要在web.xml中配置一個filter,這就足夠了。
<filter>
<filter-name>AjaxAnywhere</filter-name>
<filter-class>org.ajaxanywhere.AAFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>AjaxAnywhere</filter-name>
<url-pattern>*.jsf</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>AjaxAnywhere</filter-name>
<url-pattern>*.jsp</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>AjaxAnywhere</filter-name>
<url-pattern>*.do</url-pattern>
</filter-mapping>
值得注意的是,只有通過此filter的request url才能夠使用它的功能,所以要確保需要此功能的url能夠通過此filter!我剛開始的時候?qū)懥艘粋€servlet與ajaxanywhere的jsp頁面聯(lián)合使用,但總是抱錯:“說返回的類型并不是text/xml”類型,后來
我想肯定是要求servlet必須返回text/xml類型了,于是就在servlet的末尾增加了一句話:
response.setContentType("text/xml; charset=UTF-8");心想這回沒錯了吧,沒想到運行時仍舊顯示“返回類型不是
text/xml”,這是頁面的js報的錯誤,也就是在返回信息到了頁面,葉面分析返回數(shù)據(jù)的時候報的錯誤。仔細檢查了servlet
設(shè)置返回類型的那句話并沒有錯誤。
原來問題出在servlet的mapping上面,設(shè)置了一個/xxxx沒有帶".do"(這時還沒有struts環(huán)境呢),這樣一來,servelt返回給頁面的response并沒有被AjAxanywhere Filter截獲,當然就沒有沒有被處理過(具體內(nèi)部處理不太清楚),于是就出了上面的錯誤。
解決方法很簡單,把所有需要ajaxanywhere的servlet mapping配置成一個比較特殊的后綴,例如localServlet.aj這樣在
web.xml中配置AjaxAnywhere過濾器的filer-mapping 增加一條
<filter-mapping>
<filter-name>AjaxAnywhere</filter-name>
<url-pattern>*.aj</url-pattern>
</filter-mapping>
這樣所有的后綴為aj的servlet就都可以使用上此Filter了。錯誤就沒有了。ok,上面講了ajaxanywhere + servlet 的方法。
2.2 配置ajaxanywhere + struts .
配置也比較簡單。在struts的配置正確的基礎(chǔ)上,只需要配置ajaxanywhere的filter,增加一個mapping,如果struts ActionServlet配置了mapping *.xx ,那么表示所與后綴為xx的url都經(jīng)過AcitonServlet來處理,好,ajaxanywhere要求所有的
url在進入AciontServlet之前首先進入他的Filter,離開ActionServlet之后也要首先進入他的Filter,而不是直接返回頁面。
這樣,只要在ajaxanywhere filter的mapping后面增加
<filter-mapping>
<filter-name>AjaxAnywhere</filter-name>
<url-pattern>*.xx</url-pattern>
</filter-mapping>
即可。這樣就能和struts配置使用了。
2.3 配置ajaxanywhere +?。辏骹
例子中也講到了與jsf配合使用的方法,jsf我沒有用過,但是配置ajaxanywhere要做得就是增加一個filter-mapping而已。假設(shè)jsf的后綴是*.jsf,那么只需要在 ajaxanywhere filter中增加一個此后綴的mapping,就ok了。
2.4 ajaxanywhere + * +?。辏螅簦?br> 于jstl連用實際上就是與jsp連用,但是把jstl也融合進來需要注意,ajaxanywhere Demo例子中的web.xml
不兼容jstl,所以除了要把必要的jar文件tld文件拷貝到項目之外,還要把web.xml的頭部進行修改,原來是這樣寫的
<web-app>..... ,必須要修改成
<web-app xmlns="http://java.sun.com/xml/ns/j2ee 這樣才行。
否則你會發(fā)現(xiàn)一個特別奇怪的錯誤,例如<c:forEach items="sdfsd" var="item">${item.value}</c:forEach>
就是不循環(huán)顯示,但是<c:out value="xxxx"/>卻可以運行,當時就懵了。修改了web.xml之后就一切正常了^_^
3,ajaxanywhere的目錄結(jié)構(gòu)和文件的特色。
和普通的項目的區(qū)別就在三個地方:
3.1 /aa/aa.js 里面包含了ajaxanywhere必須使用的javascript對象和方法。這個文件必須用,
而且每個jsp頁面都要引用他,如果想深入使用就有必要對里面的方法有所了解。
3.2 多了一個Filter,一個ajaxanywhere.jar,對程序員是透明的。
3.3 jsp頁面要引入lib<%@ taglib uri=" 簡單使用時只需要配置好<aa:zone>,
然后當Get方法(鏈接跳轉(zhuǎn)),某標簽的onclick中調(diào)用“ajaxAnywhere.getAJAX(目標url)”。
當Post方法(表單提交)時,首先配置form名字,例如,ajaxAnywhere.formName = "main"
在表單里調(diào)用“ajaxAnywhere.submitAJAX();”或者干脆設(shè)置一個能夠自動submit
的input按鈕例如<intput type="image"><input type="submit">就什么都不用寫,也能提交。
4,具體使用方法:
4.1 jsp頁面上:
定義刷新區(qū)域,使用<aa:zone name="xxxx">來定義一個區(qū)域。
可以在jsp頁面上“指定”刷新區(qū)域,他和“定義”刷新區(qū)域的區(qū)別在于,定義了不一定會被刷新,定義后
又被指定的刷新區(qū)域才能被刷新。通過覆蓋js中AjaxAnywere對象的ajaxAnywhere.getZonesToReload
方法來指定刷新區(qū)域。例如,
ajaxAnywhere.getZonesToReload = function () {
return "zone,1"
};
指定了兩塊刷新區(qū)域。
在刷新區(qū)域顯示新的內(nèi)容:
刷新區(qū)域里面,使用動態(tài)腳本(scriplet,jstl)從request(或其他范圍)獲得服務(wù)端返回的新的數(shù)據(jù),
并顯示。(推薦使用jstl比scriptlet更簡潔)。
4.2 服務(wù)端:
不論是Servlet還是Action還是直接使用jsp做服務(wù)端,代碼都是一樣的。
必須有的幾行代碼是:
if (AAUtils.isAjaxRequest(request)){
AAUtils.addZonesToRefresh(request, "xxxx");//這句話也可以不寫如果jsp頁面已經(jīng)指定了刷新區(qū)域
}
然后返回一個List放到request或者其他范圍內(nèi),供頁面顯示。
注意:
服務(wù)端代碼不必使用設(shè)置context-type為xml,沒有必要。因為通過ajaxanywhere filter可以做到這一點。
5,定制js
5.1 如何在response尚未返回期間不顯示默認的“loading...”(藍色圖層)?
通過在jsp頁面里覆蓋 ajaxAnywhere.showLoadingMessage = function() {}并設(shè)置為空。
5.2 如何修改默認的loading。。。圖片為其他圖片?
通過在jsp頁面里覆蓋 ajaxAnywhere.showLoadingMessage ,hideLoadingMessage,方法。
ajaxAnywhere.showLoadingMessage = function() {
var img = document.getElementById("myImg");
if (img == null) {
img = document.createElement("img");
document.body.appendChild(img);
img.id = "myImg";
img.src = "psyline.gif";
img.style.position = "absolute";
img.style.border = "1 solid black";
img.style.top = 0;
img.style.left = documet.body.offsetLeft;
}
img.style.display = "";
}
/**
* Default sample loading message hide function. Overrride it if you like.
*/
AjaxAnywhere.prototype.hideLoadingMessage = function() {
var img = document.getElementById("myImg");
if (img != null)
img.style.display = "none";
}
好,這樣就把把默認圖片替換成其他圖片了。
5.3 如何修改loading圖片的顯示為之為相對位置?
只需要配置top,left,例如:
ajaxAnywhere.showLoadingMessage = function() {
var div = document.getElementById("testshowdiv");
if (div == null) {
div = document.createElement("DIV");
document.body.appendChild(div);
div.id = "testshowdiv";
div.innerHTML = "<img src='shc.gif' border=0/>";
div.style.position = "absolute";
div.style.border = "1 solid black";
div.style.color = "white";
div.style.backgroundColor = "blue";
div.style.width = "100px";
div.style.heigth = "50px";
div.style.fontFamily = "Arial, Helvetica, sans-serif";
div.style.fontWeight = "bold";
div.style.fontSize = "11px";
}
//注意,如果alink沒有定義,那么就始終顯示進度條了。有時抱錯,有時不抱錯。
div.style.top = document.all.alink.offsetTop;
div.style.left =document.all.alink.offsetWidth-170; // 如果不減,在屏幕上就看不到了。
div.style.display = "";
}
/**
* Default sample loading message hide function. Overrride it if you like.
*/
AjaxAnywhere.prototype.hideLoadingMessage = function() {
var div = document.getElementById("testshowdiv");
if (div != null)
div.style.display = "none";
}
5.4 如果設(shè)置默認的彈出框。在上次請求被忽略后,默認會彈出一個框,如果讓不讓他出來?
只需要覆蓋或者直接在aa。js中修改
ajaxAnywhere.handlePrevousRequestAborted = function() {
// alert("放棄上一次的提交");//或者什么都不作
}
5.5 如何處理異常彈出框?
只需要覆蓋
ajaxAnywhere.handleException = function(type, details) {
alert("出異常了: \n\n\n ***************\n"+details.substring(0,350)+"\n...\n\n ***************");
}
5.6 如何處理錯誤彈出框?
只需要覆蓋
ajaxAnywhere.handleHttpErrorCode = function(code) {
alert("返回錯誤: \n \n \n ***************\n錯誤碼:" + code+"\n\n ***************");
}
5.7 如何定時刷新指定區(qū)域?
ajax定時刷新執(zhí)行得更象普通的js,
// 指定定期執(zhí)行的刷新所指向的url
function go() {
ajaxAnywhere.getAJAX('demo.jsp');
}
//指定刷新區(qū)域
ajaxAnywhere.getZonesToReload = function () {
return "zone,1"
};
//指定刷新之后的動作
ajaxAnywhere.onAfterResponseProcessing = function () {
window.setTimeout("go();", 1000);
//setInterval("go()",1000);
}
//隱藏loading圖片
ajaxAnywhere.showLoadingMessage = function(){};
//調(diào)用刷新后的動作
ajaxAnywhere.onAfterResponseProcessing();
這樣就構(gòu)成了一個循環(huán)。
與普通的js定時執(zhí)行某個操作并沒有什么不同,只不過通過在定時操作中使用ajax,可以調(diào)用非客戶端的程序,即后臺程序。而普通的定時執(zhí)行卻做不來。
6,一些與ajaxanywhere無關(guān)的技術(shù)。
6.1 struts動態(tài)form
ajaxanywhere不是必須指定formName,因為它默認使用forms[0]當作提交的form,這并不保險(一個頁面可能有多個form),所以有必要指定formName,struts的<html:form>標簽,必須struts-config配置了form時才行,沒有必要使用ActionForm時可以定義一個空的DynaActionForm,例如,
<form-bean name="localeform" type="org.apache.struts.action.DynaActionForm">
<form-property name="nnn" type="java.lang.String"/> //這句話也可以沒有。即沒有屬性的form
</form-bean>
這樣就不必多定義一個類了,動態(tài)form與ajaxanywhere配合得很好。
6.2 struts DispatchAction
ajax與strutsDispatchAction配合得也很好。
總結(jié):
比較ajax tags,struts ajaxtag,還是ajaxanywhere比較好些。
ajaxtags是基于組件的,能實現(xiàn)的功能有限。struts ajaxtags我用了之后感覺復(fù)雜。好了,暫時就寫這么多,以后的實踐經(jīng)驗就算在ajaxanywhere的補充了。
下載地址:http://ajaxanywhere.sourceforge.net/index.html