table

          對(duì)struts2的底層源碼的解讀

          此問(wèn)題網(wǎng)上很多人在討論,至今還是沒(méi)有很好的解決方案,在我對(duì)源碼進(jìn)行解讀后,現(xiàn)在已經(jīng)有個(gè)很好的解決方案,業(yè)務(wù)是用戶注冊(cè)(含復(fù)選框),用戶注冊(cè)驗(yàn)證出錯(cuò)后,錯(cuò)誤信息的要顯示在相應(yīng)控件的后面,同時(shí)要讓請(qǐng)求選中的復(fù)選框處于選中狀態(tài)。希望您往下看,說(shuō)不定會(huì)小有收獲哦!!

          步驟:

          1)開(kāi)發(fā)工具設(shè)置

             a)工程編碼utf-8

             b)文件代碼樣式javaxml

             c)文件編碼格式utf-8jsphtmljs

          2)創(chuàng)建目錄結(jié)構(gòu)

          3) 搭建struts2的環(huán)境,

          a)    導(dǎo)入jar

          參考struts2.1.8下的app下的struts2-blank-2.1.8項(xiàng)目,拷入基本的jar

          ==========================================================

          struts2-core-2.x.x.jar :Struts 2框架的核心類庫(kù)

                 xwork-2.x.x.jar :XWork類庫(kù),Struts 2在其上構(gòu)建

          ognl-2.6.x.jar :對(duì)象圖導(dǎo)航語(yǔ)言(Object Graph Navigation Language),struts2框架通過(guò)其讀寫對(duì)象的屬性

                 freemarker-2.3.x.jar :Struts 2UI標(biāo)簽的模板使用FreeMarker編寫

                 commons-fileupload-1.2.1.jarcommons-io-1.3.2.jar這兩個(gè)jar是用于文件上傳

          ===========================================================

                 b)修改web.xml配置文件、添加struts.xml文件

                 c)啟動(dòng)項(xiàng)目測(cè)試index.jsp界面輸出

          3)注冊(cè)頁(yè)面

          頁(yè)面的源碼如下:粗心了點(diǎn)沒(méi)有實(shí)現(xiàn)純國(guó)際化


          相信您已經(jīng)推斷出我的項(xiàng)目大致部署,我這里就簡(jiǎn)要描述下:

          配置文件:struts.xmlstrus-user.xml基于模塊化配置,UserAction-registerUser-validation.xml在執(zhí)行UserActionregisterUser方法時(shí)進(jìn)行校驗(yàn)

          屬性文件:有全局的國(guó)際化文件和user模塊的國(guó)際化文件

          類:UserActionUserBeanHobby

          工程目錄


          Struts.xml文件


          UserAction




          工程目錄
          Struts.xml文件
          UserAction類
          第一個(gè)問(wèn)題出現(xiàn)了,如下圖:
          說(shuō)明
          很多人都是對(duì)此很煩惱,struts2使用的默認(rèn)主題是xhtml,查看html頁(yè)面的源碼發(fā)現(xiàn),它給我們生成了表格布局,所以界面比較整齊,但在提供便利的同時(shí),也帶來(lái)些煩惱,就是錯(cuò)誤提示出現(xiàn)的位置。
          解決方案
          1)把主題設(shè)為theme=simple,自己去控制布局,
          2)struts使用freemarker模版技術(shù),為我們標(biāo)簽生成了html代碼,所以我們通過(guò)修改模版設(shè)置錯(cuò)誤信息提示的位置。
          解讀源碼了:
           
          a: <s:textfield/>這是strus2給我們提供標(biāo)簽,所以我們查看官方文檔得知struts-tags.tld在struts-core.jar文件里,每個(gè)標(biāo)簽都是一個(gè)java類,只是該類extends TagSupport,我們查看TextFieldTag類,其實(shí)有經(jīng)驗(yàn)的人都能猜的八九不離十,您肯定是的。
          查看TextFieldTag類
          發(fā)現(xiàn)它沒(méi)有doStartTag()方法,所以猜肯定在父類里定義了,查看AbstractUITag,這個(gè)類里也沒(méi)有doStartTag()方法,這個(gè)類是所有UI標(biāo)簽的父類,里面定義了標(biāo)簽的屬性
          繼續(xù)查看父類,
          該類有doStartTag()方法,
          我們查看得知,container容器注入了component組件,組件會(huì)話出html文本,所有我們需要查看著個(gè)組件的具體實(shí)現(xiàn)類,在TextFieldTag里面發(fā)現(xiàn)
          查看Component具體類TextField,
          查看注釋得知該類構(gòu)建html文本,但為什么TextField沒(méi)有繼承Component類呢?一猜就是UIBean繼承了,查看
          果然是繼承了Component,學(xué)框架思想最重要的是看別人的注釋,因?yàn)樽⑨屖莿e人思想的表達(dá),這個(gè)類負(fù)責(zé)通過(guò)模版構(gòu)建html文本,所以我們最重要的是找到模版的位置,這個(gè)我也是大概看懂,畢竟還沒(méi)達(dá)到水平,相信您已經(jīng)達(dá)到,大致意思是找這些屬性值,從而定位到ftl模版文件
          struts.ui.theme=xhtml
           
          struts.ui.templateDir=template
          struts.ui.templateSuffix=ftl

          如:<s:checkbox/> 找/template/xhtml/checkbox.ftl模版文件,類推<s:textfield/>,在strus2-core.jar下找textfield.ftl,發(fā)現(xiàn)是text.ftl,打開(kāi)我們查看:

           
          包含三個(gè)模版,controlheader.ftl又包含controlheader-core.ftl文件,該文件才是核心,
          現(xiàn)在我們要修改controlheader-core.ftl、controlfooter.ftl文件,把錯(cuò)誤信息放到controlfooter.ftl里面,我們可以有兩種方式修改:
          1) 拷貝出兩個(gè)文件,修改后再壓縮進(jìn)去(嚴(yán)重不建議!)
          2) 既然有這樣的需求,strus2團(tuán)隊(duì)肯定考慮到了,這讓我實(shí)在太佩服他們了,每個(gè)細(xì)節(jié)考慮的都是那么周到,看官方文檔
          Strus2團(tuán)隊(duì)提出了模版的加載、選擇模版目錄、選擇主題、擴(kuò)展主題。我們想讓框架加載我們的模版文件,所以我們點(diǎn)擊Template Loading鏈接查看,
           
          意思大概是,首先加載應(yīng)用程序路徑下模版文件,然后去加載classpath下的模版文件,如果需要覆蓋某模版,拷貝修改后放置應(yīng)用程序下,那樣將首先加載。本人英語(yǔ)不是太好,如有出處,請(qǐng)見(jiàn)諒!
          現(xiàn)在我們需要把兩個(gè)ftl文件放置application下,有什么格式要求嗎?
          本章里strus2團(tuán)隊(duì)還給我們提供很多建議,建議我們不要隨便更換模版引擎,如要修改ftl文件最好把源文件拷貝出來(lái)加以修改,不要自己手工重寫,以防止出錯(cuò)。
          相信也不用解釋了,格式為:/template/$theme/$template.ftl.
          所以我們只要在Web-Root下創(chuàng)建/template/xhtml文件夾,拷貝controlheader-core.ftl、controlfooter.ftl文件再加以修改。
          本人對(duì)于freemarker語(yǔ)言不是很了解,但掌握了思想,這種增增刪刪的操作還是可以應(yīng)付的,經(jīng)過(guò)幾輪修改,總于搞定了。
          ----------------------------------------------------------------------------------------------------
          第二個(gè)問(wèn)題:
          先對(duì)strus2的默認(rèn)攔截器原理說(shuō)下
          官方文檔這兩行最能表達(dá)我的意思,excludeMethods參數(shù)是設(shè)置該攔截器忽略哪些方法,下面反之。這簡(jiǎn)單原理相信您非常了解了,來(lái)看下我們這里出現(xiàn)的情況吧!
          這是最普遍的業(yè)務(wù)邏輯,
          這是strus-user.xml配置文件里的registerUser*.action配置:
          情況一:
          我們按此配置運(yùn)行,我們不填用戶名注冊(cè),結(jié)果出現(xiàn)如下情況:
          說(shuō)明:
          為什么出現(xiàn)無(wú)法顯示網(wǎng)頁(yè)呢?我們注冊(cè)首先被validate攔截器攔截后,UserAction-registerUser-validation.xml驗(yàn)證用戶名不能為空,經(jīng)過(guò)workflow攔截器,發(fā)現(xiàn)驗(yàn)證出錯(cuò)了,所以跳轉(zhuǎn)input試圖,我們input沒(méi)有配置type,默認(rèn)是dispatcher,我們這樣轉(zhuǎn)發(fā)的話,則不再被strus2的攔截器攔截,相當(dāng)于瀏覽器訪問(wèn)registerUserUI靜態(tài)資源,因?yàn)閴焊鶝](méi)有,所有tomcat容器無(wú)法訪問(wèn),則出現(xiàn)無(wú)法顯示網(wǎng)頁(yè)
          情況二:
          好的我們現(xiàn)在修改input結(jié)果的type屬性為redirect,
          我們選中兩個(gè)愛(ài)好,提交返回界面如下:
          開(kāi)始選中的被取消了,并且沒(méi)有“用戶名不能為空”的錯(cuò)誤信息。
          說(shuō)明:
          為什么會(huì)錯(cuò)誤信息沒(méi)了呢?同樣經(jīng)過(guò)validate、workflow攔截器后,跳轉(zhuǎn)input試圖,一但我們重定向,則strus2框架會(huì)為我們創(chuàng)建一個(gè)新的UserAction對(duì)象,則fieldErrors、UserBeanhobby數(shù)組都為null了,所以錯(cuò)誤信息、開(kāi)始選中的都顯示不出來(lái)了。
          情況三:
          相信您已經(jīng)有解決方案了,把input試圖的type設(shè)為chain類型,chain類型的作用是,讓該請(qǐng)求重新被攔截器攔截,好我們來(lái)修改:
          我們同樣不填用戶名,選中兩個(gè)愛(ài)好,點(diǎn)擊注冊(cè)后,發(fā)現(xiàn)如下結(jié)果:
          意思大概是:發(fā)現(xiàn)一個(gè)無(wú)限遞歸調(diào)用。
          說(shuō)明:
          怎么會(huì)出現(xiàn)這樣無(wú)限遞歸呢?哪里在遞歸調(diào)用?我們來(lái)分析一下流程,當(dāng)經(jīng)過(guò)validate、workflow攔截器后,跳轉(zhuǎn)input試圖,此時(shí)type=chain,所以我們看下設(shè)置為chain類型后,struts2到底都干了些什么?在官方文檔Action Chaining一章里講解到,
          大概意思是如果你要拷貝當(dāng)前的action屬性到當(dāng)前chain上的action,你需要應(yīng)用Chaining攔截器,該攔截器會(huì)拷貝請(qǐng)求上的parametersvalue stack傳遞到目標(biāo)action,原始的action會(huì)保存valueStack,允許目標(biāo)action訪問(wèn)前面所有action的valueStack作用域上的屬性,同樣對(duì)于chain的result結(jié)果試圖如jsp、velocity界面同樣可以訪問(wèn)這些屬性。
          =====================================================
          所以當(dāng)我們以chain方式訪問(wèn)registerUserUI.action,原先action的valueStack上的fieldErrors同樣被拷貝到當(dāng)前UserAction對(duì)象fieldErrors字段里,在經(jīng)過(guò)workflow攔截器后,又發(fā)現(xiàn)有錯(cuò)誤,同樣調(diào)用input試圖,進(jìn)而又去調(diào)用registerUserUI.action,經(jīng)過(guò)workflow攔截器后,又發(fā)現(xiàn)有錯(cuò)誤,又去調(diào)用input試圖,進(jìn)而遞歸調(diào)用。
          現(xiàn)在該怎樣解決呢?我們要做的就是,讓他調(diào)用registerUserUI.action時(shí)被workflow攔截器攔截后,不再驗(yàn)證是否有錯(cuò)誤,前面說(shuō)到過(guò)excludeMethods參數(shù),我們查看workflow攔截器
          發(fā)現(xiàn)他忽略input方法,所以我們加上這樣的配置:
          修改UserAction的registerUserUI方法為input,ok了!我們運(yùn)行同樣不填用戶名、選中兩個(gè)愛(ài)好提交,運(yùn)行結(jié)果為:
          注意:
          雖然chain方式對(duì)于完成這種業(yè)務(wù)很方便,官方提示我們謹(jǐn)慎使用,過(guò)度使用會(huì)造成程序的代碼混亂,到時(shí)還是根據(jù)業(yè)務(wù)來(lái)決定。

          posted on 2009-12-24 15:42 小卓 閱讀(2100) 評(píng)論(2)  編輯  收藏 所屬分類: otherstruts

          Feedback

          # re: 對(duì)struts2的底層源碼的解讀 2011-05-27 17:41 easy518網(wǎng)址導(dǎo)航

          http://www.easy518.com  回復(fù)  更多評(píng)論   

          # re: 對(duì)struts2的底層源碼的解讀 2012-08-13 16:50 wew

          fsdf  回復(fù)  更多評(píng)論   


          只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。


          網(wǎng)站導(dǎo)航:
           
          主站蜘蛛池模板: 辽阳县| 资阳市| 原平市| 大洼县| 祁阳县| 观塘区| 新乐市| 呼伦贝尔市| 桑日县| 弥勒县| 乌恰县| 东乡族自治县| 江都市| 九江县| 平湖市| 牙克石市| 肃宁县| 堆龙德庆县| 宽甸| 林芝县| 分宜县| 宁河县| 新宁县| 镇江市| 黄龙县| 阿鲁科尔沁旗| 武乡县| 吉隆县| 金门县| 当雄县| 安泽县| 焦作市| 泽普县| 黑山县| 安徽省| 建宁县| 北碚区| 封开县| 荥阳市| 江安县| 红河县|