<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    Sung in Blog

               一些技術(shù)文章 & 一些生活雜碎

    Struts是源代碼開(kāi)放的企業(yè)級(jí)Web應(yīng)用開(kāi)發(fā)框架,它的設(shè)計(jì)目的是從整體上減輕構(gòu)造企業(yè)Web應(yīng)用的負(fù)擔(dān)。本文通過(guò)一個(gè)Struts應(yīng)用的實(shí)例,幫助你迅速掌握Struts。

      Struts是在Jakarta項(xiàng)目下開(kāi)發(fā)的源代碼開(kāi)放軟件,由一系列的框架類、輔助類和定制的JSP標(biāo)記庫(kù)構(gòu)成,定位在基于Model 2設(shè)計(jì)模式的J2EE應(yīng)用開(kāi)發(fā)。Model 2體系是MVC(Model-View-Controller)體系的一種應(yīng)用。在MVC體系中,數(shù)據(jù)模型(Model)、表現(xiàn)邏輯(View)和控制邏輯(Controller)是分離的組件,但它們可以互相通信。Struts力圖從整體上減輕構(gòu)造企業(yè)級(jí)Web應(yīng)用的負(fù)擔(dān),并提供國(guó)際化和數(shù)據(jù)庫(kù)連接池支持。

      Struts體系可以看成兩個(gè)相對(duì)獨(dú)立的部分:第一個(gè)部分是Struts API,用于編寫支持Struts的應(yīng)用組件;第二部分是Struts的JSP標(biāo)記庫(kù),由html、bean、logic和template四個(gè)標(biāo)記組成。Struts的兩個(gè)部分有著各自不同的用戶。對(duì)于規(guī)模較小的項(xiàng)目,同一個(gè)用戶可能同時(shí)使用這兩個(gè)部分;但對(duì)于規(guī)模較大的項(xiàng)目,通常開(kāi)發(fā)者使用API組件,而負(fù)責(zé)HTML頁(yè)面布局的人使用標(biāo)記庫(kù)。

      Struts的設(shè)計(jì)目標(biāo)是為Model 2 Web應(yīng)用開(kāi)發(fā)提供一個(gè)強(qiáng)大的框架。同時(shí),Struts還包含了一些實(shí)用組件,例如Digest,但這些組件并不從屬于上面提到的兩個(gè)部分。

    Struts應(yīng)用的體系結(jié)構(gòu)

      對(duì)于從傳統(tǒng)編程環(huán)境轉(zhuǎn)入Web開(kāi)發(fā)的人來(lái)說(shuō),Web編程中令人很不習(xí)慣的一個(gè)特點(diǎn)是缺乏“程序”。傳統(tǒng)的應(yīng)用總是有主入口點(diǎn)、流程控制和出口點(diǎn)。但在Web網(wǎng)站上,用戶可能從任何地方進(jìn)入,按照一種完全隨機(jī)的次序訪問(wèn)各個(gè)頁(yè)面,甚至可能跳過(guò)多個(gè)頁(yè)面,也可能在一、兩個(gè)小時(shí)內(nèi)毫無(wú)動(dòng)靜。這是HTTP訪問(wèn)的基本特征,無(wú)論是Struts還是其他Web編程框架,都無(wú)法改變這一點(diǎn)。然而,Struts能夠隱藏Web訪問(wèn)固有的“混亂”,幫助開(kāi)發(fā)者建立起清晰和明確的秩序和規(guī)則。

      在Struts應(yīng)用中,有一個(gè)稱為ActionServlet的主調(diào)度程序(或稱為分配器),如圖1所示。不過(guò),并非所有的請(qǐng)求都必須通過(guò)ActionServlet。用戶的請(qǐng)求目標(biāo)可以是非Struts的頁(yè)面,也可以是那些使用了Struts標(biāo)記庫(kù)但不使用Struts請(qǐng)求分配服務(wù)的頁(yè)面。這正是Struts體系的優(yōu)點(diǎn)之一:按需使用。許多編程框架要求你要么不用,要么全部使用,而且一旦你決定使用,以后要悔改從前的錯(cuò)誤就會(huì)付出高昂的代價(jià)。Struts按需使用的優(yōu)點(diǎn)與這類系統(tǒng)形成了強(qiáng)烈對(duì)比。

      

      圖1 Struts框架中的請(qǐng)求處理

      Struts應(yīng)用由下面這些基本模塊構(gòu)成:

      1.配置信息;

      2.Servlet,主要是Struts的ActionServlet;

      3.動(dòng)作類(Action),執(zhí)行邏輯和控制(請(qǐng)求分配)功能,它們由ActionServlet調(diào)用;

      4.JSP頁(yè)面(屬于View),常常通過(guò)動(dòng)作類分派;

      5.JSP標(biāo)記庫(kù),根據(jù)需要使用;

      6.各種形式的JavaBean,包括用戶定義的JavaBean。

      典型的Struts應(yīng)用要用到三種配置文件:web.xml、struts-config.xml和可選的應(yīng)用資源文件。

      web.xml是Web應(yīng)用的標(biāo)準(zhǔn)配置文件,是所有J2EE Web應(yīng)用必需的組成部分。應(yīng)用服務(wù)器通過(guò)該配置文件把URL映射到Servlet和JSP,通過(guò)該配置文件為Servlet和JSP指定啟動(dòng)參數(shù)。為Struts應(yīng)用提供的基本web.xml文件很簡(jiǎn)單,真正必需的只有一個(gè)主ActionServlet定義,以及一個(gè)確保Struts請(qǐng)求傳遞到ActionServlet的映射。按照慣例,以“.do”結(jié)尾的URL都是Struts請(qǐng)求,例如/login.do。應(yīng)用服務(wù)器利用web.xml文件中的映射,把該請(qǐng)求傳遞給ActionServlet。接著,ActionServlet決定如何分配該請(qǐng)求。ActionServlet的決定依據(jù)是struts-config.xml中定義的規(guī)則,和/或是通過(guò)ActionServlet派生類額外定義的分配邏輯。

      struts-config.xml稱為Struts配置文件。Struts應(yīng)用是一個(gè)依靠struts-config.xml文件把組件連接起來(lái)的網(wǎng)絡(luò)。struts-config.xml文件為Web應(yīng)用的組件定義了邏輯名稱,也定義了它們?cè)赟truts框架下的屬性和關(guān)系,就像web.xml文件在Web應(yīng)用框架之內(nèi)定義組件一樣。struts-config.xml文件包含了與Struts框架有關(guān)的應(yīng)用信息,這些信息分四個(gè)類:

      1.數(shù)據(jù)源信息,它是可選的。在這里可以指定一個(gè)或者多個(gè)JDBC數(shù)據(jù)源,使得數(shù)據(jù)庫(kù)定義信息集中化。對(duì)于數(shù)據(jù)庫(kù)訪問(wèn),Struts還有一個(gè)額外的優(yōu)點(diǎn),即支持基本的數(shù)據(jù)庫(kù)連接池功能。

      2. Form Bean是JavaBean的一種特殊類型,它簡(jiǎn)化了Web表單的處理。

      3. Global Forwards是全局性的轉(zhuǎn)發(fā)定義信息。Struts動(dòng)作按照一種“請(qǐng)求—轉(zhuǎn)發(fā)”機(jī)制運(yùn)行。為了最大限度地分  離動(dòng)作模塊與轉(zhuǎn)發(fā)目標(biāo),這里使用了一種映射機(jī)制,允許通過(guò)同義詞引用轉(zhuǎn)發(fā)目標(biāo)。一些目標(biāo)頁(yè)面可能被多個(gè)動(dòng)作類引用,例如登錄頁(yè)面,因此可以在全局轉(zhuǎn)發(fā)定義部分把邏輯目標(biāo)頁(yè)面映射到物理目標(biāo)頁(yè)面,避免把這部分信息加入到動(dòng)作定義部分。

      4. Actions定義了Struts應(yīng)用體系的請(qǐng)求分配信息,它們是核心分配器的補(bǔ)充定義,負(fù)責(zé)處理各種具體的請(qǐng)求類型。

    一個(gè)簡(jiǎn)單的應(yīng)用

      基于Struts的Web應(yīng)用和普通Web應(yīng)用有著許多同樣的要求,但Struts應(yīng)用也有自己特殊的需求。一個(gè)可部署的Web應(yīng)用應(yīng)該可組織和構(gòu)成一個(gè)WAR文件。WAR文件是帶有圖2所示目錄結(jié)構(gòu)的JAR包。對(duì)于Struts Web應(yīng)用來(lái)說(shuō),Web-INF目錄下還要加上一些額外的文件,例如struts-confg.xml文件和標(biāo)記庫(kù)描述器(TLD)文件。注意:應(yīng)用的資源應(yīng)該放入應(yīng)用的類路徑下,也就是Web-INF/lib目錄或Web-INF/class目錄下的JAR包內(nèi)。對(duì)于大多數(shù)簡(jiǎn)單的Struts頁(yè)面,我們只用到Struts標(biāo)記庫(kù),而按照MVC的術(shù)語(yǔ)就不需要涉及Model和Controller部分,只涉及View。請(qǐng)看圖3所示的主頁(yè)例子。雖然這個(gè)頁(yè)面沒(méi)有表單,但Struts仍能夠在設(shè)計(jì)這類頁(yè)面時(shí)提供幫助。

      圖2 Struts應(yīng)用的目錄結(jié)構(gòu)

      圖3 一個(gè)簡(jiǎn)單的View

      要管理會(huì)話,最簡(jiǎn)單的途徑是使用Cookie。會(huì)話標(biāo)識(shí)符被傳遞到客戶端之后,客戶端把它保存到Cookie,以后的每次請(qǐng)求就把Cookie發(fā)送到服務(wù)器。然而,和其他的許多Web解決方案一樣,Cookie方案也不是萬(wàn)能的,因?yàn)橐恍┯脩艨赡懿恍湃蜟ookie,關(guān)閉瀏覽器的Cookie支持。由于這種情況,URL改寫技術(shù)就出現(xiàn)了。使用URL改寫技術(shù)時(shí),整個(gè)網(wǎng)站的所有URL后面都將加上會(huì)話標(biāo)識(shí)符。雖然這個(gè)方案不像采用Cookie方案那樣簡(jiǎn)單、穩(wěn)固,但它確實(shí)行得通。URL改寫技術(shù)的不穩(wěn)固是有兩方面的原因。首先,和Cookie不同,URL沒(méi)有過(guò)期時(shí)間,如果一個(gè)帶有會(huì)話標(biāo)識(shí)的URL被截取后又重新在以后的訪問(wèn)中使用,那么這種URL不會(huì)很有用,因?yàn)闀?huì)話一般在一定的時(shí)間后會(huì)被作廢。其次,如果有一個(gè)URL鏈接的后面沒(méi)有帶上會(huì)話標(biāo)識(shí)符,整個(gè)鏈都會(huì)中斷,客戶程序無(wú)法再次獲取會(huì)話標(biāo)識(shí)符,除非它備份了帶有會(huì)話標(biāo)識(shí)符的URL訪問(wèn)歷史。

      Servlet能夠只通過(guò)一次方法調(diào)用完成URL改寫。從技術(shù)上講,JSP也一樣能夠辦到這一點(diǎn),但一個(gè)好的JSP頁(yè)面應(yīng)該不包含Java代碼,或包含盡量少的Java代碼。為此,Struts提供了一個(gè)鏈接標(biāo)記。本例使用了該標(biāo)記來(lái)維持客戶端和服務(wù)器之間的會(huì)話狀態(tài)信息。

    綁定View、Model和Controller

      前面的簡(jiǎn)單頁(yè)面不需要Struts分配器,因?yàn)樗挥泻?jiǎn)單的鏈接。圖4顯示了一個(gè)比較復(fù)雜的“類別”頁(yè)面。它列舉出了數(shù)據(jù)庫(kù)中的類別條目,并將這些條目分別鏈接到對(duì)應(yīng)的編輯頁(yè)面。為顯示這個(gè)頁(yè)面,我們就要用到Struts的ActionServlet分配機(jī)制。

      圖4 類別頁(yè)面

      在web.xml文件中,放入一項(xiàng)表示所有以“.do”結(jié)尾的URL請(qǐng)求必須發(fā)送給Struts分配器的聲明。這里的分配器可以是org.apache.struts.action.ActionServlet或其擴(kuò)展類。Struts分配器在啟動(dòng)時(shí)讀取struts-config.xml文件,并構(gòu)造出一個(gè)動(dòng)作映射圖。本例指定了一個(gè)名為ShowCategories的動(dòng)作類,來(lái)處理“ShowCategories”動(dòng)作。可以看出,Struts應(yīng)用的基本工作模式是:主分配器調(diào)用一個(gè)動(dòng)作分配器,動(dòng)作分配器確定或構(gòu)造出Model部分(一個(gè)JavaBean或其它Java對(duì)象),并把它提供給View(通常是一個(gè)JSP頁(yè)面)。

      本例使用Bean的情況稍微有點(diǎn)復(fù)雜,它有多個(gè)數(shù)據(jù)項(xiàng),因此我們不是使用單個(gè)提供數(shù)據(jù)的Bean,而是要生成一組Bean。遺憾的是,JSP頁(yè)面以HTML為基礎(chǔ),HTML沒(méi)有提供循環(huán)或其他控制邏輯。不過(guò),Struts的logic:iterate允許對(duì)數(shù)組進(jìn)行迭代操作,如下面的代碼片斷所示:

    <table>
    <logic:iterate id="category"
    type="com.strutsdemo.Category"
    name="<%= Constants.CATALOG_CATEGORIES %>"
    scope="application">
    <tr>
    <td>
    <html:link page="/editCategory.do"
    name="category"
    property="mapping">
    編輯
    </html:link>
    <html:link page="/removeCategory.do"
    name="category"
    property="mapping">
    刪除
    </html:link>
    <bean:write name="category"
    property="category"/>
    </td>
    </tr>
    </logic:iterate>
    </table>


      上面討論了Model 2體系的Model和View部分,下面來(lái)看看Controller部分。Struts體系有一個(gè)主控制器,即ActionServlet。ActionServlet負(fù)責(zé)選擇和調(diào)用合適的動(dòng)作控制器—即org.apache.struts.action.Action的擴(kuò)展類。動(dòng)作控制器實(shí)現(xiàn)了process()方法。process()方法分析從URL請(qǐng)求傳入的每一個(gè)參數(shù),執(zhí)行必要的業(yè)務(wù)邏輯,并返回一個(gè)指定了調(diào)用鏈中下一個(gè)鏈接的動(dòng)作(通常是View)。在本例中,我們想要從數(shù)據(jù)庫(kù)提取數(shù)據(jù),創(chuàng)建管理這些數(shù)據(jù)的JavaBean,把多個(gè)JavaBean整理成一個(gè)數(shù)組,再把數(shù)組保存到請(qǐng)求的上下文,從而使得作為View的JSP頁(yè)面能夠方便地進(jìn)行頁(yè)面布局。

    為保證上述操作順利進(jìn)行,在struts-config.xml文件中加入聲明,指定由哪一個(gè)動(dòng)作處理器來(lái)處理指定的動(dòng)作:

    <action path="/showCategories"
    scope="request"
    type="com.strutsdemo.ShowCategoriesAction"
    unknown="false"
    validate="false">
    <forward name="viewCategories" path="/
    ShowCategories.jsp"/>
    </action>

    表單處理

      表單處理過(guò)程充分體現(xiàn)出Struts的優(yōu)勢(shì)。在Web應(yīng)用中,大部分復(fù)雜的HTML處理任務(wù)都涉及到表單。表單編輯過(guò)程具有類似圖5所示的請(qǐng)求或應(yīng)答結(jié)構(gòu)。更新操作的過(guò)程與創(chuàng)建操作的過(guò)程相似,但對(duì)于更新操作來(lái)說(shuō),“創(chuàng)建Model”這一步驟變成“裝入Model”,而“保存Model”變成了“更新Model”。請(qǐng)注意Web應(yīng)用的特點(diǎn):操作過(guò)程隨時(shí)可能中止,這既可能是因?yàn)橛脩敉ㄟ^(guò)顯式的動(dòng)作取消了當(dāng)前的操作,也可能是因?yàn)橛脩魶](méi)有提交表單,例如用戶跳轉(zhuǎn)到了一個(gè)不是用來(lái)處理當(dāng)前表單的URL。

      

      圖5 表單處理流程

      表單編輯過(guò)程分三個(gè)階段:這里分別稱之為準(zhǔn)備(Preparation)、表現(xiàn)(Presentation)和存儲(chǔ)(Preservation)。準(zhǔn)備和存儲(chǔ)階段都屬于Struts動(dòng)作,而表現(xiàn)階段主要是客戶端的活動(dòng)。表1顯示了該過(guò)程中涉及的各種部件:

      表單Bean(Form Bean)是一種特殊的JavaBean類型,它簡(jiǎn)化了表單處理。Form Bean從org.apache.struts. action.ActionForm類擴(kuò)展而來(lái)。Form Bean有幾個(gè)有用的特點(diǎn),例如,通過(guò)reset()方法可以把Bean的屬性設(shè)置成默認(rèn)值,通過(guò)validate()方法讓Bean驗(yàn)證屬性的合法性。更重要的是,ActionServlet確保Form Bean被創(chuàng)建且可供它的動(dòng)作方法調(diào)用。HTML標(biāo)記庫(kù)還能夠確保Form Bean被正確地初始化并從Form View獲取數(shù)據(jù)。

      Form Bean應(yīng)當(dāng)屬于Model部分,然而,由于它有validate()方法,因此從某些特征來(lái)看它更接近分配器。不過(guò),不必太在乎這些概念上的問(wèn)題。Model 2并不完全等同于MVC,而且一些人已經(jīng)在責(zé)難MVC不外乎是幾種簡(jiǎn)單設(shè)計(jì)模式的混合物。不管怎樣,從應(yīng)用實(shí)踐的角度來(lái)講,系統(tǒng)的穩(wěn)定性遠(yuǎn)比概念的嚴(yán)格性更重要。在本例中,這個(gè)問(wèn)題更加富有代表性,因?yàn)槲覀儼殉志没瘷C(jī)制也包裝到Form Bean里面。從技術(shù)上看,Bean數(shù)據(jù)的持久化副本就是一個(gè)View,因此,從這個(gè)意義上來(lái)講,我們現(xiàn)在有了一個(gè)結(jié)合了分配器和View特點(diǎn)的Model。這種設(shè)計(jì)方式看起來(lái)似乎否定了引入Struts之類框架的理由,但實(shí)際上,這種設(shè)計(jì)方式兩方面的特點(diǎn)彌補(bǔ)了許多遺憾。

      首先,由于驗(yàn)證代碼和SQL代碼在很大程度上依賴于Form Bean擁有的屬性,所以把它們作為一個(gè)單元管理會(huì)帶來(lái)很大的方便。由于這里只對(duì)Form Bean的屬性感興趣,“重量級(jí)”的分配器和View部件都得到了有效的隔離。其次,F(xiàn)orm Bean與HTML標(biāo)記庫(kù)一起使用時(shí),F(xiàn)orm Bean可以包含其他對(duì)象。這些對(duì)象可以通過(guò)“.”符號(hào)應(yīng)用。使用預(yù)定義的Java對(duì)象時(shí),“.”引用方式能夠帶來(lái)很大的方便,因?yàn)镴ava不支持多重繼承。“.”引用方式避免了手工編寫大量get/set代碼的繁雜工作。

      當(dāng)內(nèi)部對(duì)象是EJB時(shí),“.”引用方式帶來(lái)的方便更加突出,因?yàn)樵贘SP頁(yè)面中引用EJB時(shí),EJB往往顯得很“笨重”。如果EJB嵌入到了Form Bean里面,許多這方面的遺憾就不再存在。更重要的是,它分離了Controller和Model,而且View持久化也簡(jiǎn)縮到了最簡(jiǎn)單的程度,因?yàn)镋JB容器可以處理所有持久化方面的細(xì)節(jié)。這樣,F(xiàn)orm Bean就幾乎成了一個(gè)純粹的分配器,一切都變得整潔和清晰。

      如果EJB有大量的屬性,而且按照ActionServlet通常對(duì)Form Bean所做的那樣,按照每個(gè)屬性分別更新的方式進(jìn)行更新,就會(huì)出現(xiàn)大量的RMI調(diào)用開(kāi)銷。對(duì)于要求較高的應(yīng)用,更好的選擇是利用EJB 2.0本地接口,或者在EJB之前加上一個(gè)傳統(tǒng)的JavaBean(通常是會(huì)話EJB),并把該Bean傳遞給實(shí)體Bean的UpdateAllProperties()業(yè)務(wù)方法。后面這種方案允許在單個(gè)RMI調(diào)用中完成所有的更新操作。

    準(zhǔn)備階段

      一次典型的編輯會(huì)話要求有一個(gè)動(dòng)作處理器準(zhǔn)備View,即一個(gè)作為View的JSP頁(yè)面,還要求有第二個(gè)動(dòng)作處理器存儲(chǔ)更新后的View。當(dāng)然,存儲(chǔ)操作之后會(huì)有第二個(gè)屬于View的頁(yè)面被顯示,例如一個(gè)“數(shù)據(jù)已經(jīng)更新,點(diǎn)擊此處繼續(xù)”的頁(yè)面(參見(jiàn)表1)。

       表1:基于Form Bean的編輯過(guò)程要用到的部件

    部件             說(shuō)明
    CatalogForm        Form Bean
    EditCategoryAction    準(zhǔn)備階段
    EditCategory.jsp     編輯
    SaveCategoryAction    存儲(chǔ)階段
    EditDone.jsp       確認(rèn)數(shù)據(jù)已經(jīng)保存
    EditFailed.jsp      “數(shù)據(jù)沒(méi)有保存”錯(cuò)誤


      下面的代碼片斷顯示了如何在struts-config.xml文件中配置準(zhǔn)備階段:

    <action path="/editCategory"
    scope="request"
    name="catForm"
    type="com.strutsdemo.EditCategoryAction"
    unknown="false"
    validate="false">
    <forward name="success"
    path="/EditCategory.jsp"/>
    </action>


      在準(zhǔn)備階段,容器嘗試從Session或Request找出指定的Form Bean,這是因?yàn)樵趧?dòng)作中指定了“name=...”。ActionServlet在struts-config.xml文件的區(qū)域?qū)ふ褾orm Bean的別名,利用Form Bean的別名尋找對(duì)應(yīng)的Java類。如果用戶的請(qǐng)求帶有參數(shù),其名字匹配Form Bean屬性名字的參數(shù)將被設(shè)置為屬性值。Struts擴(kuò)展了“屬性名字”的含義,使得訪問(wèn)Form Bean內(nèi)嵌對(duì)象的屬性成為可能。本文的例子也用到了Struts的這一優(yōu)點(diǎn)。

      準(zhǔn)備好Form Bean之后,ActionServlet接著調(diào)用動(dòng)作的process()方法,F(xiàn)orm Bean作為參數(shù)之一傳入process()方法。在這里,我們對(duì)Form Bean的屬性作最后的調(diào)整,調(diào)用業(yè)務(wù)方法,委派作為View的EditCategory,從而生成一個(gè)以Form Bean中合適數(shù)據(jù)為基礎(chǔ)的HTML頁(yè)面。這個(gè)頁(yè)面被傳遞給客戶端,接下來(lái)就進(jìn)入了“表現(xiàn)”階段。

    表現(xiàn)階段

      這一階段用戶編輯表單并提交。如果服務(wù)器端的應(yīng)用認(rèn)為用戶提交的內(nèi)容存在問(wèn)題,它把表單再次顯示給用戶,加上適當(dāng)?shù)奶崾拘畔ⅲ恢貜?fù)該過(guò)程,直至用戶提交了合法的表單,或取消了表單處理過(guò)程。編輯過(guò)程的中止可能是由于用戶跳轉(zhuǎn)到了其他頁(yè)面,或者啟動(dòng)了一個(gè)取消動(dòng)作(例如點(diǎn)擊了一個(gè)由html:cancel標(biāo)記定義的按鈕)。雖然在理論上,View的驗(yàn)證和再次顯示操作應(yīng)該屬于表現(xiàn)階段,但在Struts應(yīng)用中,這部分功能在存儲(chǔ)階段實(shí)現(xiàn)最方便。

    存儲(chǔ)階段

      準(zhǔn)備階段創(chuàng)建了一個(gè)帶有“name=”屬性定義的動(dòng)作CatForm,存儲(chǔ)階段要加入另外兩個(gè)屬性,即:“validate=‘true’”和“input=”屬性。

    <action path="/saveCategory"
    scope="request"
    name="catForm"
    type="com.strutsdemo.SaveCategoryAction"
    unknown="false"
    input="/EditCategory1.jsp"
    validate="true">
    <forward name="success"
    path="/CategoryUpdated.jsp"/>
    </action>


      設(shè)置了“validate=‘true’”屬性選項(xiàng)之后,服務(wù)器端就會(huì)增加一個(gè)處理步驟。重新用來(lái)自View的數(shù)據(jù)構(gòu)造出Form Bean,或更新From Bean的時(shí)候,F(xiàn)orm Bean的validate()方法會(huì)被調(diào)用。validate()方法執(zhí)行必要的合法性驗(yàn)證操作。如果用戶的輸入數(shù)據(jù)中存在錯(cuò)誤,validate()方法就創(chuàng)建一個(gè)或多個(gè)ActionError對(duì)象。這些ActionError對(duì)象包含了錯(cuò)誤信息源ID和表單輸入域的名稱。這些ActionError對(duì)象被收集和整理到一個(gè)ActionErrors對(duì)象,隨后ActionErrors對(duì)象由validate()方法返回。如果用戶輸入的數(shù)據(jù)不包含錯(cuò)誤,validate()返回null。

      由于指定了“input=”屬性,一旦出現(xiàn)了錯(cuò)誤,動(dòng)作會(huì)被忽略,而“input=”指定的View被顯示。這個(gè)View既包含F(xiàn)orm Bean,也包含當(dāng)前出現(xiàn)的錯(cuò)誤對(duì)象集合。一般地,這個(gè)輸入頁(yè)面就是原來(lái)執(zhí)行編輯功能的JSP頁(yè)面。

      大多數(shù)Struts的html標(biāo)記有對(duì)應(yīng)的HTML標(biāo)記,但Struts有一個(gè)HTML沒(méi)有的標(biāo)記,即標(biāo)記。要中止表單編輯過(guò)程,用戶既可以手工輸入U(xiǎn)RL,也可以點(diǎn)擊不指向存儲(chǔ)動(dòng)作處理器的鏈接。因此,用標(biāo)記定義的“取消”按鈕,不是取消編輯操作的唯一方法。

      假設(shè)validate()方法沒(méi)有發(fā)現(xiàn)任何錯(cuò)誤,且用戶沒(méi)有點(diǎn)擊“取消”按鈕,存儲(chǔ)動(dòng)作的process()方法將被調(diào)用。在本例的process()方法中,我們調(diào)用了Form Bean的save()方法把數(shù)據(jù)寫入持久性存儲(chǔ)設(shè)備,然后根據(jù)寫入操作是否成功,顯示“存儲(chǔ)操作成功”或“存儲(chǔ)操作失敗”的View。

    構(gòu)造和運(yùn)行Struts應(yīng)用

      要構(gòu)造和運(yùn)行本文的示例應(yīng)用,你必須了解如何使用Jakarta的Ant工具。如果你還不了解Ant,現(xiàn)在該是學(xué)習(xí)它的時(shí)候了!趕緊到網(wǎng)站下載Ant,通常要解開(kāi)壓縮,設(shè)置一下ANT_HOME環(huán)境變量,然后把Ant加入到執(zhí)行路徑就可以了。

    本文示例的build.xml需要稍微定制一下,修改指示本地Tomcat位置的配置,使它能夠找到在Tomcat下編譯所必需的類。另外,你還要有一份Struts的JAR。你可以去下載最新的版本。

      struts-config.xml文件是粘合Struts應(yīng)用各個(gè)部分的配置文件。在部署完成后的Web應(yīng)用中,struts-config.xml在Web-INF目錄下。你應(yīng)該修改一下數(shù)據(jù)源配置,使之符合你當(dāng)前使用的DBMS環(huán)境。數(shù)據(jù)模型和SQL模式文件在下載包的DBMS目錄下,SQL文件針對(duì)PostgreSQL DBMS編寫。

      示例中src/com/strutsdemo/ShowCategoriesAction. java是一個(gè)簡(jiǎn)單的分配器。ActionForward()是請(qǐng)求分配方法,從ActionServlet調(diào)用。該方法可以完成主要的工作,例如分析請(qǐng)求參數(shù)、執(zhí)行計(jì)算,以及構(gòu)造出View使用的JavaBean。另外,該方法還要根據(jù)處理結(jié)果,確定下一個(gè)要顯示的是什么頁(yè)面:可能是預(yù)設(shè)的多個(gè)頁(yè)面之一,也可能是一個(gè)錯(cuò)誤信息頁(yè)面。

    ActionForward()的請(qǐng)求分配過(guò)程

      當(dāng)然,最復(fù)雜的處理過(guò)程與表單有關(guān)。ActionForward方法的請(qǐng)求分配過(guò)程是:

      1. ActionServlet,對(duì)請(qǐng)求進(jìn)行解碼。由于為動(dòng)作指定了Form Bean,ActionServlet處理Form Bean(參見(jiàn)下面有關(guān)“ActionServlet如何使用Form Bean”的說(shuō)明)。然后,請(qǐng)求傳遞給了EditCategoryAction。

      2. EditCategoryAction;準(zhǔn)備處理View,或者從數(shù)據(jù)庫(kù)裝入現(xiàn)有數(shù)據(jù),或者創(chuàng)建新的數(shù)據(jù)項(xiàng)。動(dòng)作處理器利用Mapping.findForward把控制傳遞給EditCategory.jsp。

      3. DitCategory.jsp,顯示出Form Bean,允許用戶編輯數(shù)據(jù)。用戶提交數(shù)據(jù)后,控制轉(zhuǎn)到ActionServlet。

      4. ActionServlet,對(duì)請(qǐng)求進(jìn)行解碼。這一次,F(xiàn)orm Bean將從View的數(shù)據(jù)初始化,因?yàn)樗且粋€(gè)Struts的JSP表單頁(yè)面。由于有Form Bean,且struts-config.xml中指定了“validate=‘true’”,名為“catForm”的Form Bean的validate()方法被調(diào)用。如果用戶提交的數(shù)據(jù)未能通過(guò)合法性驗(yàn)證,則控制轉(zhuǎn)到EditCategory1.jsp。

      5. EditCategory1.jsp,它只是EditCategory.jsp略加修改后的一個(gè)版本。如果有必要,原始編輯頁(yè)面和帶有錯(cuò)誤提示的編輯頁(yè)面可以使用同一個(gè)View。Struts的JSP標(biāo)記能夠幫助我們輕松地辦到這一點(diǎn)。該頁(yè)面提交給/saveCategory.do。這樣,用戶就在這幾個(gè)頁(yè)面之間繞圈子,直到他跳轉(zhuǎn)到一個(gè)與編輯操作無(wú)關(guān)的頁(yè)面,或者他提交的數(shù)據(jù)通過(guò)了合法性驗(yàn)證。

      6. 如果Form Bean合法性驗(yàn)證通過(guò),ActionServlet把請(qǐng)求(包括Form Bean)傳遞給SaveCategoryAction。在這個(gè)例子中,“save”可能意味著創(chuàng)建操作,也可能意味著更新操作,具體由URL提供的選項(xiàng)決定。寫入數(shù)據(jù)的操作通過(guò)調(diào)用Form Bean的store()方法完成。注意:實(shí)際的應(yīng)用應(yīng)當(dāng)使用某種類型的事務(wù)管理機(jī)制(或使用EJB,因?yàn)镋JB有內(nèi)建的事務(wù)管理機(jī)制),以避免并發(fā)訪問(wèn)帶來(lái)的問(wèn)題。

    ActionServlet如何使用Form Bean

      涉及Form Bean的ActionServlet處理過(guò)程包含六個(gè)步驟:

      1. 找到或創(chuàng)建Form Bean;

      2. 據(jù)從HTTP請(qǐng)求傳入的相應(yīng)數(shù)據(jù),更新Form Bean的各個(gè)屬性;

      3. 檢查用戶是否點(diǎn)擊了“取消”按鈕。如是,跳過(guò)步驟4和步驟5;

      4. 驗(yàn)證Form Bean數(shù)據(jù)的合法性;

      5. 如數(shù)據(jù)未能通過(guò)合法性驗(yàn)證,發(fā)送“input=”參數(shù)中指定的View;

      6. 否則,把Form Bean傳遞給動(dòng)作處理器。

    posted on 2005-09-09 14:00 Sung 閱讀(364) 評(píng)論(1)  編輯  收藏 所屬分類: Struts

    FeedBack:
    # re: 一個(gè)掌握Struts企業(yè)級(jí)Web開(kāi)發(fā)框架的實(shí)例
    2005-10-24 22:09 | Sung
    DynaForms比靜態(tài)Form有更大的優(yōu)勢(shì)  回復(fù)  更多評(píng)論
      
    主站蜘蛛池模板: 国产精品美女久久久免费| 亚洲国产成人精品无码区在线观看 | 国产精品美女自在线观看免费| 亚洲精品无码专区在线| 亚洲AV综合色区无码另类小说| 最近2019年免费中文字幕高清| 亚洲 自拍 另类小说综合图区| 4444亚洲国产成人精品| 亚洲欧洲自拍拍偷精品 美利坚 | 亚洲一区二区三区免费观看| 精品国产呦系列在线观看免费 | 亚州免费一级毛片| 国产成人无码区免费内射一片色欲 | 亚洲色偷偷av男人的天堂| 国产三级在线观看免费| 黄色a三级免费看| 亚洲人成色在线观看| 亚洲日韩精品无码专区网址| 国产婷婷高清在线观看免费| 精品免费视在线观看| 久久精品免费大片国产大片| 羞羞视频在线观看免费| 亚洲欧洲在线观看| 亚洲国产日韩在线观频| 国产精品色午夜视频免费看| 天天看免费高清影视| 中文精品人人永久免费| 2022国内精品免费福利视频| 亚洲av永久无码精品三区在线4| 亚洲A丁香五香天堂网| 免费a级黄色毛片| 亚洲国产日韩在线观频| 久久影视国产亚洲| 国产亚洲精品影视在线产品| 精品亚洲视频在线观看| 亚洲欭美日韩颜射在线二| 国产亚洲一区二区三区在线不卡| 成人片黄网站A毛片免费| 夭天干天天做天天免费看| 日本免费一区二区三区最新| 哒哒哒免费视频观看在线www|