我們都知道普通的文件上傳是通過表單進(jìn)行文件上傳的,還不能達(dá)到異步上傳的目的。通過使用某些技術(shù)手段,比如jquery form.js可以達(dá)到異步上傳的目的,但最重要的問題在于,它不能夠進(jìn)行多個(gè)文件的上傳。如果你要上傳多個(gè)文件,必須一個(gè)一個(gè)地上傳,同時(shí)還要在界面上處理當(dāng)上傳完一個(gè)文件之后,下一個(gè)文件上傳框的問題。
現(xiàn)在我們有了一個(gè)更多的運(yùn)行,即使用swfupload進(jìn)行多文件異步上傳。顧名思義,它是一個(gè)flash的上傳工具,但在界面上的表現(xiàn)形式使它和普通的html元素一樣,沒有復(fù)雜的展現(xiàn),就一個(gè)普通的上傳框,即可達(dá)到想要目的。
關(guān)于swfupload的使用這里自不必多,這里主要介紹的是解決在java web開發(fā)過程中經(jīng)常碰到的驗(yàn)證失敗的問題。這是因?yàn)閒lash在上傳的時(shí)候使用的是和瀏覽器不同的會(huì)話,flash的SWFUpload上傳利用socket套接字進(jìn)行通信,所以導(dǎo)致session和原來上一次的會(huì)話不同,導(dǎo)致session丟失。這樣就導(dǎo)致服務(wù)器在驗(yàn)證時(shí)自然被認(rèn)為是新會(huì)話,從而驗(yàn)證不能通過,導(dǎo)致上傳不能成功了。
解決問題的方法,就是讓flash在上傳文件的時(shí)候帶上同在一個(gè)界面的session標(biāo)識(shí),這通常是修改其中的upload_url來達(dá)到我們的目的,修改如下所示:
upload_url: "/admin/infobuild/image/upload.action;jsessionid=${pageContext.session.id }"
上面這句話,必須放到j(luò)sp界面上,因?yàn)槔锩媸褂玫搅薐avaWeb的語法,當(dāng)然這可以修改,通過將<%=session.getId()%> 或 ${pageContext.session.id } 放到特殊的js變量中,可以達(dá)到隱藏變量的目的。比如如下的代碼:
<!-- 這句要房子jsp頁面中的script腳本中,或是放在servlet的response.getWriter()流中的script腳本中;總之要在swfupload 的js引入之前執(zhí)行 -->
window["sessionId"]="${pageContext.session.id}";
<!-- 這句話就可以在引入的js中使用 -->
upload_url: Gtip.util.addContextPath("/admin/infobuild/image/upload.action;jsessionId" + "=" + window["sessionId"]),
以上方案是解決在jsp頁面中解決的取值java的變量值;
如上代碼的第一句放到j(luò)sp文件中,如jsp的公共include文件中。下面一句就放到j(luò)s文件中,如引入的upload.js文件當(dāng)中。
但以上代碼還存在一個(gè)問題,就是默認(rèn)的sessionName問題。在tomcat或者其它j2ee容器,默認(rèn)的sessionName也是 jsessionId。如果我們修改了sessionName如通過tomcat的server.xml修改session_cookie_name,這樣默認(rèn)的sessionName就是我們修改之后的了。解決此問題,需要再加一個(gè)參數(shù)設(shè)置才可,如下所示:
<!-- 這三行放在include 導(dǎo)入的那個(gè)jsp的頁面中 -->
window["contextPath"] = "${pageContext.request.contextPath}";
window["sessionId"] = "${pageContext.session.id}";
window["sessionName"] = "jsessionId";
// js中使用jsp中設(shè)置的window的變量值
upload_url: addContextPath("/admin/infobuild/image/upload.action;" + window["sessionName"] + "=" + window["sessionId"])
以上代碼的前三行放到公共的include.jsp中,最后一行放到公共的upload.js中。這樣即可滿足最終要求了。
不過有一點(diǎn)不好的即是,在部署環(huán)境中時(shí),如果部署環(huán)境修改了sessionName,則必須在此include.jsp中修改一個(gè)具體的sessionName才可。
轉(zhuǎn)載請(qǐng)標(biāo)明出處:i flym
本文地址:http://www.iflym.com/index.php/code/201108190001.html
摘要: 開發(fā)環(huán)境: System:Windows WebBrowser:IE6+、Firefox3+ JavaEE Server:tomcat5.0.2.8、tomcat6 IDE:eclipse、MyEclipse 6.5 開發(fā)依賴庫: JavaEE5、ext 2.2.2 Email:hoojo_@126.com Blog:http://blog.csdn.net/IBM_hoojo ...
閱讀全文
摘要: 支持Form顏色選擇組件、日期時(shí)間選擇組件、帶圖標(biāo)的下拉列表、多選下來列表、動(dòng)態(tài)下拉列表樹等組件 開發(fā)環(huán)境: System:Windows WebBrowser:IE6+、Firefox3+ JavaEE Server:tomcat5.0.2.8、tomcat6 IDE:eclipse、MyEclipse 8 開發(fā)依賴庫: JavaEE5、ext 2.2.2 Email:hoojo_@126.co...
閱讀全文
摘要: 上兩篇文章:http://www.cnblogs.com/hoojo/archive/2011/06/01/2066426.html http://www.cnblogs.com/hoojo/archive/2011/06/02/2068665.html 介紹到了在MongoDB的控制臺(tái)完成MongoDB的數(shù)據(jù)操作、以及通過Java MongoDB 的驅(qū)動(dòng)完成在Java中對(duì)Mon...
閱讀全文
做手機(jī)Web開發(fā)做瀏覽器兼容用到了,所以在網(wǎng)上找了些匯總下。
alert($(window).height()); //瀏覽器當(dāng)前窗口可視區(qū)域高度
alert($(document).height()); //瀏覽器當(dāng)前窗口文檔的高度
alert($(document.body).height());//瀏覽器當(dāng)前窗口文檔body的高度
alert($(document.body).outerHeight(true));//瀏覽器當(dāng)前窗口文檔body的總高度 包括border padding margin
alert($(window).width()); //瀏覽器當(dāng)前窗口可視區(qū)域?qū)挾?
alert($(document).width());//瀏覽器當(dāng)前窗口文檔對(duì)象寬度
alert($(document.body).width());//瀏覽器當(dāng)前窗口文檔body的高度
alert($(document.body).outerWidth(true));//瀏覽器當(dāng)前窗口文檔body的總寬度 包括border padding margin
// 獲取頁面的高度、寬度
function getPageSize() {
var xScroll, yScroll;
if (window.innerHeight && window.scrollMaxY) {
xScroll = window.innerWidth + window.scrollMaxX;
yScroll = window.innerHeight + window.scrollMaxY;
} else {
if (document.body.scrollHeight > document.body.offsetHeight) { // all but Explorer Mac
xScroll = document.body.scrollWidth;
yScroll = document.body.scrollHeight;
} else { // Explorer Mac...would also work in Explorer 6 Strict, Mozilla and Safari
xScroll = document.body.offsetWidth;
yScroll = document.body.offsetHeight;
}
}
var windowWidth, windowHeight;
if (self.innerHeight) { // all except Explorer
if (document.documentElement.clientWidth) {
windowWidth = document.documentElement.clientWidth;
} else {
windowWidth = self.innerWidth;
}
windowHeight = self.innerHeight;
} else {
if (document.documentElement && document.documentElement.clientHeight) { // Explorer 6 Strict Mode
windowWidth = document.documentElement.clientWidth;
windowHeight = document.documentElement.clientHeight;
} else {
if (document.body) { // other Explorers
windowWidth = document.body.clientWidth;
windowHeight = document.body.clientHeight;
}
}
}
// for small pages with total height less then height of the viewport
if (yScroll < windowHeight) {
pageHeight = windowHeight;
} else {
pageHeight = yScroll;
}
// for small pages with total width less then width of the viewport
if (xScroll < windowWidth) {
pageWidth = xScroll;
} else {
pageWidth = windowWidth;
}
arrayPageSize = new Array(pageWidth, pageHeight, windowWidth, windowHeight);
return arrayPageSize;
}
// 滾動(dòng)條
document.body.scrollTop;
$(document).scrollTop();
posted @
2012-02-16 17:45 hoojo 閱讀(12521) |
評(píng)論 (0) |
編輯 收藏
有問題可以留言、私信、發(fā)郵件:
Email:hoojo_@126.com Blog:http://blog.csdn.net/IBM_hoojo
http://hoojo.cnblogs.com/
方法一:
1、安裝Rational Rose2003時(shí),在需選擇安裝項(xiàng)的時(shí)候,只選擇Rational Rose EnterPrise Edition即可,不需選擇其他項(xiàng),之后選擇“DeskTop Installation from CD Image“,一路下一步。出現(xiàn)Mem_pointer_Bad錯(cuò)誤,點(diǎn)擊確定繼續(xù);
2、安裝finish后將彈出的Rational License Key Administrator向?qū)У却翱陉P(guān)閉。若有連接FLEXlm License Server的出錯(cuò)提示框出現(xiàn),也關(guān)閉它們。
安裝會(huì)出現(xiàn) Mem_pointer_Bad 錯(cuò)誤,原因應(yīng)該是某個(gè)函數(shù)因?yàn)榘踩燃?jí)問題而無法運(yùn)行,只要下載一個(gè)SHW32.dll把 ../Rational/Rose/SHW32.dll替換即可。(注:此方法可以避免報(bào)錯(cuò),但是亦可能會(huì)造成Rose新建工程報(bào)Automation錯(cuò)誤,所以此方法基本無效。。。任他報(bào)錯(cuò)吧!囧)
下載地址: http://www.oyksoft.com/soft/1880.html
3、安裝好Rational Rose Enterprise Editon后,打開rose2003crack.rar壓縮包,里面有四個(gè)文件,分別為flexlm.cpl、license.dat、lmgrd.exe、rational.exe。
4、用記事本打開license.dat文件,大約在文件的中間位置有:
SERVER MICROSOFT ANY
DAEMON rational "C:\Program Files\Rational\common\rational.exe"
將其修改為:SERVER 計(jì)算機(jī)名 ANY DAEMON rational "自己安裝的目錄\rational.exe"后,保存。
5、將license.dat、 lmgrd.exe 、rational.exe三個(gè)文件一起拷貝到:安裝目錄\rational\common\ 下面。
如:若為默認(rèn)則為:C:\Program Files\Rational\common\目錄。
6、將flexlm.cpl拷貝到C:\Windows\system32目錄下。
7、進(jìn)入控制面板,則在控制面板的上方會(huì)增加了一個(gè)圖標(biāo),即FLEXlm License Manager,將其打開,在Setup頁中l(wèi)mgrd.exe右側(cè)目錄寫為:C:\Program Files\Rational\Common\lmgrd.exe(若為默認(rèn)安裝目錄)
License File右側(cè)目錄寫為:C:\Program Files\Rational\Common\license.dat 點(diǎn)擊“應(yīng)用”。
8、回到Control頁,點(diǎn)擊Start,若出現(xiàn)"Server Started",則表示已經(jīng)成功,可以點(diǎn)擊Status,若狀態(tài)為:計(jì)算機(jī)名:license server UP(MASTER)則成功。

9、這時(shí)可打開安裝的Rational Rose Enterprise Edition,若還是出現(xiàn)Error,則打開Rational License Key Administrator ,點(diǎn)擊工具欄中的第一個(gè)工具(Start WIzard),點(diǎn)擊下一步,在Server Name中的名字改為自己的計(jì)算機(jī)名,port可以不輸,能進(jìn)入下一個(gè)管理窗口并且沒出錯(cuò)提示,就代表license server配置成功,Rational的產(chǎn)品應(yīng)該可以運(yùn)行了。


——————————————————————————————————————————————————
更簡(jiǎn)單方法二:
安裝完成后,下載rational_perm.dat覆蓋到Common文件夾即可完成破解,簡(jiǎn)單吧 o(∩_∩)o...哈哈!
###########################################################################
另一版本:
FROM:http://blog.csdn.net/fenglibing/archive/2007/08/17/1747693.aspx
這么好的東西,不拿來出分享,我對(duì)不起原作者呀。但是我這里不知道作者是誰,感謝在先了。
http://www.oyksoft.com/soft/1880.html
http://files.cnblogs.com/lixianhuei/rose2003crack.rar
以上兩個(gè)網(wǎng)址分別是用來下載Rational Rose 2003及其破解軟件的。
1、安裝Rational Rose2003時(shí),在需選擇安裝項(xiàng)的時(shí)候,只選擇Rational Rose EnterPrise Edition即可,不需選擇其他項(xiàng)。
2、安裝好Rational Rose Enterprise Editon后,打開rose2003crack.rar壓縮包,里面有四個(gè)文件,分別為flexlm.cpl、license.dat、lmgrd.exe、rational.exe。
3、用記事本或者是EditPlus打開license.dat文件,大約在文件的中間位置有:SERVER Microsoft ANY
DAEMON rational “C:\Program Files\Rational\common\rational.exe” 將其修改為:SERVER 計(jì)算機(jī)名 ANY DAEMON rational “自己安裝的目錄\rational.exe”后,保存
注:若是按默認(rèn)目錄安裝,則只需修改計(jì)算機(jī)名即可。
4、將license.dat、 lmgrd.exe 、rational.exe三個(gè)文件一起拷貝到:安裝目錄\rational\common\ 下面。
如:若為默認(rèn)則為:C:\Program Files\Rational\common\目錄。
5、將flexlm.cpl拷貝到system32目錄下。如win2000系統(tǒng)中為C:\WINNT\system32目錄。
6、進(jìn)入控制面板,則在控制面板的上方會(huì)增加了一個(gè)圖標(biāo),即FLEXlm License Manager,將其打開,在Setup頁中l(wèi)mgrd.exe右側(cè)目錄寫為:C:\Program Files\Rational\Common\lmgrd.exe(若為默認(rèn)安裝目錄)
License File右側(cè)目錄寫為:C:\Program Files\Rational\Common\license.dat
7、回到Control頁,點(diǎn)擊Start,若出現(xiàn)”Server Started”,則表示已經(jīng)成功,可以點(diǎn)擊Status,若狀態(tài)為:計(jì)算機(jī)名:license server UP(MASTER)則成功。
8、這時(shí)可打開安裝的Rational Rose Enterprise Edition,若還是出現(xiàn)Error,則打開Rational License Key Administrator ,點(diǎn)擊工具欄中的第一個(gè)工具(Start WIzard),點(diǎn)擊下一步,在Server Name中的名字改為自己的計(jì)算機(jī)名即可。因現(xiàn)在的學(xué)習(xí)需在使用Rational Rose,所以進(jìn)行了安裝,但確實(shí)花了不少工夫,所以特把自己安裝的經(jīng)驗(yàn)來跟大家一起分享,希望能對(duì)大家有所幫助。
該文章為轉(zhuǎn)載文章,原文作者應(yīng)該是163.com的blog,但找不到作者blog,只能通過圖片url找到是163.com的
Email:hoojo_@126.com
Blog:http://blog.csdn.net/IBM_hoojo
http://hoojo.cnblogs.com/
posted @
2012-02-14 11:35 hoojo 閱讀(135796) |
評(píng)論 (24) |
編輯 收藏
摘要: 最近在搭建一個(gè)項(xiàng)目,需要用到很多通用的工具類,自己也寫了幾個(gè)。現(xiàn)在分享一下,也方便自己以后使用。如果你覺得不錯(cuò)的話,也歡迎轉(zhuǎn)載。blog http://blog.csdn.net/IBM_hoojohttp://hoojo.cnblogs.comhttp://hoojo.blogjava.netemail hoojo_@126.com 文件上傳狀態(tài)枚舉類: package com...
閱讀全文
摘要: 支持將Image的寬度、高度縮放到指定width、height,并保存在指定目錄通過目標(biāo)對(duì)象的大小和標(biāo)準(zhǔn)(指定)大小計(jì)算出圖片縮小的比例可以設(shè)置圖片縮放質(zhì)量,并且可以根據(jù)指定的寬高縮放圖片 源碼: package com.hoo.util; import java.awt.Image;import java.awt.image.BufferedImage;import java.io....
閱讀全文
Struts 概述
隨著MVC 模式的廣泛使用,催生了MVC 框架的產(chǎn)生。在所有的MVC 框架中,出現(xiàn)最早,應(yīng)用最廣的就是Struts 框架。
Struts 的起源
Struts 是Apache 軟件基金組織Jakarta 項(xiàng)目的一個(gè)子項(xiàng)目, Struts 的前身是CraigR. McClanahan 編寫的JSP Model2 架構(gòu)。
Struts 在英文中是"支架、支撐"的意思,這表明了Struts 在Web 應(yīng)用開發(fā)中的巨大作用,采用Struts 可以更好地遵循MVC 模式。此外, Struts 提供了一套完備的規(guī)范,以基礎(chǔ)類庫,可以充分利用JSP/Servlet 的優(yōu)點(diǎn),減輕程序員的工作量,具有很強(qiáng)的可擴(kuò)展性。
Struts優(yōu)點(diǎn)
提高開發(fā)效率,減輕了程序員的工作量,降低了重復(fù)代碼(降低代碼冗余),文件不再臃腫。
可以規(guī)范軟件開發(fā)的行為。ActionForm為我們封裝請(qǐng)求數(shù)據(jù)
增加代碼的擴(kuò)展性、移植性
提高代碼的可重用性、可讀性,無需多個(gè)Servlet多個(gè)方法
Action轉(zhuǎn)發(fā)頁面只須配置跳轉(zhuǎn)資源即可,無效全路徑、硬編碼。降低代碼的耦合性
Struts 架構(gòu)的工作原理
1. Model 部分
Struts 的Model 部分由ActionForm和JavaBean 組成。其中ActionForm用于封裝用戶請(qǐng)求參數(shù),所有的用戶請(qǐng)求參數(shù)由系統(tǒng)自動(dòng)封裝成ActionForm 對(duì)象:該對(duì)象被ActionServlet轉(zhuǎn)發(fā)給Action; 然后Action 根據(jù)ActionForm里的請(qǐng)求參數(shù)處理用戶請(qǐng)求。JavaBean 則封裝了底層的業(yè)務(wù)邏輯,包括數(shù)據(jù)庫訪問等。在更復(fù)雜的應(yīng)用中,JavaBean所代表的絕非一個(gè)簡(jiǎn)單的JavaBean,可能是EJB 組件或者其他的業(yè)務(wù)邏輯組件。該Model 對(duì)應(yīng)圖3 .4的Model 部分。
2. View 部分
Struts 的View 部分采用JSP 實(shí)現(xiàn)。Struts 提供了豐富的標(biāo)簽庫,通過這些標(biāo)簽庫可以最大限度地減少腳本的使用。這些自定義的標(biāo)簽庫可以實(shí)現(xiàn)與Model 的有效交互,并增加了顯示功能。對(duì)應(yīng)圖的JSP 部分。
整個(gè)應(yīng)用由客戶端請(qǐng)求驅(qū)動(dòng),當(dāng)客戶端請(qǐng)求被ActionServlet 攔截時(shí), ActionServlet根據(jù)請(qǐng)求決定是否需要調(diào)用Model 處理用戶請(qǐng)求,當(dāng)用戶請(qǐng)求處理完成后,其處理結(jié)果通過JSP 呈現(xiàn)給用戶。
3. Controller部分
Struts 的Controller 由兩個(gè)部分組成。
·系統(tǒng)核心控制器—攔截用戶請(qǐng)求ActionServlet 派發(fā)請(qǐng)求
·業(yè)務(wù)邏輯控制器—處理用戶請(qǐng)求的Action,處理業(yè)務(wù)邏輯
其中,系統(tǒng)核心控制器是一個(gè)ActionServlet。該控制器由Struts 框架提供,繼承HttpServlet類,因此可以配置成一個(gè)標(biāo)準(zhǔn)的Servlet。該控制器負(fù)責(zé)攔截所有Http請(qǐng)求,然后根據(jù)用戶請(qǐng)求決定是否需要調(diào)用業(yè)務(wù)邏輯控制器,如果需要調(diào)用業(yè)務(wù)邏輯控制器,則將請(qǐng)求轉(zhuǎn)發(fā)給Action 處理,否則直接轉(zhuǎn)向請(qǐng)求的JSP 頁面。業(yè)務(wù)邏輯控制器負(fù)責(zé)處理用戶請(qǐng)求,但業(yè)務(wù)邏輯控制器本身并不具有處理能力,而是調(diào)用Model 來完成處理。業(yè)務(wù)邏輯控制器對(duì)應(yīng)圖3 .4中的Action 部分。
下面結(jié)合圖3.7 對(duì)Struts 的工作流程作詳細(xì)的講解。
Web 應(yīng)用都是請(qǐng)求一響應(yīng)的程序結(jié)構(gòu)。程序是由客戶端Client 發(fā)出Http 請(qǐng)求開始的,客戶端請(qǐng)求被ActionServlet 攔截。在ActionServlet 處,有兩種情況:
·要求邏輯控制器處理的請(qǐng)求:
·簡(jiǎn)單轉(zhuǎn)發(fā)的請(qǐng)求。
對(duì)于第一種的請(qǐng)求,ActionServlet 需要調(diào)用對(duì)應(yīng)的Action。因此ActionServlet 將請(qǐng)求轉(zhuǎn)發(fā)到Action ,如果請(qǐng)求還配置了對(duì)應(yīng)的FormBean,則ActionServlet 還負(fù)責(zé)用請(qǐng)求參數(shù)填充ActionForm,此時(shí)如果ActionForm還沒有創(chuàng)建。ActionServlet會(huì)幫我們創(chuàng)建一個(gè)可以用的ActionForm,如果ActionForm已經(jīng)創(chuàng)建就直接給我們用, ActionForm 的實(shí)質(zhì)就是JavaBean,專門用于封裝請(qǐng)求參數(shù)。并且在次期間,如果ActionForm如果有驗(yàn)證方法,會(huì)去執(zhí)行驗(yàn)證方法,如果驗(yàn)證通過會(huì)進(jìn)入Action中。驗(yàn)證失敗,會(huì)跳轉(zhuǎn)到Action配置的input資源頁面。
此時(shí)的Action 將無須從HTTP Request 中獲取請(qǐng)求參數(shù),而是從ActionForm 中獲得請(qǐng)求參數(shù)。Action 獲得請(qǐng)求參數(shù)后,調(diào)用Model 對(duì)象由JavaBean 處理用戶請(qǐng)求。Action處理完用戶請(qǐng)求之后,將處理結(jié)果包裝成ActionForward,回送給ActionServlet。
由于ActionForward 對(duì)象封裝了JSP 資源的映射。因此, ActionServlet 知道調(diào)用合適的JSP 資源表現(xiàn)給客戶端。
對(duì)于第二種請(qǐng)求, HTTP 請(qǐng)求無須Action 處理,只是對(duì)普通資源的請(qǐng)求,作為超級(jí)鏈接的替代。因?yàn)锳ctionServlet 直接將該請(qǐng)求轉(zhuǎn)發(fā)給JSP 資源,既不會(huì)填充ActionForm,也無須調(diào)用Action 處理。
JSP 頁面在表現(xiàn)之前,還需要調(diào)用對(duì)應(yīng)的JavaBean,此處的JavaBean 不再是包含業(yè)務(wù)邏輯的JavaBean,而是封裝了處理結(jié)果的普通vo (值對(duì)象)。JSP 頁面根據(jù)vo 的值,可能利用JSTL 或者Struts 的標(biāo)簽庫來生成HTTP 響應(yīng)給客戶端。總之JSP 應(yīng)盡量避免使用Java 腳本。
Action配置
path是我們請(qǐng)求訪問的路徑,如果用struts標(biāo)簽,會(huì)默認(rèn)加上.do的后綴。ActionServlet攔截到*.do的請(qǐng)求后,就進(jìn)行相應(yīng)的業(yè)務(wù)處理,然后派發(fā)到path對(duì)應(yīng)的Action;
name是Action對(duì)象的ActionForm,ActionForm是封裝請(qǐng)求的信息,如表單
attribute和name一樣,可以省略,在省略的情況下用name。都是對(duì)應(yīng)ActionForm
type是Action對(duì)象對(duì)應(yīng)的文件路徑,含包名
scope是ActionForm的作用域,默認(rèn)request
parameter后帶方法名稱,即請(qǐng)求所執(zhí)行的方法
forward是轉(zhuǎn)發(fā)后的資源頁面
ActionForward配置
name邏輯名稱和Action中的mapping.forward參數(shù)對(duì)應(yīng)
path對(duì)應(yīng)映射的JSP頁面
redirect是否重定向請(qǐng)求
forward有全局和局部的2種,如果當(dāng)前Action配置的forward資源在當(dāng)前配置的Action中沒有找到,然后回到全局的forward資源中查找。局部?jī)?yōu)先全局
ActonForm配置
name是form的名稱
type是form的包名+文件名
ActionForm還有動(dòng)態(tài)ActionForm、驗(yàn)證ActionForm
國(guó)際化I18N(Internationalization)
目的:是適應(yīng)更多的、更好的用戶界面
Java 程序的國(guó)際化主要通過如下三個(gè)類完成。
java.util. ResourceBundle: 對(duì)應(yīng)用于加載一個(gè)資源包。
java.util.Locale: 對(duì)應(yīng)一個(gè)特定的國(guó)家/區(qū)域及語言環(huán)境。
java.text.MessageFormat: 用于將消息格式化。
為了實(shí)現(xiàn)程序的國(guó)際化,必須先提供程序所需要的資源文件。資源文件的內(nèi)容是和很多key-value 對(duì)。其中key 是程序使用的部分,而value 則是程序界面的顯示。
資源文件的命名可以有如下三種形式。
baseName _language_country.properties。
baseName _language.properties。
baseNarne.properties 。
其中baseName 是資源文件的基本名,用戶可以自由定義。而language 和count可都不可隨意變化,必須是Java 所支持的語言和國(guó)家。
1.國(guó)際化支持的語言和國(guó)家
事實(shí)上, Java 也不可能支持所有國(guó)家和語言,如需要獲取Java 所支持的語言和國(guó)家,可調(diào)用Locale 類的getAvailableLocale 方法來獲取。該方法返回一個(gè)Locale 數(shù)組,該數(shù)組里包含了Java 所支持的語言和國(guó)家。
2. 編寫國(guó)際化所需的資源
國(guó)際化所需的資源文件內(nèi)容是key-value 對(duì),下面提供了兩個(gè)資源文件,這兩個(gè)資源文件很簡(jiǎn)單,只包含一個(gè)key-value 對(duì)。
下面是MyResource.properties 的文件的內(nèi)容:
資源文件的內(nèi)容: key-value 對(duì)。
msg=Hello , {O} Today is {1}.
下面是MyResource_zh_CN.properties 文件的內(nèi)容:
資源文件的內(nèi)容: key-value 對(duì)
msg=你好. {O} 今天是{l}。
所有資源文件的key 都是相同的,只是value 會(huì)隨國(guó)家和語言的不同而變化。
3.程序從哪里獲取資源呢?
在ResourceBundle 加載資源時(shí)按如下順序搜索。
搜索所有國(guó)家和語言都匹配的資源文件,例如,對(duì)于簡(jiǎn)體中文的環(huán)境,先搜索如下文件:
MyResource_zh_CN.properties
如果沒有找到國(guó)家和語言都匹配的資源文件,則再搜索語言匹配的文件,即搜索如下文件:
MyResource_zh.properties
如果上面的文件依然無法搜索到,則搜索baseNarne 匹配的文件,即搜索如下文件:
MyResource.properties
4. 使用類文件代替資源文件
Java 也允許使用類文件代替資源文件,即將所有的key-value對(duì)存入class 文件,而不是屬性文件。
用來代替資源文件的Java 文件必須滿足如下條件。
·類的名字必須為baseNarne_language_country,這與屬性文件的命名相似。
·該類必須繼承ListResourceBundle,并重寫getContents 方法,該方法返回Object數(shù)組,該數(shù)組的每一個(gè)項(xiàng)都是key=value 對(duì)。
eg:下面的類文件可以代替上面的屬性文件:
public class MyResource_zh_CN extends ListResourceBundle {
// 定義資源
private final Object myData[][] = { "msg" , " {0}您好!今天是{l} "};
//重寫方法getContents()
public Object[] [] getContents() {
//該方法返回資源的key-value對(duì)
return myData;
}
}
如果系統(tǒng)同時(shí)存在資源文件及類文件,則系統(tǒng)將以類文件為主,而不會(huì)調(diào)用資源文件。對(duì)于簡(jiǎn)體中文的Locale, ResourceBundle 搜索資源的順序是:
(1) baseName zh CN.class 。
(2) baseNarne_zh_CN.properties。
(3) baseNarne zh.class 。
(4) baseNarne_zh.properties。
(5) baseNarne.class。
(6) baseNarne.properties。
當(dāng)系統(tǒng)按上面的順序搜索資源文件時(shí),如果前面的文件不存在,則會(huì)使用下一個(gè):如果一直找不到對(duì)應(yīng)的文件,系統(tǒng)將拋出異常。
struts加載資源文件
資源文件的加載通過struts-config.xml文件來配置,加載資源文件應(yīng)從Web 應(yīng)用的WEB-INF/classes路徑開始加載。因此,資源文件必須放在WEB-INF/classes路徑或該路徑的子路徑下。如果直接放在WEB-INF/classes 路徑下,在配置資源文件時(shí),直接指定資源文件的baseName 即可。但如果放在子路徑下,則必須以包的形式配置。
動(dòng)態(tài)ActionForm
Why?當(dāng)一個(gè)form表單的屬性、字段非常多的情況下,需要我們不斷的修改、添加ActionForm中的屬性,并提供getter、setter方法。雖然這個(gè)類比較簡(jiǎn)單,但是大量重復(fù)的getter、setter方法也是比較繁瑣的。這個(gè)時(shí)候struts的動(dòng)態(tài)ActionForm就派上用場(chǎng)了。使用動(dòng)態(tài)ActionForm 的目的是為了減少代碼的書寫量,但是相對(duì)在配置方面要復(fù)雜些。
配置動(dòng)態(tài)ActionForm
所有的動(dòng)態(tài)ActionForm 的實(shí)現(xiàn)類都必須是org.apache.struts.action.DynaActionForm類,或者是它的子類。使用動(dòng)態(tài)ActionForm 與前面不同的是:因?yàn)橄到y(tǒng)不清楚動(dòng)態(tài)ActionForm 的屬性,所以必須在配置文件中配置對(duì)應(yīng)的屬性。可以使用form-property 元素來配置動(dòng)態(tài)ActionForm 的屬性。
<!一配置動(dòng)態(tài)ActionForm,動(dòng)態(tài)Aciton 必須使用烏rnaActionForm 一〉
<form-bean name="loginForm" type="org.apache.struts.action.DynaActionForm">
<!一配置ActionForm的屬性: username-->
<form-property name="username" type="java.lang.String"/>
<! 配置ActionForm的屬性: pass-->
<form-property name="pass"type="java.lang.String"/>
</form-bean>
<!-- 配置Action中的path , type , name 屬性>
<action path="/login" type="com.hoo.LoginAction" name="loginForm">
<!一配置兩個(gè)局部Forward-->
<forward name="welcome" path="/WEB-INF/jsp/welcome.jsp"/>
<forward name="input" path="/login.jsp"/>
</action>
從上面的配置文件可看出,動(dòng)態(tài)ActionForm 的配置必須增加form-property 元素,每個(gè)屬性必須對(duì)應(yīng)一個(gè)form-property元素。
form-property元素包含兩個(gè)屬性。
name: 屬性的名字,必須與JSP 頁面的表單域的名字相同。
type: 屬性的類型。
使用動(dòng)態(tài)ActionForm
//必須重寫該核心方法,該方法actionForm 將表單的請(qǐng)求參數(shù)封裝成值對(duì)象
public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
//將ActionForm強(qiáng)制類型轉(zhuǎn)換為DynaActionForm
DynaActionForm loginForm = (DynaActionForm)form;
//從ActionForm中解析出請(qǐng)求參數(shù): username
String username = (String)loginForm.get("username");
//從ActionForm中解析出請(qǐng)求參數(shù): password
String pass = (String)loginForm.get("pass");
//后面的處理與前一個(gè)示例的Action 相同。
…………
}
使用動(dòng)態(tài)ActionForm 時(shí),請(qǐng)求參數(shù)必須使用DynaActionForm的getter 方法獲取。
DynaActionForm 的getter 方法主要有如下三個(gè)。
Object get(java.lang.String name): 根據(jù)屬性名返回對(duì)應(yīng)的值。
Object get(java.lang.String name, int index): 對(duì)于有多個(gè)重名表單域的情況, Struts將其當(dāng)成數(shù)組處理,此處根據(jù)表面域名和索引獲取對(duì)應(yīng)值。
Object get(java.lang.String name, java.lang.String key): 對(duì)于使用Map 屬性的情況,根據(jù)屬性名及對(duì)應(yīng)key. 獲取對(duì)應(yīng)的值。
Struts 的標(biāo)簽庫
Struts 提供了大量的標(biāo)簽庫,用于完成表現(xiàn)層的輸出。借助于Struts 的標(biāo)簽庫,可避免在JSP 中嵌入大量的Java 腳本,從而提高代碼的可讀性。
Struts 主要提供了如下三個(gè)標(biāo)簽庫。
A、 html: 用于生成HTML 的基本標(biāo)簽。
B、 bean: 用于完成程序國(guó)際化,輸出Struts 的ActionForm 的屬性值等。
C、 logic: 用于完成循環(huán)、選擇等流程控制。
使用html 標(biāo)簽庫
Struts 為htrnl 的大部分標(biāo)簽提供了對(duì)應(yīng)的htrnl 標(biāo)簽, htrnl 所支持的標(biāo)簽大致有如下。
* base: 表現(xiàn)成一個(gè)HTML 的<base>標(biāo)簽。
* button: 表現(xiàn)成一個(gè)按鈕,該按鈕默認(rèn)沒有任何動(dòng)作。
* cancel: 表現(xiàn)成一個(gè)取消按鈕。
* checkbox: 表現(xiàn)成一個(gè)Checkbox 的輸入框。
* error: 用于輸出數(shù)據(jù)校驗(yàn)的出錯(cuò)提示。
* file: 表現(xiàn)成一個(gè)文件瀏覽輸入框。
* form: 表現(xiàn)成一個(gè)form 域。
* frame: 表現(xiàn)成一個(gè)HTML<frame>標(biāo)簽。
* hidde: 表現(xiàn)成一個(gè)隱藏域。
* htrnl: 表現(xiàn)成HTML 的<htrnl>標(biāo)簽。
* image: 表現(xiàn)成表單域的image 域。
* img: 表現(xiàn)成一個(gè)HTML 的img 標(biāo)簽。
* javascrit: 表現(xiàn)成JavaScript 的校驗(yàn)代碼,這些校驗(yàn)代碼根據(jù)ValidatorPlugIn 生成。
* link: 表現(xiàn)成HTML 的超級(jí)鏈接。
* messages: 用于輸出Struts 的各種提示信息,包括校驗(yàn)提示。
* multibox: 表現(xiàn)成一個(gè)Checkbox 輸入框。
* option: 表現(xiàn)成選擇框的一個(gè)選項(xiàng)。
* password: 表現(xiàn)成一個(gè)密碼輸入框。
* radio: 表現(xiàn)成一個(gè)單選輸入框。
* reset: 表現(xiàn)成一個(gè)重設(shè)按鈕。
* rewrite: 表現(xiàn)成一個(gè)URL 。
* select: 表現(xiàn)成一個(gè)列表選擇框。
* submit: 表現(xiàn)成一個(gè)提交按鈕。
* text: 表現(xiàn)成一個(gè)單行文本輸入框。
* textarea: 表現(xiàn)成一個(gè)多行文本框。
使用bean 標(biāo)簽庫
bean 標(biāo)簽庫主要用于輸出屬性值、提示消息及定義請(qǐng)求參數(shù)等。下面是bean 標(biāo)簽庫的常用標(biāo)簽。
* cookie: 將請(qǐng)求的cookie 的值定義成腳本可以訪問的JavaBean 實(shí)例。
* define: 將某個(gè)bean 的屬性值定義成腳本可以訪問的變量。
* header: 將請(qǐng)求頭的值定義成腳本可以訪問的變量。
* include: 將某個(gè)JSP 資源完整定義成一個(gè)bean 實(shí)例。
* message: 用于輸出國(guó)際化信息。
* page: 將page Context 中的特定項(xiàng)定義成一個(gè)bean 。
* parameter: 將請(qǐng)求參數(shù)定義成腳本可以訪問的變量。
* resource: 加載Web 應(yīng)用的資源,并將其變成JavaB eano
* struts: 用于將某個(gè)Struts 的內(nèi)部配置成一個(gè)bean 。
* write: 用于輸出某個(gè)bean 的屬性值。
使用logic 標(biāo)簽庫
logic 標(biāo)簽庫是使用最頻繁,相對(duì)復(fù)雜的標(biāo)簽庫。logic 標(biāo)簽庫主要用于完成基本的流程控制,比如循環(huán)及選擇等。
logic 標(biāo)簽庫主要有如下標(biāo)簽。
* empty: 如果給定的變量為空或者為空字符串,則就計(jì)算并輸出標(biāo)簽體的內(nèi)容。
* equal: 如果給定變量與特定的值相等,則會(huì)計(jì)算并輸出該標(biāo)簽體的內(nèi)容。
* forward: 將某個(gè)頁面的控制權(quán)forward 確定的ActionForward 項(xiàng)。
* greaterEqual: 如果給定變量大于或等于特定的值,則會(huì)計(jì)算并輸出標(biāo)簽體的內(nèi)容。
* greaterThan: 如果給定變量大于特定的值,則會(huì)計(jì)算井輸出標(biāo)簽體的內(nèi)容。
* iterate: 通過遍歷給定集合的元素,對(duì)標(biāo)簽體的內(nèi)容進(jìn)行循環(huán)。
* lessEqual: 如果給定變量小于或等于特定的值,則會(huì)計(jì)算并輸出標(biāo)簽體的內(nèi)容。
* lessThan: 如果給定變量小于特定的值,則會(huì)計(jì)算并輸出標(biāo)簽體的內(nèi)容。
* match: 如果特定字符串是給定消息合適的子字符串,則會(huì)計(jì)算并輸出標(biāo)簽體的內(nèi)容。
* messagesNotPresent: 如果請(qǐng)求中不包含特定的消息內(nèi)容,將計(jì)算并輸出標(biāo)簽體的內(nèi)容。
* messagesPresent: 如果請(qǐng)求中包含特定的消息內(nèi)容,則計(jì)算并輸出標(biāo)簽體的內(nèi)容。
* notEmpty: 如果給定的變量既不為空,也不是空字符串,則計(jì)算并輸出標(biāo)簽體的內(nèi)容。
* notEqual: 如果給定變量不等于特定的值,則會(huì)計(jì)算并輸出標(biāo)簽體的內(nèi)容。
* notMatch: 如果特定宇符串不是給定消息合適的子字符串,則會(huì)計(jì)算并輸出標(biāo)簽體的內(nèi)容。
* notPresent: 如果特定的值沒有出現(xiàn)在請(qǐng)求中,則計(jì)算并輸出標(biāo)簽體的內(nèi)容。
* present: 如果特定的值出現(xiàn)在請(qǐng)求中,則計(jì)算并輸出標(biāo)簽體的內(nèi)容。
* redirect: 重定向頁面。
Struts 的數(shù)據(jù)校驗(yàn)
數(shù)據(jù)校驗(yàn)也稱為輸入校驗(yàn),指導(dǎo)對(duì)用戶的輸入進(jìn)行基本過濾,包括必填宇段,宇段必須為數(shù)字及兩次輸入的密碼必須相匹配等。這些是每個(gè)MVC 框架都應(yīng)該完成的任務(wù),Struts 提供了基本的數(shù)據(jù)校驗(yàn),如果結(jié)合commons-validator, Struts 則擁有強(qiáng)大的校驗(yàn)框架,包括進(jìn)行客戶端的JavaScript 校驗(yàn)等。
Struts 的數(shù)據(jù)校驗(yàn)大致有如下幾種方式:
ActionForm 的代碼校驗(yàn)。
Action 里的代碼校驗(yàn)。
結(jié)合commons-validator.jar 的校驗(yàn)。
ActionForm 的代碼校驗(yàn)
ActionForm 的代碼校驗(yàn)是最基本的校驗(yàn)方式。這種校驗(yàn)方式是重寫ActionForm 的validate 方法,在該方法內(nèi)對(duì)所有的宇段進(jìn)行基本校驗(yàn)。如果出現(xiàn)不符合要求的輸出,則將出錯(cuò)提示封裝在ActionError 對(duì)象里,最后將多個(gè)ActionError 組合成ActionErrors 對(duì)象,該對(duì)象里封裝了全部的出錯(cuò)提示。并將錯(cuò)誤信息用<html:error/>展現(xiàn)在配置的input的失敗頁面上。
Action 的代碼校驗(yàn)
在Action 里通過代碼完成輸入校驗(yàn),是最基本,也最容易使用的方法。與最初的MVC 設(shè)計(jì)相似,在調(diào)用業(yè)務(wù)邏輯組件之前,先對(duì)數(shù)據(jù)進(jìn)行基本校驗(yàn)。這是最傳統(tǒng)也是最原始的方法。
這種校驗(yàn)方式非常容易理解,所有的代碼都需要程序員自己控制,相當(dāng)靈活。
但有如下幾個(gè)不方便之處。
·用戶需要書寫大量的校驗(yàn)代碼,使程序變得煩瑣。
· 數(shù)據(jù)校驗(yàn)應(yīng)該在填充ActionForm里完成,最好能在客戶端完成校驗(yàn),而不是推遲到Action 里才完成數(shù)據(jù)校驗(yàn)。
注意:在實(shí)際的使用中,這種校驗(yàn)方式不僅程序開發(fā)復(fù)雜,且性能也不高。
結(jié)合commons-validator.jar 的校驗(yàn)
借助于commons-validator.jar 的支持, Struts的校驗(yàn)功能非常強(qiáng)大,幾乎不需書寫任何代碼。不僅可以完成服務(wù)器端校驗(yàn),同時(shí)還可完成客戶端校驗(yàn),即彈出Javascript 提示。
使用commons-validator.jar 校驗(yàn)框架時(shí),有如下幾個(gè)通用配置。
·增加校驗(yàn)資源。
·利用ValidatorPlugIn 加載校驗(yàn)資源。
·ActionForm 使用ValidatorForm 的于類。
下面分別通過三個(gè)示例講解這三種校驗(yàn):基本的校驗(yàn)、對(duì)動(dòng)態(tài)ActionForm 執(zhí)行校驗(yàn)及彈出JavaScript 校驗(yàn)提示。
1. 繼承ValidatorForm 的校驗(yàn)
如果需要使用commons-validator 框架,請(qǐng)按如下步驟進(jìn)行。
(1) Struts 的ActionForm必須是ValidatorForm的子類,提供驗(yàn)證屬性字段的getter、setter方法
(2) 編寫表單域時(shí)必須滿足校驗(yàn)規(guī)則。校驗(yàn)規(guī)則都由規(guī)則文件控制,規(guī)則文件有以下兩個(gè)。
* validator-rules.xml 文件
* validation.xml 文件
第一個(gè)文件可在Struts 的解壓縮后的文件夾的lib 下找到,將該文件復(fù)制到WEB-INF
2. common-validator支持的校驗(yàn)規(guī)則
common-validator支持的校驗(yàn)規(guī)則非常豐富,特別是mask 和validwhen 兩個(gè)規(guī)則,
極大地豐富了該校驗(yàn)框架的功能。
常用的校驗(yàn)規(guī)則有如下幾種。
* required: 必填。
* va1idwhen: 必須滿足某個(gè)有效條件。
* minlength: 輸入必須大于最小長(zhǎng)度。
* maxlength: 輸入必須小于最大長(zhǎng)度。
* mask: 輸入匹配正確的表達(dá)式。
* byte: 輸入只能是一個(gè)byte 類型變量。
* short: 輸入只能是一個(gè)short 類型變量。
* integer: 輸入只能是一個(gè)integer 變量。
* long: 輸入只能是一個(gè)long 變量。
* float: 輸入只能是一個(gè)float 變量。
* double: 輸入只能是一個(gè)double 變量。
* date: 輸入必須是一個(gè)日期。
* intRange: 輸入的數(shù)字必須在整數(shù)范圍內(nèi)。
* floatRange: 輸入的數(shù)字必須在單精度浮點(diǎn)數(shù)范圍內(nèi)。
* doubleRange: 輸入的數(shù)字必須在雙精度浮點(diǎn)數(shù)范圍內(nèi)。
* email: 輸入必須是有效的E-mail 地址。
* uri: 輸入必須是有效的uri 地址。
3.使用DynaValidatorForm 的校驗(yàn)
即使不書寫ActionForm,也可以利用cornmon-validator 校驗(yàn)框架。此時(shí)使用的ActionForm 的實(shí)現(xiàn)類,必須既是動(dòng)態(tài)Form ,也是驗(yàn)證Form,DynaValidatorForm 就是滿足這兩個(gè)條件的Form。
4. 彈出客戶端JavaScript提示
如需要彈出客戶端JavaScript 校驗(yàn)非常簡(jiǎn)單,無須修改其他配置文件,只需修改登錄使用的JSP 頁面的兩個(gè)地方。
(1) 為form 元素增加onsubmit="return validateXxxForm(this);"屬性,其中的XxxForm就是需要校驗(yàn)的form 名,與struts-config.xrnl中配置的form-bean 的name 屬性一致,也與validation.xrnl文件中需要校驗(yàn)的form 的name 屬性一致。
(2) 增加<html:javascript formName="xxxForm"/> ,其中xxxForm 是需要校驗(yàn)的form 名。
注意:即使使用了客戶端技驗(yàn)規(guī)則,也不要?jiǎng)h除頁面的htm1 :rnessages 標(biāo)簽。因?yàn)樵摌?biāo)簽會(huì)在客戶端技驗(yàn)通過,而在服務(wù)器端技驗(yàn)并未通過時(shí)彈出提示。
Struts 的異常框架
Struts 1.1 版本中加入了對(duì)異常的處理,稱之為Exception Handling,標(biāo)志著作為一個(gè)整體的框架, Struts 越來越趨于成熟。
在以前的Struts 開發(fā)過程中,對(duì)于異常的處理,主要是采用手動(dòng)處理的方式:如通過try/catch 等捕獲異常:然后將定制個(gè)性化的,比較詳細(xì)的錯(cuò)誤信息放進(jìn)ActionMessage中:最后在返回頁面中把這些錯(cuò)誤信息反饋給用戶。
對(duì)于異常的原始信息,不管是最終用戶還是開發(fā)員都不希望看到。
借助于Struts 的異常框架,異常處理只需通過struts-config.xm1文件定義即可。根據(jù)異常定義的位置不同,異常可分為局部異常和全局異常兩種。
·局部異常作為action 的子元素中定義。
·全局異常在globa1-excetpions 元素中定義。
異常定義的格式如下:
<exception key="keyNarne" type="ExceptionNarne" scope="scope" path="uri"/>: 當(dāng)Struts 出現(xiàn)ExceptionNarne 的異常時(shí),頁面自動(dòng)轉(zhuǎn)向uri 指向的資源,并在該頁面輸出keyName 對(duì)應(yīng)的國(guó)際化中的出錯(cuò)提示。
幾種常用的Action
除了基本的Action 之外, Struts 還提供了幾個(gè)其他類型的Action ,這些Action 大大豐富了Struts 的功能。下面介紹如下兒個(gè)常用的Action 。
* DispatchAction: 能同時(shí)完成多個(gè)Action 功能的Action 。
* ForwardActon: 該類用來整合Struts 和其他業(yè)務(wù)邏輯組件,通常只對(duì)請(qǐng)求作有效性檢查。
* IncludeAction: 用于引入其他的資源和頁面。
* LookupDispatchAction: DispatchAction 的子類,根據(jù)按鈕的key ,控制轉(zhuǎn)發(fā)給action的方法。
* MappingDispatchAction: DispatchAction 的子類,一個(gè)action 可映射出多個(gè)Action地址。
* SwitchAction: 用于從一個(gè)模塊轉(zhuǎn)換至另一個(gè)模塊,如果應(yīng)用分成多個(gè)模塊時(shí),就可以使用SwitchAction 完成模塊之間的切換。
DispatchAction
在該action 的配置中,增加了parameter屬性,該屬性用于指定參數(shù)名,即Struts 將根據(jù)該參數(shù)的值調(diào)用對(duì)應(yīng)的方法。為了讓請(qǐng)求增加method 的參數(shù),method參數(shù)對(duì)應(yīng)的是要請(qǐng)求執(zhí)行的方法。
<action path="/login" type="com.hoo.LoginAction" name="loginForm" scope="request" validate="true" input="login.jsp" parameter="method">
<forward name="success" path="/welcome.jsp"/>
</action>
Login.do?method=login
MappingDispatchAction
可將同一個(gè)Action 的不同方法映射成多個(gè)Action URI ,這種Action 的寫法與DispatchAction 非常相似,同樣不需要重寫execute 方法,而是將書寫多個(gè)自定義的方法。這些方法除了方法名與execute 方法不同外,其他的參數(shù)列表及異常處理完全一樣。
<!-- 配置第一個(gè)Action. 實(shí)現(xiàn)類是com.hoo.LoginAction , parameter 為add-->
<action path="/add" type="com.hoo.LoginAction" name="loginForm" scope="request" validate="true" input="login.jsp" parameter="add">
<forward name="success" path="/welcome.jsp"/>
</action>
<! 配置第二個(gè)Action. 實(shí)現(xiàn)類是com.hoo.LoginAction , parameter 為modify-->
<action path="/modify" type="com.hoo.LoginAction" name="loginForm" scope="request" validate="true" input="login.jsp" parameter="modify">
<forward name="success" path="/welcome.jsp"/>
</action>
其中,path對(duì)應(yīng)的是請(qǐng)求的地址uri,而parameter是對(duì)于當(dāng)前請(qǐng)求所執(zhí)行的方法;
注意:使用MappingDispatchAction 并沒有帶來太大的優(yōu)勢(shì),系統(tǒng)完全可以書寫兩個(gè)Action,分別定義兩個(gè)不同的action 映射,而其他部分沒有區(qū)別。
LookupDispatchAction
LookupDispatchAction也是DispatchAction 的一種,但它的處理更加簡(jiǎn)單。該Action也可包含多個(gè)處理方法,它可讓處理方法與按鈕直接關(guān)聯(lián),無須使用任何的JavaScript腳本。因此可通過重寫getKeyMethodMap方法完成按鈕與Action 中方法的關(guān)聯(lián)。
//用于關(guān)聯(lián)按鈕和方法
protected Map getKeyMethodMap() {
Map map = new HashMap();
//如果按鈕標(biāo)題的key 為button.add. 則提交該按鈕時(shí)對(duì)應(yīng)add 方法
map .put ("button. add" , "add");
//如果按鈕標(biāo)題的key 為button.modify. 則提交該按鈕時(shí)對(duì)應(yīng)modify 方法
map.put ("button.modify" , "modify") ;
return map;
}
ForwardAction
如果需要從一個(gè)頁面或資源轉(zhuǎn)換到另一個(gè)資源時(shí),直接使用頁面或資源路徑的超級(jí)鏈接定位并不是好的做法,這使得控制器沒有機(jī)會(huì)處理相關(guān)的請(qǐng)求事直。
使用ForwardAction可以完成請(qǐng)求的轉(zhuǎn)發(fā),當(dāng)控制器調(diào)用ForwardAction的perform()方法時(shí),它會(huì)使用屬性parameter 所設(shè)定的路徑進(jìn)行forward 的動(dòng)作。下面是一個(gè)設(shè)定ForwardAction的例子:
<actlon-mapplngs>
<action path="/welcome" type="org.apache.struts.actions.ForwardAction" parameter="/welcome.jsp"/>
</action-mappings>
該action 僅僅完成轉(zhuǎn)發(fā),并沒有執(zhí)行其他的額外動(dòng)作。頁面控制轉(zhuǎn)發(fā)的代碼如下:
<a href="welcome.do">轉(zhuǎn)入</a>
當(dāng)單擊轉(zhuǎn)入超級(jí)鏈接時(shí),將可以轉(zhuǎn)向ForwardAction中parameter指向的資源。
IncludeAction
IncludeAction的用法與ForwardAction的用法比較相似,區(qū)別在于ForwardAction將跳轉(zhuǎn)到action 定義的資源,而IncludeAction用于引入該action 對(duì)應(yīng)的資源。
下面是IncludeAction定義的源代碼:
<action-mapplngs>
<action path="/welcome" type="org.apache. struts.actions.IncludeAction" parameter="/welcome.jsp"/>
</action-mappings>
該action 用于經(jīng)welcome.jsp 作為資源導(dǎo)入。
頁面中負(fù)責(zé)加載該action 所導(dǎo)入資源的代碼如下:
<jsp:include page="welcome.do"/><br>
上面的代碼將會(huì)把welcome action 定義的資源導(dǎo)入該頁面。
SwitchAction
SwitchAction 主要用于模塊之間的切換。當(dāng)一個(gè)應(yīng)用之中存在多個(gè)模塊時(shí),使用SwitchAction在不同模塊之間的action 之間切換還是相當(dāng)方便的。
Struts 的常見擴(kuò)展方法
Struts 的強(qiáng)大吸引力還來自于它的可擴(kuò)展性,其擴(kuò)展性通常有如下三種方式。
·實(shí)現(xiàn)PlugIn: 如果需要在應(yīng)用啟動(dòng)或關(guān)閉時(shí)完成某些操作,可以創(chuàng)建自己的PlugIn類。
·繼承RequestProcessor: 如果想在請(qǐng)求被處理中的某個(gè)時(shí)刻做一些業(yè)務(wù)邏輯時(shí),可以考慮實(shí)現(xiàn)自己的RequestProcessor 類。
·繼承ActionServlet: 如果需要在每次開始處理請(qǐng)求之前,或者處理請(qǐng)求結(jié)束之后完成某些操作,可以實(shí)現(xiàn)自己的ActionServlet 來完成擴(kuò)展。
下面分別從三個(gè)方面來介紹Struts 的擴(kuò)展。
實(shí)現(xiàn)PlugIn 接口
Struts 已經(jīng)演示了PlugIn 的擴(kuò)展方法:與common- validation 的整合。后面還將介紹Spring 與Struts 的整合,也利用了PlugIn 的擴(kuò)展。
在下面的應(yīng)用中,系統(tǒng)使用Hibernate 作為持久層,在啟動(dòng)時(shí)創(chuàng)建SessionFactory 實(shí)例,并將該SessionFactory 存入application ,在應(yīng)用關(guān)閉時(shí)銷毀SessionFactory 。只需如下兩步即可完成此功能。
(1) 實(shí)現(xiàn)自己的PlugIn 類。
實(shí)現(xiàn)PlugIn 接口必須實(shí)現(xiàn)如下兩個(gè)方法。
1 void destroy()。
2 void init(ActionServlet serlet, ModuleConfig config) 。
應(yīng)用啟動(dòng)時(shí)調(diào)用init 方法,而應(yīng)用關(guān)閉時(shí)則調(diào)用destroy 方法。
下面是SessionFactoryLoaderPlugIn 的實(shí)現(xiàn)類:
public class SessionFactoryLoaderPlugin implements PlugIn {
//Hibernate 的配置文件
private String configFile;
//應(yīng)用關(guān)閉時(shí),銷毀資源
public void destroy()
System.out.println("系統(tǒng)銷毀SessionFactory");
}
//應(yīng)用啟動(dòng)時(shí),完成SessionFactory 的初始化
public void init(ActionServlet actionServlet , ModuleConfig config) throws ServletException
System.out.println("系統(tǒng)以" + getConfigFile() + "為配置文件初始化SessionFactory") ;
//獲取Plugln 配置文件的方法
public String getConfigFile() {
return configFile;
}
// 負(fù)責(zé)加載Plugln 配置屬性的方法
public void setConfigFile(String configFile) {
this.configFile = configFile;
}
}
在上面的PlugIn 中,并沒有真正初始化SessionFactory ,僅在控制臺(tái)打印出字符串來標(biāo)識(shí)創(chuàng)建動(dòng)作。另外,還提供了configFile 屬性的setter 和getter 方法,這兩個(gè)方法負(fù)責(zé)訪問plugin 元素的configFile 屬性。
( 2 ) 將SessionFactoryLoaderPlugIn 配置在struts-config.xml 文件中。方法與ValidatorPlugIn 的配置并沒有區(qū)別,下面是配置SessionFactoryLoaderPlugIn 的代碼:
<plug-in className="hoo.SessionFactoryLoaderPluging">
<set-property property="conf工gFile" value=" WEB-INF/hibernate.cfg.xml"I>
</plug-in>
在配置SessionFactoryLoaderPlugIn 時(shí),配置了configFile 屬性,該屬性用于確定Hibernate 配置文件的文件名。
繼承RequestProcessor
RequestProcessor 是Struts 的核心類,而Struts 的核心控制器是ActionServlet 。但ActionServlet 并未完成真正的處理,只是調(diào)用RequestProcessor , RequestProcessor 才是Struts 的核心類。
擴(kuò)展RequestProcessor 的實(shí)例在Spring 中有個(gè)示范, Spring 提供的Delegating RequestProcessor 是一個(gè)很好的示例。下面示例對(duì)RequestProcessor 進(jìn)行簡(jiǎn)單的擴(kuò)展。
RequestProcessor 包含了如下常見的方法。
* ActionForm processActionForm: RequestProcessor填充ActionForm 時(shí)執(zhí)行該方法。
* Action processActionCreate: RequestProcessor 調(diào)用Action 時(shí)調(diào)用該方法。
* boolean processPreprocess: 預(yù)處理用戶請(qǐng)求時(shí)執(zhí)行該方法。
* boolean processValidate: 處理輸入校驗(yàn)時(shí)調(diào)用該方法。
擴(kuò)展RequestProcessor 只需兩步即可。
(2)在struts-config.xml 文件中配置MyRequestProcessor。用戶重寫了RequestProcessor,但Struts 并不知道,必須在struts-config且nl 中配置才可以。
下面是配置MyRequestProcessor 的代碼:
<controller processorClass="lee.MyRequestProcessor" />
該屬性的配置應(yīng)該放在action-mappings元素之后。
注意:重寫RequestProccessor的方法時(shí),別忘了使用super 來調(diào)用父類的動(dòng)作。如果沒有調(diào)用該方法,意味著開發(fā)者必須完成Struts 框架所完成的動(dòng)作。這是不應(yīng)該的,因?yàn)槌绦騿T只是在框架中加入額外的處理,并不是要替代Struts。
繼承ActionServlet
如果需要在開始處理請(qǐng)求,或者處理結(jié)束之后加入自己的處理時(shí),可對(duì)ActionServlet進(jìn)行擴(kuò)展。例如解決中文的編碼問題。
ActionServlet 接收處理請(qǐng)求參數(shù)時(shí),并不是按GBK 的解碼方式處理請(qǐng)求,因此容易形成亂碼。為了解決該問題,可以強(qiáng)制指定ActionServlet 使用GBK 的解碼方式。
繼承ActionServlet重寫process方法,設(shè)置request、response編碼為gbk,然后配置在web.xml中。
Servlet 是一種比JSP 更早的動(dòng)態(tài)網(wǎng)頁編程技術(shù)。在沒有JSP 之前, Servlet 也是同時(shí)充當(dāng)視圖層、業(yè)務(wù)邏輯層及持久層角色。
Servlet 的開發(fā)效率非常低,特別是當(dāng)使用Servlet 生成表現(xiàn)層頁面時(shí),頁面中所有的HTML 標(biāo)簽,都需采用Servlet 的輸出流來輸出,因此極其煩瑣。由于Servlet 是個(gè)標(biāo)準(zhǔn)的Java 類,因此必須由程序員開發(fā),其修改難度大,美工人員根本無法參與Servlet 頁面的開發(fā)。這一系列的問題,都阻礙了Servlet 作為表現(xiàn)層的使用。
自MVC 規(guī)范出現(xiàn)后, Servlet 的責(zé)任開始明確下來,僅僅作為控制器使用,不再需要生成頁面標(biāo)簽,也不再作為視圖層角色使用。
Servlet ,通常稱為服務(wù)器端小程序,是運(yùn)行在服務(wù)器端的程序,用于處理及響應(yīng)客戶端請(qǐng)求。
Servlet 是個(gè)特殊的Java 類,這個(gè)Java 類必須繼承HttpServlet 。每個(gè)Servlet 可以響應(yīng)戶端的請(qǐng)求。Servlet 提供不同的方法用于響應(yīng)客戶端請(qǐng)求。
doGet: 用于響應(yīng)客戶端的get 請(qǐng)求。
doPost: 用于響應(yīng)客戶端的post 請(qǐng)求。
doPut: 用于響應(yīng)客戶端的put 請(qǐng)求。
doDelete: 用于響應(yīng)客戶端的delete 請(qǐng)求。
事實(shí)上,客戶端的請(qǐng)求通常只有g(shù)et 和post 兩種; Servlet 為了響應(yīng)這兩種請(qǐng)求,必須重寫doGet 和doPost 兩個(gè)方法。如果Servlet 為了響應(yīng)四個(gè)方法,則需要同時(shí)重寫上面的四個(gè)方法。
大部分時(shí)候, Servlet 對(duì)于所有請(qǐng)求的響應(yīng)都是完全一樣的。此時(shí),可以采用重寫一個(gè)方法來代替上面的幾個(gè)方法, Servlet 只需重寫service 方法即可響應(yīng)客戶端的所有請(qǐng)求。另外, HttpServlet 還包含兩個(gè)方法。
init(ServletConfig config): 創(chuàng)建Servlet 實(shí)例時(shí),調(diào)用的初始化方法。
destroy: 銷毀Servlet 實(shí)例時(shí),自動(dòng)調(diào)用的資源回收方法。
通常無須重寫init和destroy兩個(gè)方法,除非需要在初始化Servlet 時(shí),完成某些資源初始化的方法,才考慮重寫init 方法。如果需要在銷毀Servlet 之前,先完成某些資源的回收,比如關(guān)閉數(shù)據(jù)庫連接等,才需要重寫destroy 方法。
注意:如果重寫了init(ServletConfig config)方法,則應(yīng)在重寫該方法的第一行調(diào)用super.init(config) 。該方法將調(diào)用HttpServlet 的init 方法。
Servlet 和JSP 的區(qū)別在于:
Servlet 中沒有內(nèi)置對(duì)象,原來JSP 中的內(nèi)置對(duì)象都必須通過HttpServletRequest對(duì)象,或由HttpServletResponse 對(duì)象生成:
對(duì)于靜態(tài)的HTML 標(biāo)簽, Servlet 都必須使用頁面輸出流逐行輸出。
這也正是筆者在前面介紹的: JSP 是Servlet 的一種簡(jiǎn)化,使用JSP 只需要完成程序員需要輸出到客戶端的內(nèi)容,至于JSP 中的Java 腳本如何鑲嵌到一個(gè)類中,由JSP 容器完成。而Servlet 則是個(gè)完整的Java 類,這個(gè)類的service 方法用于生成對(duì)客戶端的響應(yīng)。
Servlet 的配置
編輯好的Servlet 源文件并不能響應(yīng)用戶請(qǐng)求,還必須將其編譯成class 文件。將編譯后的HelloServlet. class 文件放在WEB-INF/classes 路徑下,如果Servlet 有包,則還應(yīng)該將class 文件放在對(duì)應(yīng)的包路徑下。
為了讓Servlet 能響應(yīng)用戶請(qǐng)求,還必須將Servlet 配置在Web 應(yīng)用中。配置Servlet時(shí),需要修改web.xrnl 文件。
配置Servlet 需要配置兩個(gè)部分。<servlet>/<servlet-mapping>
Servlet的生命周期
Servlet 在容器中運(yùn)行,其實(shí)例的創(chuàng)建及銷毀等都不是由程序員決定的,而是由容器進(jìn)行控制。
Servlet 的創(chuàng)建有兩個(gè)選擇。
客戶端請(qǐng)求對(duì)應(yīng)的Servlet 時(shí),創(chuàng)建Servlet 實(shí)例:大部分的Servlet 都是這種Servlet。 Web 應(yīng)用啟動(dòng)時(shí),立即創(chuàng)建Servlet 實(shí)例:即load-on-startup Servlet。
每個(gè)Servlet 的運(yùn)行都遵循如下生命周期。
(1)創(chuàng)建Servlet 實(shí)例。
(2) Web 容器調(diào)用Servlet 的init 方法,對(duì)Servlet 進(jìn)行初始化。
(3) Servlet 初始化后,將一直存在于容器中,用于響應(yīng)客戶端請(qǐng)求。如果客戶端有g(shù)et 請(qǐng)求,容器調(diào)用Servlet 的doGet 方法處理并響應(yīng)請(qǐng)求。對(duì)于不同的請(qǐng)求,有不同的處理方法,或者統(tǒng)一使用service 方法處理來響應(yīng)用戶請(qǐng)求。
(4) Web 容器角色銷毀Servlet 時(shí),調(diào)用Servlet 的destroy 方法,通常在關(guān)閉Web容器之時(shí)銷毀Servlet。
使用Servlet創(chuàng)作為控制器
正如前面見到,使用Servlet 作為表現(xiàn)層的工作量太大,所有的HTML 標(biāo)簽都需要使用頁面輸出流生成。因此,使用Servlet 作為表現(xiàn)層有如下三個(gè)劣勢(shì)。
開發(fā)效率低,所有的HTML 標(biāo)簽都需使用頁面輸出流完成。
不利于團(tuán)隊(duì)協(xié)作開發(fā),美工人員無法參與Servlet 界面的開發(fā)。
程序可維護(hù)性差,即使修改一個(gè)按鈕的標(biāo)題,都必須重新編輯Java 代碼,并重新編譯。
整個(gè)結(jié)構(gòu)非常清晰,下面是MVC 中各個(gè)角色的對(duì)應(yīng)組件。
M: Model,即模型,對(duì)應(yīng)JavaBean 。
V: View ,即視圖,對(duì)應(yīng)JSP 頁面。
C: Controller,即控制器,對(duì)應(yīng)Servlet。
load-on-startup Servlet
Servlet 的實(shí)例化有兩個(gè)時(shí)機(jī):用戶請(qǐng)求之時(shí),或應(yīng)用啟動(dòng)之時(shí)。應(yīng)用啟動(dòng)時(shí)就啟動(dòng)的Servlet 通常是用于某些后臺(tái)服務(wù)的Servlet ,或者攔截很多請(qǐng)求的Servlet; 這種Servlet 通常作為應(yīng)用的基礎(chǔ)Servlet 使用,提供重要的后臺(tái)服務(wù)。如果需要Web 應(yīng)用啟動(dòng)時(shí),可使用load-on-startup 元素完成Servlet 的初始化。load-on-startup 元素只接收一個(gè)整型值,這個(gè)整型值越小, Servlet 就越優(yōu)先初始化。
訪問Servlet 的配置參數(shù)
配置Servlet 時(shí),還可以增加附加的配置參數(shù)。通過使用配置參數(shù),可以實(shí)現(xiàn)更好地解耦,避免將所有的參數(shù)以硬編碼方式寫在程序中。
訪問Servlet 配置參數(shù)要通過ServletConfig 類的實(shí)例完成, ServletConfig提供如下方法。
java.lang.String getInitParameter(java.lang.String name): 用于獲取初始化參數(shù)。
注意: JSP 的內(nèi)直對(duì)象config 就是此處的ServletConfig
自定義標(biāo)簽類
使用標(biāo)簽類,可以使用簡(jiǎn)單的標(biāo)簽來封裝復(fù)雜的功能,從而使團(tuán)隊(duì)更好地協(xié)作開發(fā)(能讓美工人員更好地參與JSP 頁面的開發(fā))。
自定義標(biāo)簽類都必須繼承一個(gè)父類: java.Servlet.jsp.tagext.TagSupport 。除此之外,自定義標(biāo)簽類還有如下要求。
·如果標(biāo)簽類包含屬性,每個(gè)屬性都有對(duì)應(yīng)的getter 和setter 方法。
·重寫doStartTag或doEndTag方法,這兩個(gè)方法生成頁面內(nèi)容。
·如果需要在銷毀標(biāo)簽之前完成資源回收,則重寫re1ease方法。
TLD 文件
TLD 是Tag Library Definition 的縮寫,即標(biāo)簽庫定義,文件的后綴是tld ,每個(gè)TLD文件對(duì)應(yīng)一個(gè)標(biāo)簽庫,一個(gè)標(biāo)簽庫中可包含多個(gè)標(biāo)簽。TLD 文件也稱為標(biāo)簽庫定義文件。標(biāo)簽庫定義文件的根元素是taglib,它可以有多個(gè)tag 子元素,每個(gè)tag 子元素都對(duì)應(yīng)一個(gè)標(biāo)簽。
編輯了標(biāo)簽庫定義文件還不夠, Web 容器還無法加載標(biāo)簽庫定義文件。還必須在web.xml 文件中增加標(biāo)簽庫的定義。在web.xml 文件中定義標(biāo)簽庫時(shí)使用taglib 元素,該元素包含兩個(gè)子元素: taglib-uri和taglib-location,前者確定標(biāo)簽庫的URI; 后者確定標(biāo)簽庫定義文件的位置。
使用標(biāo)簽庫
使用標(biāo)簽庫分成以下兩步。
(1) 導(dǎo)入標(biāo)簽庫:使用taglib 編譯指令導(dǎo)入標(biāo)簽。
(2) 使用標(biāo)簽:在JSP 頁面中使用自定義標(biāo)簽。
taglib 的語法格式如下:
〈%@ taglib uri="tagliburi" prefix="tagPrefix" %〉
其中uri 屬性確定標(biāo)簽庫定義文件的URI,這個(gè)URI 就是在web.xml 文件中為標(biāo)簽
庫定義的URI。而prefix 屬性確定的是標(biāo)簽前綴,即在JSP 頁面中使用標(biāo)簽時(shí),該標(biāo)簽
庫負(fù)責(zé)處理的標(biāo)簽前綴。
使用標(biāo)簽的語法格式如下:
<tagPrefix : tagName tagAttribute=ntagValue n ...>
<tagBody/>
</tagPrefix>
如果該標(biāo)簽沒有標(biāo)簽體,則可以使用如下語法格式:
<tagPrefix : tagName tagAttribute=ntagValue n …/>
帶標(biāo)簽體的標(biāo)簽
帶標(biāo)簽體的標(biāo)簽,就是允許在標(biāo)簽內(nèi)嵌套標(biāo)簽,通常可用于完成一些邏輯運(yùn)算例如判斷和循環(huán)等。
帶標(biāo)簽體的標(biāo)簽需要繼承BodyTagSupport,該類包含一個(gè)bodyContent 屬性,該屬性代表標(biāo)簽體。
BodyTagSupport 還包含兩個(gè)方法。
doAfterBody: 每次處理完標(biāo)簽體后調(diào)用該方法。
void doInitBody: 開始調(diào)用標(biāo)簽體時(shí)調(diào)用該方法。
如果有必要,可以重寫這兩個(gè)方法。
在處理標(biāo)簽類的各個(gè)方法中,不同的返回值對(duì)應(yīng)不同的含義,常用的返回值有如下幾個(gè)。
SKIP_BODY: 不處理標(biāo)簽體,直接調(diào)用doEndTag方法。
SKIP_PAGE: 忽略標(biāo)簽后面的JSP 頁面。
EVAL_PAGE: 處理標(biāo)簽結(jié)束,直接處理頁面內(nèi)容。
EVAL_BODY_BUFFERED: 處理標(biāo)簽體。
EVAL_BODY_INCLUDE: 處理標(biāo)簽體,但忽略setBodyContent和doInitBody方法。
EVAL_BODY_AGAIN: 對(duì)標(biāo)簽體循環(huán)處理。
Filter
Filter 并不是一個(gè)標(biāo)準(zhǔn)的Servlet ,它不能處理用戶請(qǐng)求,也不能對(duì)客戶端生成響應(yīng)。主要用于對(duì)HttpServletRequest 進(jìn)行預(yù)處理,也可以對(duì)HttpServletResponse 進(jìn)行后處理,是個(gè)典型的處理鏈。
Filter 有如下幾個(gè)用處。
·在HttpServletRequest 到達(dá)Servlet 之前,攔截客戶的HttpServletRequest 。
·根據(jù)需要檢查HttpServletRequest ,也可以修改HttpServletRequest 頭和數(shù)據(jù)。
·在HttpServletResponse 到達(dá)客戶端之前,攔截HttpServletResponse 。
·根據(jù)需要檢查HttpServletResponse ,也可以修改HttpServletResponse 頭和數(shù)據(jù)。
Filter 有如下幾個(gè)種類。
·用戶授權(quán)的Filter: Filter 負(fù)責(zé)檢查用戶請(qǐng)求,根據(jù)請(qǐng)求過濾用戶非法請(qǐng)求。
·日志Filter: 詳細(xì)記錄某些特殊的用戶請(qǐng)求。
·負(fù)責(zé)解碼的Filter: 包括對(duì)非標(biāo)準(zhǔn)編碼的請(qǐng)求解碼。
.能改變XML 內(nèi)容的XSLTFilter 等。
一個(gè)Filter 可負(fù)責(zé)攔截多個(gè)請(qǐng)求或響應(yīng):一個(gè)請(qǐng)求或響應(yīng)也可被多個(gè)請(qǐng)求攔截。
創(chuàng)建一個(gè)Filter 只需兩個(gè)步驟:
(1)創(chuàng)建Filter 處理類:
(2) 在web.xml 文件中配置Filter。
創(chuàng)建Filter 類
創(chuàng)建Filter 必須實(shí)現(xiàn)javax.servle t. Filter 接口,在該接口中定義了三個(gè)方法。
void init(FilterConfig config): 用于完成Filter 的初始化。
void destroy: 用于Filter 銷毀前,完成某些資源的回收。
void doFilter(ServletRequest request, ServletResponse response,FilterChain chain): 實(shí)現(xiàn)過濾功能,該方法就是對(duì)每個(gè)請(qǐng)求及響應(yīng)增加的額外處理。
執(zhí)行chain.doFilter(request,reponse)方法,當(dāng)Filter 對(duì)請(qǐng)求過濾后,依然將請(qǐng)求發(fā)送到目的地址。如果檢查權(quán)限,可以在Filter 中根據(jù)用戶請(qǐng)求的HttpSession,判斷用戶權(quán)限是否足夠。
如果權(quán)限不夠,則調(diào)用重定向即可,無須調(diào)用chain.doFilter(request,reponse)方法。
配置Filter
Filter 的配置和Servlet 的配置非常相似,都需要配置兩個(gè)部分:
·配置Filter 名。
·配置Filter 攔截URL 模式。
區(qū)別在于, Servlet 通常只配置一個(gè)URL ,而Filter 可以同時(shí)攔截多個(gè)請(qǐng)求的URL。
因此,可以配置多個(gè)Filter 攔截模式。
Listener
Listener 的作用非常類似于load-on-startup Servlet。用于在Web 應(yīng)用啟動(dòng)時(shí),啟動(dòng)某些后臺(tái)程序,這些后臺(tái)程序負(fù)責(zé)為系統(tǒng)運(yùn)行提供支持。
Listener 與load-on-startup Servlet 的區(qū)別在于: Listener 的啟動(dòng)時(shí)機(jī)比load-on-startup Servlet 早,只是Listener 是Servlet 2.3 規(guī)范之后才出現(xiàn)的。
使用Listener 只需要兩個(gè)步驟:
(1) 創(chuàng)建Listener 實(shí)現(xiàn)類。
(2) 在web.xml 文件中配置Listener。
創(chuàng)建Listener 類
創(chuàng)建Li stener 類必須實(shí)現(xiàn)ServletContex tListener 接口,該接口包含兩個(gè)方法。
eontextInitialized(ServletContextEvent see): 啟動(dòng)Web 應(yīng)用時(shí),系統(tǒng)調(diào)用該Filter的方法。
eontextDestroyed(ServletContextEvent see): 關(guān)閉Web 應(yīng)用時(shí)候,系統(tǒng)調(diào)用Filter
的方法。
配置Listener
正如load-an-startup Servlet 一樣, Listener 用于啟動(dòng)Web 應(yīng)用的后臺(tái)服務(wù)程序,但不負(fù)責(zé)處理及響應(yīng)用戶請(qǐng)求,因此無須配置URL。
若將Listener 配置在Web 容器中(如果Web 容器支持Listener),則Listener 將隨Web 應(yīng)用的啟動(dòng)而啟動(dòng)。
配置Listener 時(shí)使用<listener/>元素,下面是配置Listener 的片段:
<!-- 配置Listener-->
<listener>
<!- 指定Listener 的實(shí)現(xiàn)類→
<listener-class>lee.ScheduleListener</listener-class>
</listener>
在上面的配置中,既無須配置Listener 的名字,也無須配置Listener 的URL 只需配置它的實(shí)現(xiàn)類即可。此時(shí)容器將自動(dòng)檢測(cè)部署在容器中的Listener,并在應(yīng)用啟動(dòng)時(shí),自動(dòng)加載所有的Listener。
摘要: UML的組成
UML由視圖(View)、圖(Diagram)、模型元素(Model Element)和通用機(jī)制(General Mechanism)等幾個(gè)部分組成。
a) 視圖(View): 是表達(dá)系統(tǒng)的某一方面的特征的UML建模元素的子集,由多個(gè)圖構(gòu)成,是在某一個(gè)抽象層上,對(duì)系統(tǒng)的抽象表示。
b) 圖(Diagram): 是模型元素集的圖形表示,通常是由弧(關(guān)系)和頂點(diǎn)(其他模型元素)相互連接構(gòu)成的。
c) 模型元素(Model Element):代表面向?qū)ο笾械念悺?duì)象、消息和關(guān)系等概念,是構(gòu)成圖的最基本的常用概念。
d) 通用機(jī)制(General Mechanism):用于表示其他信息,比如注釋、模型元素的語義等。另外,UML還提供擴(kuò)展機(jī)制,使UML語言能夠適應(yīng)一個(gè)特殊的方法(或過程),或擴(kuò)充至一個(gè)組織或用戶。
閱讀全文
摘要: 對(duì)jQuery blockUI插件進(jìn)行了小的封裝擴(kuò)展,支持confirm、alert、dialog彈出窗口提示信息,支持按鈕回調(diào)事件。可以自定義css樣式、覆蓋blockUI的樣式等 首先要到j(luò)query blockUI 官方網(wǎng)址:http://malsup.com/jquery/block/ 下載jquery.blockUI JS lib:http://malsup.com/jquery/blo...
閱讀全文
select * from account where userName like 'ad%';
select * from account where userName >= 'ad' and userName < 'ae';
/*
這兩種查詢的結(jié)果是一樣的,效率好像也差不多,沒有做具體的效率測(cè)試,有興趣可以測(cè)試下效率。
like查詢中的ad%是查詢ad開頭userName的數(shù)據(jù),
而userName >= 'ad'就是查詢ad開頭的數(shù)據(jù)并且還包含 ae、af、ag……,也就是說是查詢“ad”中包含d且大于“ad”中d的數(shù)據(jù)
所以,and userName < 'ad'就保證查詢的區(qū)間在“ad”中的,而ae、af、ag……這些數(shù)據(jù)就不會(huì)出現(xiàn)在結(jié)果集中。
當(dāng)然你可以試試:
select * from account where userName >= 'ad' and userName < 'az';
結(jié)果集是不是包含:ae、af、ag……ak、al……ay、az等開頭的數(shù)據(jù)。
*/
摘要: Solr 是一種可供企業(yè)使用的、基于 Lucene 的搜索服務(wù)器,它支持層面搜索、命中醒目顯示和多種輸出格式。在這篇文章中,將介紹 Solr 并展示如何輕松地將其表現(xiàn)優(yōu)異的全文本搜索功能加入到 Web 應(yīng)用程序中。 開發(fā)環(huán)境: System:Windows WebBrowser:IE6+、Firefox3+ JDK:1.6+ JavaEE Server:tomcat5.0.2.8、tom...
閱讀全文
摘要:
閱讀全文
摘要: 基本原理:利用URLConnection獲取要下載文件的長(zhǎng)度、頭部等相關(guān)信息,并設(shè)置響應(yīng)的頭部信息。并且通過URLConnection獲取輸入流,將文件分成指定的塊,每一塊單獨(dú)開辟一個(gè)線程完成數(shù)據(jù)的讀取、寫入。通過輸入流讀取下載文件的信息,然后將讀取的信息用RandomAccessFile隨機(jī)寫入到本地文件中。同時(shí),每個(gè)線程寫入的數(shù)據(jù)都文件指針也就是寫入數(shù)據(jù)的長(zhǎng)度,需要保存在一個(gè)臨時(shí)文件中。這樣當(dāng)...
閱讀全文
開發(fā)環(huán)境:
System:Windows
WebBrowser:IE6+、Firefox3+
JavaEE Server:tomcat5.0.2.8、tomcat6
IDE:eclipse、MyEclipse 8
Flex IDE:Flash Builder 4
BlazeDS:4.5
開發(fā)依賴庫:
JavaEE5、blazeDS 4.5
Email:hoojo_@126.com
Blog:http://blog.csdn.net/IBM_hoojo
http://hoojo.cnblogs.com/
一、準(zhǔn)備工作
1、 首先要提供相關(guān)的jar包
Java服務(wù)器端需要提供BlazeDS相關(guān)的配置和jar包
下載地址:http://opensource.adobe.com/wiki/display/blazeds/download+blazeds+trunk
下載后,解壓你可以看到這樣的一個(gè)目錄
Docs就是文檔
Resource是源碼
SampleDB是示例用的數(shù)據(jù)庫,可以運(yùn)行startdb.bat來啟動(dòng)數(shù)據(jù)庫
Tomcat是內(nèi)置的tomcat,如果你沒有tomcat的話可以使用它,在tomcat的webapps目錄中有samples示例
blazeds.war就是blazeDS的核心文件、庫,你可以把這個(gè)war放到tomcat的webapps目錄下,就會(huì)自動(dòng)解壓。當(dāng)然你也可以自己手動(dòng)解壓。
Blazeds-spring.war是和spring整合的配置
Ds-console.war是blazeDS的控制臺(tái)程序
Samples.war是官方提供的示例
Samples-spring.war是spring和blazeDS的整合示例
二、部署服務(wù)器端程序
1、新建一個(gè)JavaWeb Project工程,然后在WEB-INF/lib目錄中添加如下jar包
這些jar包可以在blazeds.war包中的lib目錄中可以找到
2、 然后你需要將blazeds.war包中的WEB-INF目錄下的flex目錄復(fù)制到當(dāng)前工程的WEB-INF下
3、 將blazeds.war包中的WEB-INF目錄下的web.xml的配置,添加到當(dāng)前工程的web.xml文件中
4、 最后基本的樣式如下
5、 最后你發(fā)布當(dāng)前工程,如果沒有錯(cuò)誤就表明你服務(wù)器端部署成功了。
6、 編寫一個(gè)HelloWorld的java程序。代碼如下
package com.hoo.flex;
/**
* <b>function:</b> HelloWorld Example
* @author hoojo
* @createDate 2011-8-31 下午06:11:27
* @file HelloWorld.java
* @package com.hoo.flex
* @project BlazeDSServer
* @blog http://blog.csdn.net/IBM_hoojo
* @email hoojo_@126.com
* @version 1.0
*/
public class HelloWorld {
public HelloWorld() {
}
public String sayHello(String name) {
return "[" + name + "] say hello!";
}
}
就一個(gè)sayHello方法,接收一個(gè)參數(shù)。
三、Flex客戶端程序
1、創(chuàng)建一個(gè)Flex工程,在選擇服務(wù)器技術(shù)的時(shí)候,你需要選擇J2EE。然后勾上使用J2EE技術(shù),然后選擇BlazeDS。點(diǎn)擊Next下一步
2、配置根文件夾,也就是JavaEE服務(wù)器端發(fā)布程序在tomcat中的位置。我這里是在tomcat的webapps的BlazeDSServer中,BlazeDSServer是我的服務(wù)器端程序。根URL是訪問服務(wù)器端程序的url;上下文目錄對(duì)應(yīng)工程名稱;最后就是輸出文件夾目錄,這個(gè)是Flex的文件最后在tomcat中保存的目錄。
3、最后你需要設(shè)置服務(wù)器端的services-config.xml的路徑到編譯參數(shù)中,這個(gè)很重要!如果你不設(shè)置的話,那么你在后面用RemoteObject調(diào)用BlazeDS的時(shí)候,就需要設(shè)置endpoint。設(shè)置如下:
-services是參數(shù)鍵,后面的字符串是值。我這里是設(shè)置BlazeDSServer發(fā)布到tomcat目錄中的services-config.xml的路徑。
4、編譯Flex前端代碼,代碼如下:
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" viewSourceURL="BlazeDSHelloWorld.mxml" layout="absolute" minWidth="955" minHeight="600">
<mx:Script>
<![CDATA[
import mx.controls.Alert;
import mx.rpc.AsyncToken;
import mx.rpc.events.ResultEvent;
private function faultHandler(event: Event): void {
Alert.show(event.toString(), event.type);
}
private function resultHandler(event: ResultEvent): void {
//event.result是服務(wù)器端返回對(duì)象
result.text = "Message:" + event.result.toString();
}
private function sendHandler(): void {
helloRemoteObject.sayHello(userName.text);
}
]]>
</mx:Script>
<!-- 當(dāng)工程沒有設(shè)置編譯器-service參數(shù) 或是-context-root等參數(shù),就需要手動(dòng)設(shè)置endpoint參數(shù) -->
<mx:RemoteObject
id="helloRemoteObject"
destination="helloWorld"
fault="faultHandler(event)"
result="resultHandler(event)"
showBusyCursor="true"/>
<mx:Panel x="10" y="10" width="272" height="148" layout="absolute" title="BlazeDS Remote HelloWorld Sample">
<mx:Label x="10" y="22" text="請(qǐng)輸入名稱"/>
<mx:TextInput x="70" y="19" id="userName"/>
<mx:Button x="184" y="45" label="發(fā)送" click="sendHandler()"/>
<mx:Text x="10" y="79" id="result"/>
</mx:Panel>
</mx:Application>
首先你需要將Java服務(wù)器端的HelloWorld程序配置在flex的remoting-config.xml中,配置如下:
<?xml version="1.0" encoding="UTF-8"?>
<service id="remoting-service"
class="flex.messaging.services.RemotingService">
<adapters>
<adapter-definition id="java-object" class="flex.messaging.services.remoting.adapters.JavaAdapter" default="true"/>
</adapters>
<default-channels>
<channel ref="my-amf"/>
</default-channels>
<destination id="helloWorld">
<properties>
<source>com.hoo.flex.HelloWorld</source>
</properties>
</destination>
</service>
上面mxml代碼中的RemoteObject的destination對(duì)應(yīng)的就是remoting-config.xml配置文件中的destination的id。這個(gè)是一一對(duì)應(yīng)的,然后在sendHandler方法中,helloRemoteObject對(duì)應(yīng)的就是RemoteObject的id,而sayHello方法對(duì)應(yīng)的就是配置在remoting-config.xml中的destination的source的Java服務(wù)器端代碼的公有方法。添加完配置后,需要重啟tomcat。
運(yùn)行上面的flex程序后,如果輸入?yún)?shù)后,點(diǎn)擊發(fā)送,可以看到服務(wù)器端返回的消息就說明BlazeDS整合Flex成功了。
摘要: Dom4j也可以很方便完成XML文檔的創(chuàng)建、元素的修改、文檔的查詢遍歷等,但dom4j稍比jdom復(fù)雜一點(diǎn),不過在大片文檔的情況下dom4j的性能要不jdom好。 # 準(zhǔn)備 首先,提供相關(guān)的jar包 Dom4j jar包下載: http://sourceforge.net/projects/dom4j/files/dom4j-2.0.0-ALPHA-2/ jaxen jar下載: http://...
閱讀全文
摘要: 可擴(kuò)展標(biāo)記語言——eXtensible Markup Language 用戶可以自己定義語言標(biāo)記,只要有開始和閉合標(biāo)簽即可。 xsl裝飾、修飾xml的顯示結(jié)果。 dtd約束xml文件中的標(biāo)記。 ? XML的優(yōu)點(diǎn): 1、xml可以讓數(shù)據(jù)和標(biāo)記分離。 2、異質(zhì)信息互通 3、機(jī)...
閱讀全文
SQL Server 數(shù)據(jù)庫設(shè)計(jì)
一、數(shù)據(jù)庫設(shè)計(jì)的必要性
二、什么是數(shù)據(jù)庫設(shè)計(jì)
三、數(shù)據(jù)庫設(shè)計(jì)的重要
四、數(shù)據(jù)模型
實(shí)體-關(guān)系(E-R)數(shù)據(jù)模型
實(shí)體(Entity)
屬性(Attribute)
關(guān)系(Relationship)
五、數(shù)據(jù)庫設(shè)計(jì)步驟
1、 需求分析階段
2、 概要設(shè)計(jì)階段
3、 詳細(xì)設(shè)計(jì)階段
六、數(shù)據(jù)庫設(shè)計(jì)規(guī)范化
數(shù)據(jù)庫設(shè)計(jì)中經(jīng)常出現(xiàn)的問題
規(guī)范設(shè)計(jì)
規(guī)范化和性能關(guān)系
SQL Server 數(shù)據(jù)庫基礎(chǔ)編程
Go批處理語句
使用、切換數(shù)據(jù)庫
創(chuàng)建、刪除數(shù)據(jù)庫
基本數(shù)據(jù)類型
精確數(shù)字類型
近似數(shù)字類型
日期時(shí)間類型
字符串類型
Unicode字符串類型
二進(jìn)制字符串類型
判斷表或其他對(duì)象及列是否存在
創(chuàng)建、刪除表
給表添加字段、修改字段、刪除字段
添加、刪除約束
插入數(shù)據(jù)
查詢、修改、刪除數(shù)據(jù)
備份數(shù)據(jù)、表
利用存儲(chǔ)過程查詢表信息
SQL Server Transact-SQL 編程
變量
1、 局部變量(Local Variable)
2、 全局變量(Global Variable
輸出語句
邏輯控制語句
1、 if-else判斷語句
2、 while…continue…break循環(huán)語句
3、 case
4、 其他語句
SQL Server T-SQL高級(jí)查詢
基本常用查詢
嵌套子查詢
# from (select … table)示例
# in, not in子句查詢示例
# exists和not exists子句查詢示例
# some、any、all子句查詢示例
聚合查詢
1、 distinct去掉重復(fù)數(shù)據(jù)
2、 compute和compute by匯總查詢
3、 cube匯總
排序函數(shù)
# row_number函數(shù)
# rank函數(shù)函數(shù)
# dense_rank函數(shù)
# partition by分組子句
# ntile平均排序函數(shù)
集合運(yùn)算
1、 union和union all進(jìn)行并集運(yùn)算
2、 intersect進(jìn)行交集運(yùn)算
3、 except進(jìn)行減集運(yùn)算
公式表表達(dá)式
連接查詢
1、 簡(jiǎn)化連接查詢
2、 left join左連接
3、 right join右連接
4、 inner join內(nèi)連接
5、 cross join交叉連接
6、 自連接(同一張表進(jìn)行連接查詢)
函數(shù)
1、 聚合函數(shù)
2、 日期時(shí)間函數(shù)
3、 數(shù)學(xué)函數(shù)
4、 元數(shù)據(jù)
5、 字符串函數(shù)
6、 安全函數(shù)
7、 系統(tǒng)函數(shù)
8、 配置函數(shù)
9、 系統(tǒng)統(tǒng)計(jì)函數(shù)
10、 用戶自定義函數(shù)
SQL Server 索引和視圖
索引
1、 什么是索引
2、 索引分類
3、 創(chuàng)建索引
4、 適合的創(chuàng)建索引的列
5、 不適合創(chuàng)建索引的列
視圖
1、 什么是視圖
2、 創(chuàng)建視圖準(zhǔn)則
3、 創(chuàng)建視圖
4、 修改視圖
5、 加密視圖
SQL Server 存儲(chǔ)過程
存儲(chǔ)過程的概念
1、 存儲(chǔ)過程的優(yōu)點(diǎn)
A、 存儲(chǔ)過程允許標(biāo)準(zhǔn)組件式編程
B、 存儲(chǔ)過程能夠?qū)崿F(xiàn)較快的執(zhí)行速度
C、 存儲(chǔ)過程減輕網(wǎng)絡(luò)流量
D、 存儲(chǔ)過程可被作為一種安全機(jī)制來充分利用
系統(tǒng)存儲(chǔ)過程
用戶自定義存儲(chǔ)過程
1、 創(chuàng)建語法
2、 創(chuàng)建不帶參數(shù)存儲(chǔ)過程
3、 修改存儲(chǔ)過程
4、 帶參存儲(chǔ)過程
5、 帶通配符參數(shù)存儲(chǔ)過程
6、 帶輸出參數(shù)存儲(chǔ)過程
7、 不緩存存儲(chǔ)過程
8、 加密存儲(chǔ)過程
9、 帶游標(biāo)參數(shù)存儲(chǔ)過程
10、 分頁存儲(chǔ)過程
Raiserror
SQL Server 事務(wù)、異常和游標(biāo)
事務(wù)
1、 事務(wù)的特點(diǎn)
原子性
一致性
隔離性
持久性
2、 事務(wù)的模式
a、 顯示事務(wù)
b、 自動(dòng)提交事務(wù)
c、 隱式事務(wù)
3、 事務(wù)處理
a、 begin transaction語句
b、 commit transaction語句
c、 rollback transaction語句
4、 事務(wù)的示例
異常
# 示例:用異常處理錯(cuò)誤信息
# 示例:異常能處理的錯(cuò)誤信息
# 示例:無法提交的事務(wù)
# 示例:處理異常日志信息
游標(biāo)
1、游標(biāo)實(shí)際功能
2、游標(biāo)的基本操作
A、 定義游標(biāo)
B、 打開游標(biāo)
C、 檢索游標(biāo)
D、 關(guān)閉游標(biāo)
E、 刪除游標(biāo)
3、游標(biāo)操作示例
SQL Server 觸發(fā)器
什么是觸發(fā)器
DML觸發(fā)器分為:
1、 after觸發(fā)器(之后觸發(fā))
a、 insert觸發(fā)器
b、 update觸發(fā)器
c、 delete觸發(fā)器
2、 instead of 觸發(fā)器 (之前觸發(fā))
創(chuàng)建觸發(fā)器
# 創(chuàng)建insert類型觸發(fā)器
# 創(chuàng)建delete類型觸發(fā)器
# 創(chuàng)建update類型觸發(fā)器
# update更新列級(jí)觸發(fā)器
# instead of類型觸發(fā)器
# 創(chuàng)建instead of觸發(fā)器
# 顯示自定義消息raiserror
# 修改觸發(fā)器
# 啟用、禁用觸發(fā)器
# 查詢創(chuàng)建的觸發(fā)器信息
# 示例,驗(yàn)證插入數(shù)據(jù)
# 示例,操作日志
SQL Server 數(shù)據(jù)庫安全