空間站

          北極心空

            BlogJava :: 首頁(yè) :: 聯(lián)系 :: 聚合  :: 管理
            15 Posts :: 393 Stories :: 160 Comments :: 0 Trackbacks

          Struts framework 的工作原理和組件

          對(duì)于 Struts 如何控制、處理客戶(hù)請(qǐng)求,讓我們通過(guò)對(duì) struts 的四個(gè)核心組件介紹來(lái)具體說(shuō)明。這幾個(gè)組件就是: ActionServlet Action Classes Action Mapping (此處包括 ActionForward ), ActionFrom Bean

          Struts ActionServlet 控制器對(duì)象

          ?????? ActionServlet 繼承自 javax.servlet.http.HttpServlet 類(lèi) 其在 Struts framework 中扮演的角色是中心控制器。 它提供一個(gè)中心位置來(lái)處理全部的終端請(qǐng)求。 控制器 ActionServlet 主要負(fù)責(zé)將 HTTP 的客戶(hù)請(qǐng)求信息組裝后,根據(jù)配置文件的指定描述,轉(zhuǎn)發(fā)到適當(dāng)?shù)奶幚砥鳌?/span>

          ?????? 按照 Servelt 的標(biāo)準(zhǔn) 所有得 Servlet 必須在 web 配置文件 web.xml 聲明。同樣 ActoinServlet 必須在 Web Application 配置文件 web.xml 中描述 有關(guān)配置信息如下。

          <servlet>

          <servlet-name>action</servlet-name>

          <servlet-class>org.apache.struts.action.ActionServlet</servlet-class>

          </servlet>

          全部的請(qǐng)求 URI *.do 的模式存在并映射到這個(gè) servlet 其配置如下

          <servlet-mapping>

          <servlet-name>action</servlet-name>

          <url-pattern>*.do</url-pattern>

          </servlet-mapping>

          一個(gè)該模式的請(qǐng)求 URI 符合如下格式:

          ????????????? http://www.my_site_name.com/mycontext/actionName.do

          ?

          中心控制器為所有的表示層請(qǐng)求提供了一個(gè)集中的訪(fǎng)問(wèn)點(diǎn)。這個(gè)控制器提供的抽象概念減輕了開(kāi)發(fā)者建立公共應(yīng)用系統(tǒng)服務(wù)的困難,如管理視圖、會(huì)話(huà)及表單數(shù)據(jù)。它也提供一個(gè)通用機(jī)制如錯(cuò)誤及異常處理,導(dǎo)航,國(guó)際化,數(shù)據(jù)驗(yàn)證,數(shù)據(jù)轉(zhuǎn)換等。

          ?

          當(dāng)用戶(hù)向服務(wù)器端提交請(qǐng)求的時(shí)候,實(shí)際上信息是首先發(fā)送到控制器 ActionServlet ,一旦控制器獲得了請(qǐng)求,其就會(huì)將請(qǐng)求信息傳交給一些輔助類(lèi)( help classes )處理。這些輔助類(lèi)知道如何去處理與請(qǐng)求信息所對(duì)應(yīng)的業(yè)務(wù)操作。在 Struts 中,這個(gè)輔助類(lèi)就是 org.apache.struts.action.Action 。通常開(kāi)發(fā)者需要自己繼承 Aciton 類(lèi),從而實(shí)現(xiàn)自己的 Action 實(shí)例。

          Struts Action Classes

          ?????? ActionServlet 全部提交的請(qǐng)求都被控制器委托到 RequestProcessor 對(duì)象。 RequestProcessor 使用 struts-config.xml 文件檢查請(qǐng)求 URI 找到動(dòng)作 Action 標(biāo)示符。

          一個(gè) Action 類(lèi)的角色,就像客戶(hù)請(qǐng)求動(dòng)作和業(yè)務(wù)邏輯處理之間的一個(gè)適配器( Adaptor ),其功能就是將請(qǐng)求與業(yè)務(wù)邏輯分開(kāi)。這樣的分離,使得客戶(hù)請(qǐng)求和 Action 類(lèi)之間可以有多個(gè)點(diǎn)對(duì)點(diǎn)的映射。而且 Action 類(lèi)通常還提供了其它的輔助功能,比如:認(rèn)證( authorization )、日志( logging )和數(shù)據(jù)驗(yàn)證( validation )。

          public ActionForward execute(ActionMapping ? mapping,

          ???????????????????????????? ActionForm ? form,

          ????? ???????????????????????javax.servlet.ServletRequest ? request,

          ???????????????????????????? javax.servlet.ServletResponse ? response)

          ????????????????????? throws java.io.IOException,javax.servlet.ServletException

          ?

          ?????? Action 最為常用的是 execute ()方法。(注意,以前的 perform 方法在 struts1.1 中已經(jīng)不再支持),還有一個(gè) execute ()方法,請(qǐng)參考 apidoc ,在此不在說(shuō)明。

          ?????? 當(dāng) Controller 收到客戶(hù)的請(qǐng)求的時(shí)候,在將請(qǐng)求轉(zhuǎn)移到一個(gè) Action 實(shí)例時(shí),如果這個(gè)實(shí)例不存在,控制器會(huì)首先創(chuàng)建,然后會(huì)調(diào)用這個(gè) Action 實(shí)例的 execute ()方法。 Struts Framework 為應(yīng)用系統(tǒng)中的每一個(gè) Action 類(lèi)只創(chuàng)建一個(gè)實(shí)例。因?yàn)樗械挠脩?hù)都使用這一個(gè)實(shí)例,所以你必須確定你的 Action 類(lèi)運(yùn)行在一個(gè)多線(xiàn)程的環(huán)境中。下圖顯示了一個(gè) execute ()方法如何被訪(fǎng)問(wèn):

          Action 實(shí)例的 execute() 方法

          ??????

          注意,客戶(hù)自己繼承的 Action 子類(lèi),必須重寫(xiě) execute ()方法,因?yàn)?/span> Action 類(lèi)在默認(rèn)情況下是返回 null 的。

          Struts Action Mapping

          上面講到了一個(gè)客戶(hù)請(qǐng)求是如何被控制器轉(zhuǎn)發(fā)和處理的,但是,控制器如何知道什么樣的信息轉(zhuǎn)發(fā)到什么樣的 Action 類(lèi)呢?這就需要一些與動(dòng)作和請(qǐng)求信息相對(duì)應(yīng)的映射配置說(shuō)明。在 struts 中,這些配置映射信息是存儲(chǔ)在特定的 XML 文件(比如 struts-config.xml )。 ?

          這些配置信息在系統(tǒng)啟動(dòng)的時(shí)候被讀入內(nèi)存,供 struts framework 在運(yùn)行期間使用。 在內(nèi)存中,每一個(gè) <action> 元素都與 org.apache.struts.action.ActionMapping 類(lèi)的一個(gè)實(shí)例對(duì)應(yīng)。下表就顯示了一個(gè)登陸的配置映射。

          <action-mappings>

          ? <action? path="/logonAction"

          ?????????? type="com.test.LogonAction"

          ?????????? name="LogonForm"

          ?????????? scope="request"

          ?????????? input="logoncheck.jsp"

          validate="false">

          <forward name="welcome" path="/welcome.jsp"/>

          <forward name="failure" path="/logon_failure.jsp "/>

          </action>

          </action-mappings>

          ?

          ?

          <form-beans>

          ? <form-bean? name="LoginForm"

          type="com.test.LoginForm"/>

          </form-beans>

          上面的配置表示:當(dāng)可以通過(guò) /logonAction.do (此處假設(shè)配置的控制器映射為 *.do )提交請(qǐng)求信息的時(shí)候,控制器將信息委托 com.test.LogonAction 處理。調(diào)用 LogonAction 實(shí)例的 execute() 方法。同時(shí)將 Mapping 實(shí)例和所對(duì)應(yīng)的 LogonForm Bean 信息傳入。其中 name=LogonForm ,使用的 form-bean 元素所聲明的 ActionForm Bean 。有關(guān) form-bean 的申明如下顯示。

          使用 ActionForward 導(dǎo)航

          元素 <forward> 則表示了當(dāng) Action 實(shí)例的 execute() 方法運(yùn)行完畢或,控制器根據(jù) Mapping 可將響應(yīng)信息轉(zhuǎn)到適當(dāng)?shù)牡胤健H缟厦娆F(xiàn)實(shí),如果客戶(hù)登陸成功,則調(diào)用 welcome forward ,將成功信息返回到 /welcome.jsp 頁(yè)面。在你的 execute() 方法的結(jié)尾可以使用下面的實(shí)例代碼而返回 welcome forward 。當(dāng)然你的 welcome forward 必須在 action 元素屬性中定義,正如上面所聲明的那樣。

          return (mapping.findForward("welcome"));

          ?

          ?????? ActionForward 對(duì)象是配置對(duì)象。這些配置對(duì)象擁有獨(dú)一無(wú)二的標(biāo)識(shí)以允許它們按照有意義的名稱(chēng)如 “success” “failure” 等來(lái)檢索。 ActionForward 對(duì)象封裝了向前進(jìn)的 URL 路徑且被請(qǐng)求處理器用于識(shí)別目標(biāo)視圖。 ActionForward 對(duì)象建立自 <forward> 元素位于 struts-config.xml 。下面是一個(gè) Struts <forward> 元素例子,屬于 <action> 元素范圍。

          <action path="/editCustomerProfile"

          type="packageName.EditCustomerProfileAction"

          name="customerProfileForm" scope="request">

          <forward name="success" path="/MainMenu.jsp"/>

          <forward name="failure" path="/CustomerService.jsp"/>

          </action>

          ?????? 基于執(zhí)行請(qǐng)求處理器的 execute(…) 方法的結(jié)果,當(dāng)傳遞一個(gè)值匹配指定于 <forward> 元素中 name 屬性的值的時(shí)候,下一個(gè)視圖可以在 execute(…) 方法中被開(kāi)發(fā)者用方便的方法 org.apache.struts.action.ActionMapping.findForward(…) 選擇。 ActionMapping.findForward(…) 方法既從它的本地范圍又從全局范圍提供一個(gè) ActionForward 對(duì)象,該對(duì)象返回至 RequestProcessor RequestDispatcher.forward(…) response.sendRedirect(…) 調(diào)用下一個(gè)視圖。當(dāng) <forward> 元素有 redirect=“false” 屬性或 redirect 屬性不存在的時(shí)候, RequestDispatcher.forward(…) 被執(zhí)行;當(dāng) redirect=“true” 是,將調(diào)用 sendRedirect(…) 方法。下例舉例說(shuō)明了 redirect 屬性的用法:

          ?????? ? <forward name="success" path="/Catalog.jsp" redirect="true"/>

          如果 redirect=true, URL 建立如 /contextPath/path 因?yàn)?/span> HttpServletResponse.sendRedirect(…) 中解釋 URL 采用 ”/” 開(kāi)頭相對(duì)于 servlet 容器根目錄。

          如果 redirect=false, URI 建立如 /path 因?yàn)?/span> ServletContext.getRequestDisptacher(…) 采用虛擬目錄相關(guān) URL

          ?

          在此稍稍說(shuō)一下有關(guān) global-forwards 的概念。其在配置文件中描述了整個(gè)應(yīng)用系統(tǒng)可以使用的 ActionForward ,而不是僅僅是一個(gè)特定的 Action

          ? ?<global-forwards>

          ??? <forward name="logout" path="/logout.do"/>

          <forward name="error"? path="/error.jsp"/>

          ? </global-forwards>

          ?

          Struts ActionForm Bean 捕獲表單數(shù)據(jù)

          在上面講解 ActionServlet Action Classes Action Mapping 的時(shí)候,我們都提到了 ActionForm Bean 的概念。一個(gè)應(yīng)用系統(tǒng)的消息轉(zhuǎn)移(或者說(shuō)狀態(tài)轉(zhuǎn)移)的非持久性數(shù)據(jù)存儲(chǔ),是由 ActionForm Bean 的負(fù)責(zé)保持的。

          ?????? ActionForm 派生的對(duì)象用于保存請(qǐng)求對(duì)象的參數(shù),因此它們和用戶(hù)緊密聯(lián)系。

          ?????? 一個(gè) ActionForm 類(lèi)被 RequestProcessor 建立。這是發(fā)生在已完成向前進(jìn)到一個(gè) URL ,該 URL 為映射到控制器 servlet 而不是 JSP 和相應(yīng)的動(dòng)作映射指定的表單屬性的。在這個(gè)情況下,如果沒(méi)有在指定的活動(dòng)范圍內(nèi)找到, RequestProcessor 將嘗試尋找可能導(dǎo)致創(chuàng)建一個(gè)新 ActionForm 對(duì)象的表單 bean 。該 ActionForm 對(duì)象在指定的活動(dòng)范圍內(nèi)被用 <action> 元素的 name 屬性找到;

          RequestProcessor 將隨后重新安排表單屬性,用請(qǐng)求時(shí)參數(shù)填充表單,隨即調(diào)用表單對(duì)象的 validate(…) 方法以履行服務(wù)器端用戶(hù)輸入驗(yàn)證。僅當(dāng) ActionMapping 對(duì)象中 validate 屬性被設(shè)為 true 時(shí), validate(…) 方法被調(diào)用;這就是默認(rèn)的行為。 request.getParameterValues(parameterName) 被用于得到一個(gè) String[] 對(duì)象,它用來(lái)表單填充;驗(yàn)證的結(jié)果應(yīng)該是一個(gè) ActionErrors 對(duì)象,用 org.apache.struts.taglib.html.ErrorsTag 來(lái)顯示驗(yàn)證錯(cuò)誤給用戶(hù)。 ActionForm 也可以被用于為當(dāng)前用戶(hù)保存即將被一個(gè)視圖引用的中間模型狀態(tài)。

          當(dāng)一個(gè)表單對(duì)象被 RequestProcessor 找到,它被傳遞到請(qǐng)求處理器的 execute(…) 方法。一個(gè) ActionForm 對(duì)象也可以被請(qǐng)求處理器建立。表單對(duì)象建立目的是提供中間模型狀態(tài)給使用請(qǐng)求范圍 JSP ;這將確保對(duì)象不會(huì)在有效性過(guò)期后仍然存在。默認(rèn)的,所有的表單都被保存為會(huì)話(huà)范圍。會(huì)話(huà)中表單對(duì)象脫離有效性的存在可能導(dǎo)致浪費(fèi)內(nèi)存,同樣的,請(qǐng)求處理器必須跟蹤保存在會(huì)話(huà)中的表單對(duì)象的生命周期。一個(gè)好的捕獲表單數(shù)據(jù)的實(shí)踐是為橫跨多用戶(hù)交互的相關(guān)表單用一個(gè)單獨(dú)的表單 bean 。表單 bean 也可以在反饋的時(shí)候用來(lái)儲(chǔ)存能夠被自定義標(biāo)簽改變的中間模型狀態(tài)。在視圖中標(biāo)簽用法避免結(jié)合 Java 代碼,因此要成一個(gè)好的任務(wù)劃分, web 生產(chǎn)組主要處理標(biāo)志,而應(yīng)用開(kāi)發(fā)組主要處理 Java 代碼。標(biāo)簽因素退出訪(fǎng)問(wèn)中間模型狀態(tài)的邏輯;當(dāng)訪(fǎng)問(wèn)嵌套的對(duì)象或當(dāng)通過(guò)聚集列舉時(shí)這個(gè)邏輯可能很復(fù)雜。

          注意:在 struts1.1 中, ActionForm 的校驗(yàn)功能,逐漸被剝離出來(lái)(當(dāng)然依然可以使用)。使用了 validator framework 對(duì)整個(gè)應(yīng)用系統(tǒng)的表單數(shù)據(jù)驗(yàn)證進(jìn)行統(tǒng)一管理。相信信息請(qǐng)參考: http://home.earthlink.net/~dwinterfeldt

          ActionForm 的使用中, Struts 提倡使用到值對(duì)象( Value Object )。這樣將客戶(hù)或開(kāi)發(fā)人員,對(duì)數(shù)據(jù)狀態(tài)與對(duì)象狀態(tài)能夠更加清晰的理解和使用。

          對(duì)于每一個(gè)客戶(hù)請(qǐng)求, Struts framework 在處理 ActionForm 的時(shí)候,一般需要經(jīng)歷如下幾個(gè)步驟:

          (1)檢查 Action 的映射,確定 Action 中已經(jīng)配置了對(duì) ActionForm 的映射

          ?????? (2)根據(jù) name 屬性,查找 form bean 的配置信息

          ?????? (3)檢查 Action formbean 的使用范圍,確定在此范圍下,是否已經(jīng)有此 form bean 的實(shí)例。

          ?????? (4)假如當(dāng)前范圍下,已經(jīng)存在了此 form bean 的實(shí)例,而是對(duì)當(dāng)前請(qǐng)求來(lái)說(shuō),是同一種類(lèi)型的話(huà),那么就重用。

          ?????? (5)否則,就重新構(gòu)建一個(gè) form bean 的實(shí)例

          ?????? (6) form bean reset() 方法備調(diào)用

          ?????? (7)調(diào)用對(duì)應(yīng)的 setter 方法,對(duì)狀態(tài)屬性賦值

          ?????? (8)如果 validatede 的屬性北設(shè)置為 true ,那么就調(diào)用 form bean validate() 方法。

          9 )如果 validate ()方法沒(méi)有返回任何錯(cuò)誤,控制器將 ActionForm 作為參數(shù),傳給 Action 實(shí)例的 execute ()方法并執(zhí)行。

          ?

          注意:直接從 ActionFrom 類(lèi)繼承的 reset() validate() 方法,并不能實(shí)現(xiàn)什么處理功能,所以有必要自己重新覆蓋。

          Struts 的其他組件

          ?????? Struts framework 本身提供了很多可擴(kuò)展的組件或 sub framework ,方便的開(kāi)發(fā)人員在其構(gòu)架上構(gòu)建 web 層的應(yīng)用系統(tǒng)。比如 upload,collections ,logging 等等。讓我們來(lái)看看兩個(gè)比較重要的組件: validationg framework struts taglib 。有關(guān)其他組件請(qǐng)參考 Struts 用戶(hù)手冊(cè)( http://jakarta.apache.org/struts/userGuide )。

          ??????

          Validation Framework for Struts

          struts1.1 中,新增了 validation framework 。增加了對(duì) form 數(shù)據(jù)提交的驗(yàn)證。將原本需要在 ActionFrom Bean validate ()進(jìn)行的驗(yàn)證通過(guò)配置文件的描述進(jìn)行驗(yàn)證。

          有關(guān)其詳細(xì)信息,請(qǐng)參考 http://home.earthlink.net/~dwinterfeldt 。個(gè)人建議對(duì)于小型應(yīng)用系統(tǒng)可以采用這種配置方式,但是對(duì)于應(yīng)用系統(tǒng)中有大量 web 層表單應(yīng)用的系統(tǒng),并且業(yè)務(wù)需求變動(dòng)比較大的,使用 validation framework 可能會(huì)加重開(kāi)發(fā)難度、系統(tǒng)維護(hù)難度。可以借鑒 validation framework Javascript Validator Tag

          ?

          Struts TagLib

          ?????? struts 提供了一組可擴(kuò)展的自定義標(biāo)簽庫(kù)( TagLib ),可以簡(jiǎn)化創(chuàng)建用戶(hù)界面的過(guò)程。目前包括: Bean Tags HTML Tags Logic Tags Nested Tags Template Tags  這幾個(gè) Taglib 。有關(guān) Struts Taglib 的結(jié)構(gòu)和使用,可以參考前面有關(guān) Cutomer Tag Lib 的介紹,有關(guān)起詳細(xì)資料,請(qǐng)參考

          BeanUtils

          ?????? 這個(gè)組件的全稱(chēng)是 Bean Introspection Utilites 。是屬于 Jakarta Commons 項(xiàng)目組的。主要是幫助構(gòu)建 javabean 的屬性操作的( getter,setter ),已經(jīng)提供一種動(dòng)態(tài)定義和訪(fǎng)問(wèn) bean 的屬性。有關(guān)詳細(xì)信息,請(qǐng)參考。

          http://jakarta.apache.org/commons/beanutils.html

          ?????? 如果各位對(duì)這方面有很興趣,可以參考一些有關(guān) java 反射( Reflectio )方面的資料。

          Collections

          ?????? 這個(gè)組件主要是提供了一些集合或列表對(duì)象 在原有的 java collections framework 的基礎(chǔ)上進(jìn)行了擴(kuò)展。詳細(xì)資料請(qǐng)參考:

          http://jakarta.apache.org/commons/collections.html 以及

          http://cvs.apache.org/viewcvs/~checkout~/jakarta-commons/collections/STATUS.html?rev=1.13

          Digester

          ?????? 這個(gè)組件翻譯成中文的意思是 匯編 。其主要功能是根據(jù) xml 配置文件,初始化系統(tǒng)的一些 java 類(lèi)對(duì)象。 Digester 幫助你指定 XML java 對(duì)象之間映射模型,而且允許客戶(hù)話(huà)定制映射規(guī)則( rules )。詳細(xì)資料請(qǐng)參考

          http://jakarta.apache.org/commons/digester.html

          ?

          ?



          Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=323752

          posted on 2006-12-20 16:07 蘆葦 閱讀(618) 評(píng)論(0)  編輯  收藏 所屬分類(lèi): Struts
          主站蜘蛛池模板: 抚顺县| 泰宁县| 定日县| 阿尔山市| 阳朔县| 五莲县| 东乌珠穆沁旗| 醴陵市| 河西区| 永顺县| 班戈县| 富蕴县| 桦南县| 长宁区| 长汀县| 瑞金市| 齐齐哈尔市| 高唐县| 什邡市| 漳州市| 文成县| 喀喇| 夏河县| 宜川县| 资源县| 左云县| 镇巴县| 孙吴县| 大荔县| 青冈县| 大悟县| 礼泉县| 朔州市| 武义县| 独山县| 同心县| 玛曲县| 长阳| 西城区| 肃宁县| 公主岭市|