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

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

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

    海鷗航際

    JAVA站
    posts - 11, comments - 53, trackbacks - 1, articles - 102

    Struts原理與實(shí)踐(1----2)

    Posted on 2005-03-23 17:44 海天一鷗 閱讀(417) 評(píng)論(0)  編輯  收藏 所屬分類: Struts專題
    一、 什么是Struts

    框架(Framework)是可重用的,半完成的應(yīng)用程序,可以用來(lái)產(chǎn)生專門的定制程序。

    您只要細(xì)心地研究真實(shí)的應(yīng)用程序,就會(huì)發(fā)現(xiàn)程序大致上由兩類性質(zhì)不同的組件組成,一類與程序要處理的具體事務(wù)密切相關(guān),我們不妨把它們叫做業(yè)務(wù)組件;另一類是應(yīng)用服務(wù)。比如說(shuō):一個(gè)稅務(wù)征管系統(tǒng)和一個(gè)圖書管理系統(tǒng)會(huì)在處理它們的業(yè)務(wù)方面存在很大的差異,這些直接處理業(yè)務(wù)的組件由于業(yè)務(wù)性質(zhì)的不同不大可能在不同的系統(tǒng)中重用,而另一些組件如決定程序流向的控制、輸入的校驗(yàn)、錯(cuò)誤處理及標(biāo)簽庫(kù)等這些只與程序相關(guān)的組件在不同的系統(tǒng)中可以很好地得到重用。人們自然會(huì)想要是把這些在不同應(yīng)用程序中有共性的一些東西抽取出來(lái),做成一個(gè)半成品程序,這樣的半成品就是所謂的程序框架,再做一個(gè)新的東西時(shí)就不必白手起家,而是可以在這個(gè)基礎(chǔ)上開始搭建。實(shí)際上,有些大型軟件企業(yè)選擇自己搭建這樣的框架。但大多數(shù)中小型軟件企業(yè)或者其他組織,沒有條件自己建立框架。

    Struts作為一個(gè)開放原代碼的應(yīng)用框架,在最近幾年得到了飛速的發(fā)展,在JSP Web應(yīng)用開發(fā)中應(yīng)用得非常廣泛,有的文獻(xiàn)上說(shuō)它已經(jīng)成為JSP Web應(yīng)用框架的事實(shí)上的標(biāo)準(zhǔn)。那么,究竟什么是Struts呢?

    要回答這個(gè)問題還得從JSP Web應(yīng)用的兩種基本的結(jié)構(gòu)模式:Model 1和Model 2說(shuō)起,為了給讀者一些實(shí)實(shí)在在的幫助,并力圖讓學(xué)習(xí)曲線變得平坦一些,我想采用實(shí)例驅(qū)動(dòng)的方法來(lái)逐步深入地回答有關(guān)問題,因?yàn)椋瑢W(xué)一門技術(shù)的最好方法莫過于在實(shí)踐中學(xué)習(xí)、在實(shí)踐中體會(huì),逐步加深對(duì)其精神實(shí)質(zhì)的理解和把握,而不是一上來(lái)就引入一大堆新概念讓大家覺得無(wú)所適從,或者死記硬背一大堆概念而面對(duì)一個(gè)真正的實(shí)際需求束手無(wú)策。正如,一個(gè)人即使在書本上學(xué)成了游泳博士,只要他不下水,我想他也是不大可能真正會(huì)游泳的。

    Model 1結(jié)構(gòu)如圖1所示:



    圖1

    mode1 1是一個(gè)以JSP文件為中心的模式,在這種模式中JSP頁(yè)面不僅負(fù)責(zé)表現(xiàn)邏輯,也負(fù)責(zé)控制邏輯。專業(yè)書籍上稱之為邏輯耦合在頁(yè)面中,這種處理方式,對(duì)一些規(guī)模很小的項(xiàng)目如:一個(gè)簡(jiǎn)單的留言簿,也沒什么太大的壞處,實(shí)際上,人們開始接觸一些對(duì)自己來(lái)說(shuō)是新的東西的時(shí)候,比如,用JSP訪問數(shù)據(jù)庫(kù)時(shí),往往喜歡別人能提供一個(gè)包含這一切的單個(gè)JSP頁(yè)面,因?yàn)檫@樣在一個(gè)頁(yè)面上他就可以把握全局,便于理解。但是,用Model 1模式開發(fā)大型時(shí),程序流向由一些互相能夠感知的頁(yè)面決定,當(dāng)頁(yè)面很多時(shí)要清楚地把握其流向?qū)⑹呛軓?fù)雜的事情,當(dāng)您修改一頁(yè)時(shí)可能會(huì)影響相關(guān)的很多頁(yè)面,大有牽一發(fā)而動(dòng)全身的感覺,使得程序的修改與維護(hù)變得異常困難;還有一個(gè)問題就是程序邏輯開發(fā)與頁(yè)面設(shè)計(jì)糾纏在一起,既不便于分工合作也不利于代碼的重用,這樣的程序其健壯性和可伸縮性都不好。

    Grady Booch等人在UML用戶指南一書中,強(qiáng)調(diào)建模的重要性時(shí),打了一個(gè)制作狗窩、私人住宅、和大廈的形象比喻來(lái)說(shuō)明人們處理不同規(guī)模的事物時(shí)應(yīng)該采用的合理方法一樣,人們對(duì)不同規(guī)模的應(yīng)用程序也應(yīng)該采用不同的模式。

    為了克服Model 1的缺陷,人們引入了Model 2,如圖2所示:



    圖2

    它引入了"控制器"這個(gè)概念,控制器一般由servlet來(lái)?yè)?dān)任,客戶端的請(qǐng)求不再直接送給一個(gè)處理業(yè)務(wù)邏輯的JSP頁(yè)面,而是送給這個(gè)控制器,再由控制器根據(jù)具體的請(qǐng)求調(diào)用不同的事務(wù)邏輯,并將處理結(jié)果返回到合適的頁(yè)面。因此,這個(gè)servlet控制器為應(yīng)用程序提供了一個(gè)進(jìn)行前-后端處理的中樞。一方面為輸入數(shù)據(jù)的驗(yàn)證、身份認(rèn)證、日志及實(shí)現(xiàn)國(guó)際化編程提供了一個(gè)合適的切入點(diǎn);另一方面也提供了將業(yè)務(wù)邏輯從JSP文件剝離的可能。業(yè)務(wù)邏輯從JSP頁(yè)面分離后,JSP文件蛻變成一個(gè)單純完成顯示任務(wù)的東西,這就是常說(shuō)的View。而獨(dú)立出來(lái)的事務(wù)邏輯變成人們常說(shuō)的Model,再加上控制器Control本身,就構(gòu)成了MVC模式。實(shí)踐證明,MVC模式為大型程序的開發(fā)及維護(hù)提供了巨大的便利。

    其實(shí),MVC開始并不是為Web應(yīng)用程序提出的模式,傳統(tǒng)的MVC要求M將其狀態(tài)變化通報(bào)給V,但由于Web瀏覽器工作在典型的拉模式而非推模式,很難做到這一點(diǎn)。因此有些人又將用于Web應(yīng)用的MVC稱之為MVC2。正如上面所提到的MVC是一種模式,當(dāng)然可以有各種不同的具體實(shí)現(xiàn),包括您自己就可以實(shí)現(xiàn)一個(gè)體現(xiàn)MVC思想的程序框架,Struts就是一種具體實(shí)現(xiàn)MVC2的程序框架。它的大致結(jié)構(gòu)如圖三所示:



    圖三

    圖三基本勾勒出了一個(gè)基于Struts的應(yīng)用程序的結(jié)構(gòu),從左到右,分別是其表示層(view)、控制層(controller)、和模型層(Model)。其表示層使用Struts標(biāo)簽庫(kù)構(gòu)建。來(lái)自客戶的所有需要通過框架的請(qǐng)求統(tǒng)一由叫ActionServlet的servlet接收(ActionServlet Struts已經(jīng)為我們寫好了,只要您應(yīng)用沒有什么特別的要求,它基本上都能滿足您的要求),根據(jù)接收的請(qǐng)求參數(shù)和Struts配置(struts-config.xml)中ActionMapping,將請(qǐng)求送給合適的Action去處理,解決由誰(shuí)做的問題,它們共同構(gòu)成Struts的控制器。Action則是Struts應(yīng)用中真正干活的組件,開發(fā)人員一般都要在這里耗費(fèi)大量的時(shí)間,它解決的是做什么的問題,它通過調(diào)用需要的業(yè)務(wù)組件(模型)來(lái)完成應(yīng)用的業(yè)務(wù),業(yè)務(wù)組件解決的是如何做的問題,并將執(zhí)行的結(jié)果返回一個(gè)代表所需的描繪響應(yīng)的JSP(或Action)的ActionForward對(duì)象給ActionServlet以將響應(yīng)呈現(xiàn)給客戶。

    過程如圖四所示:



    圖四

    這里要特別說(shuō)明一下的是:就是Action這個(gè)類,上面已經(jīng)說(shuō)到了它是Struts中真正干活的地方,也是值得我們高度關(guān)注的地方。可是,關(guān)于它到底是屬于控制層還是屬于模型層,存在兩種不同的意見,一種認(rèn)為它屬于模型層,如:《JSP Web編程指南》;另一些則認(rèn)為它屬于控制層如:《Programming Jakarta Struts》、《Mastering Jakarta Struts》和《Struts Kick Start》等認(rèn)為它是控制器的一部分,還有其他一些書如《Struts in Action》也建議要避免將業(yè)務(wù)邏輯放在Action類中,也就是說(shuō),圖3中Action后的括號(hào)中的內(nèi)容應(yīng)該從中移出,但實(shí)際中確有一些系統(tǒng)將比較簡(jiǎn)單的且不打算重用的業(yè)務(wù)邏輯放在Action中,所以在圖中還是這樣表示。顯然,將業(yè)務(wù)對(duì)象從Action分離出來(lái)后有利于它的重用,同時(shí)也增強(qiáng)了應(yīng)用程序的健壯性和設(shè)計(jì)的靈活性。因此,它實(shí)際上可以看作是Controller與Model的適配器,如果硬要把它歸于那一部分,筆者更傾向于后一種看法,即它是Controller的一部分,換句話說(shuō),它不應(yīng)該包含過多的業(yè)務(wù)邏輯,而應(yīng)該只是簡(jiǎn)單地收集業(yè)務(wù)方法所需要的數(shù)據(jù)并傳遞給業(yè)務(wù)對(duì)象。實(shí)際上,它的主要職責(zé)是:
  • 校驗(yàn)前提條件或者聲明
  • 調(diào)用需要的業(yè)務(wù)邏輯方法
  • 檢測(cè)或處理其他錯(cuò)誤
  • 路由控制到相關(guān)視圖

    上面這樣簡(jiǎn)單的描述,初學(xué)者可能會(huì)感到有些難以接受,下面舉個(gè)比較具體的例子來(lái)進(jìn)一步幫助我們理解。如:假設(shè),我們做的是個(gè)電子商務(wù)程序,現(xiàn)在程序要完成的操作任務(wù)是提交定單并返回定單號(hào)給客戶,這就是關(guān)于做什么的問題,應(yīng)該由Action類完成,但具體怎么獲得數(shù)據(jù)庫(kù)連接,插入定單數(shù)據(jù)到數(shù)據(jù)庫(kù)表中,又怎么從數(shù)據(jù)庫(kù)表中取得這個(gè)定單號(hào)(一般是自增數(shù)據(jù)列的數(shù)據(jù)),這一系列復(fù)雜的問題,這都是解決怎么做的問題,則應(yīng)該由一個(gè)(假設(shè)名為orderBo)業(yè)務(wù)對(duì)象即Model來(lái)完成。orderBo可能用一個(gè)返回整型值的名為submitOrder的方法來(lái)做這件事,Action則是先校驗(yàn)定單數(shù)據(jù)是否正確,以免常說(shuō)的垃圾進(jìn)垃圾出;如果正確則簡(jiǎn)單地調(diào)用orderBo的submitOrder方法來(lái)得到定單號(hào);它還要處理在調(diào)用過程中可能出現(xiàn)任何錯(cuò)誤;最后根據(jù)不同的情況返回不同的結(jié)果給客戶。

    二、為什么要使用Struts框架

    既然本文的開始就說(shuō)了,自己可以建這種框架,為什么要使用Struts呢?我想下面列舉的這些理由是顯而易見的:首先,它是建立在MVC這種公認(rèn)的好的模式上的,Struts在M、V和C上都有涉及,但它主要是提供一個(gè)好的控制器和一套定制的標(biāo)簽庫(kù)上,也就是說(shuō)它的著力點(diǎn)在C和V上,因此,它天生就有MVC所帶來(lái)的一系列優(yōu)點(diǎn),如:結(jié)構(gòu)層次分明,高可重用性,增加了程序的健壯性和可伸縮性,便于開發(fā)與設(shè)計(jì)分工,提供集中統(tǒng)一的權(quán)限控制、校驗(yàn)、國(guó)際化、日志等等;其次,它是個(gè)開源項(xiàng)目得到了包括它的發(fā)明者Craig R.McClanahan在內(nèi)的一些程序大師和高手持續(xù)而細(xì)心的呵護(hù),并且經(jīng)受了實(shí)戰(zhàn)的檢驗(yàn),使其功能越來(lái)越強(qiáng)大,體系也日臻完善;最后,是它對(duì)其他技術(shù)和框架顯示出很好的融合性。如,現(xiàn)在,它已經(jīng)與tiles融為一體,可以展望,它很快就會(huì)與JSF等融會(huì)在一起。當(dāng)然,和其他任何技術(shù)一樣,它也不是十全十美的,如:它對(duì)類和一些屬性、參數(shù)的命名顯得有些隨意,給使用帶來(lái)一些不便;還有如Action類execute方法的只能接收一個(gè)ActionForm參數(shù)等。但瑕不掩瑜,這些沒有影響它被廣泛使用。

    三、Struts的安裝與基本配置

    我們主要針對(duì)Struts1.1版本進(jìn)行講解,這里假定讀者已經(jīng)配置好java運(yùn)行環(huán)境和相應(yīng)的Web容器,本文例子所使用的是j2sdk和Tomcat4.1.27。下面,將采用類似于step by step的方式介紹其基礎(chǔ)部分。

    安裝Struts
    到http://jakarta.apache.org/ 下載Struts的安裝文件,本文例子使用的是1.1版。

    接下來(lái)您要進(jìn)行如下幾個(gè)步驟來(lái)完成安裝:
    1、解壓下載的安裝文件到您的本地硬盤
    2、生成一個(gè)新的Web應(yīng)用,假設(shè)我們生成的應(yīng)用程序的根目錄在/Webapps/mystruts目錄。在server.xml文件中為該應(yīng)用新建一個(gè)別名如/mystruts
    3、從第1步解壓的文件中拷貝下列jar文件到/Webapps/mystruts/WEB-INF/lib目錄,主要文件有如下一些。

    struts.jar
    commons-beanutils.jar
    commons-collections.jar
    commons-dbcp.jar
    commons-digester.jar
    commons-logging.jar
    commons-pool.jar
    commons-services.jar
    commons-validator.jar


    4、創(chuàng)建一個(gè)web.xml文件,這是一個(gè)基于servlet的Web應(yīng)用程序都需要的部署描述文件,一個(gè)Struts Web應(yīng)用,在本質(zhì)上也是一個(gè)基于servlet的Web應(yīng)用,它也不能例外。

    Struts有兩個(gè)組件要在該文件中進(jìn)行配置,它們是:ActionServlet和標(biāo)簽庫(kù)。下面是一個(gè)配置清單:

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3
    //EN" "http://java.sun.com/dtd/web-app_2_3.dtd">
    <web-app>
      <servlet>
        <servlet-name>action</servlet-name>
        <servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
        <init-param>
          <param-name>config</param-name>
          <param-value>/WEB-INF/struts-config.xml</param-value>
        </init-param>
        <init-param>
          <param-name>debug</param-name>
          <param-value>2</param-value>
        </init-param>
        <load-on-startup>2</load-on-startup>
      </servlet>
      <servlet-mapping>
        <servlet-name>action</servlet-name>
        <url-pattern>*.do</url-pattern>
      </servlet-mapping>
      <taglib>
        <taglib-uri>/WEB-INF/struts-bean.tld</taglib-uri>
        <taglib-location>/WEB-INF/struts-bean.tld</taglib-location>
      </taglib>
      <taglib>
        <taglib-uri>/WEB-INF/struts-html.tld</taglib-uri>
        <taglib-location>/WEB-INF/struts-html.tld</taglib-location>
      </taglib>
      <taglib>
        <taglib-uri>/WEB-INF/struts-logic.tld</taglib-uri>
        <taglib-location>/WEB-INF/struts-logic.tld</taglib-location>
      </taglib>
    </web-app>


    上面我們?cè)趙eb.xml中完成了對(duì)servlet和標(biāo)簽庫(kù)的基本配置,而更多的框架組件要在struts-config.xml中進(jìn)行配置:

    5、創(chuàng)建一個(gè)基本的struts-config.xml文件,并把它放在/Webapps/mystruts/WEB-INF/目錄中,該文件是基于Struts應(yīng)用程序的配置描述文件,它將MVC結(jié)構(gòu)中的各組件結(jié)合在一起,開發(fā)的過程中會(huì)不斷對(duì)它進(jìn)行充實(shí)和更改。在Struts1.0時(shí),一個(gè)應(yīng)用只能有一個(gè)這樣的文件,給分工開發(fā)帶來(lái)了一些不便,在Struts1.1時(shí),可以有多個(gè)這樣的文件,將上述缺點(diǎn)克服了。需在該文件中配置的組件有:data-sources

    global-execptions
    form-beans
    global-forwards
    action-mappings
    controller
    message-resources
    plug-in


    配置清單如下:

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE struts-config PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 1.1
    //EN" "http://jakarta.apache.org/struts/dtds/struts-config_1_1.dtd">
    <struts-config>
      <message-resources parameter="ApplicationResources" />
    </struts-config>


    到此為止,我們已經(jīng)具備了完成一個(gè)最簡(jiǎn)單Struts應(yīng)用的所需的各種組件。前面已經(jīng)提到,在開發(fā)過程中我們會(huì)不斷充實(shí)和修改上面兩個(gè)配置描述文件。下面我們將實(shí)際做一個(gè)非常簡(jiǎn)單的應(yīng)用程序來(lái)體驗(yàn)一下Struts應(yīng)用開發(fā)的真實(shí)過程,以期對(duì)其有一個(gè)真實(shí)的認(rèn)識(shí)。在完成基礎(chǔ)部分的介紹后,筆者會(huì)給出一些在實(shí)際開發(fā)中經(jīng)常用到而又讓初學(xué)者感到有些難度的實(shí)例。最后,會(huì)介紹Struts與其他框架的關(guān)系及結(jié)合它們生成應(yīng)用程序的例子。


    下面,我們就從一個(gè)最簡(jiǎn)單的登錄例子入手,以對(duì)Struts的主要部分有一些直觀而清晰的認(rèn)識(shí)。這個(gè)例子功能非常簡(jiǎn)單,假設(shè)有一個(gè)名為lhb的用戶,其密碼是awave,程序要完成的任務(wù)是,呈現(xiàn)一個(gè)登錄界面給用戶,如果用戶輸入的名稱和密碼都正確返回一個(gè)歡迎頁(yè)面給用戶,否則,就返回登錄頁(yè)面要求用戶重新登錄并顯示相應(yīng)的出錯(cuò)信息。這個(gè)例子在我們講述Struts的基礎(chǔ)部分時(shí)會(huì)反復(fù)用到。之所以選用這個(gè)簡(jiǎn)單的程序作為例子是因?yàn)椴幌胱屵^于復(fù)雜的業(yè)務(wù)邏輯來(lái)沖淡我們的主題。

    因?yàn)镾truts是建立在MVC設(shè)計(jì)模式上的框架,你可以遵從標(biāo)準(zhǔn)的開發(fā)步驟來(lái)開發(fā)你的Struts Web應(yīng)用程序,這些步驟大致可以描述如下:
    1定義并生成所有代表應(yīng)用程序的用戶接口的Views,同時(shí)生成這些Views所用到的所有ActionForms并將它們添加到struts-config.xml文件中。
    2在ApplicationResource.properties文件中添加必要的MessageResources項(xiàng)目
    3生成應(yīng)用程序的控制器。
    4在struts-config.xml文件中定義Views與 Controller的關(guān)系。
    5生成應(yīng)用程序所需要的model組件
    6編譯、運(yùn)行你的應(yīng)用程序.

    下面,我們就一步步按照上面所說(shuō)的步驟來(lái)完成我們的應(yīng)用程序:

    第一步,我們的應(yīng)用程序的Views部分包含兩個(gè).jsp頁(yè)面:一個(gè)是登錄頁(yè)面logon.jsp,另一個(gè)是用戶登錄成功后的用戶功能頁(yè)main.jsp,暫時(shí)這個(gè)頁(yè)面只是個(gè)簡(jiǎn)單的歡迎頁(yè)面。

    其中,logon.jsp的代碼清單如下:

    <%@ page contentType="text/html; charset=UTF-8" %>
    <%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean" %>
    <%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %>
    <HTML>
    <HEAD>
    <TITLE><bean:message key="logon.jsp.title"/></TITLE>
    <html:base/>
    </HEAD>
    <BODY>
    <h3><bean:message key="logon.jsp.page.heading"/></h3>
    <html:errors/>
    <html:form action="/logonAction.do" focus="username">
    <TABLE border="0" width="100%">
    <TR>
    <TH align="right"><bean:message key="logon.jsp.prompt.username"/></TH>
    <TD align="left"><html:text property="username"/></TD>
    </TR>
    <TR>
    <TH align="right"><bean:message key="logon.jsp.prompt.password"/></TH>
    <TD align="left"><html:password property="password"/></TD>
    </TR>
    <TR>
    <TD align="right">
      <html:submit><bean:message key="logon.jsp.prompt.submit"/></html:submit>
    </TD>
    <TD align="left">
      <html:reset><bean:message key="logon.jsp.prompt.reset"/></html:reset>
    </TD>
    </TR>
    </TABLE>
    </html:form>
    </BODY>
    </HTML>


    main.jsp的代碼清單如下:

    <%@ page contentType="text/html; charset=UTF-8" %>
    <%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean" %>
    <%@ taglib uri="/WEB-INF/struts-logic.tld" prefix="logic" %>
    
    <HTML>
    <HEAD>
    <TITLE><bean:message key="main.jsp.title"/></TITLE>
    <html:base/>
    </HEAD>
    <BODY>
    <logic:present name="userInfoForm">
    <H3>
      <bean:message key="main.jsp.welcome"/> 
      <bean:write name="userInfoForm" property="username"/>!
    </H3>
    </logic:present>
    </BODY>
    </HTML>


    首先,我們看一下logon.jsp文件,會(huì)發(fā)現(xiàn)它有這么兩個(gè)鮮明的特點(diǎn):一是文件頭部有諸如:
    <%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean" %>
    <%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %>

    這樣的指令代碼,他們的作用就是指示頁(yè)面要用到struts的自定義標(biāo)簽,標(biāo)簽庫(kù)uri是一個(gè)邏輯引用,標(biāo)簽庫(kù)的描述符(tld)的位置在web.xml文件中給出,見上篇文章的配置部分。struts的標(biāo)簽庫(kù)主要由四組標(biāo)簽組成,它們分別是:
  • bean標(biāo)簽,作用是在jsp中操縱bean
  • logic標(biāo)簽,作用是在jsp中進(jìn)行流程控制
  • html標(biāo)簽,作用是顯示表單等組件
  • template標(biāo)簽,作用是生成動(dòng)態(tài)模板

    關(guān)于每類標(biāo)簽的具體作用及語(yǔ)法,因受篇幅限制,不在這里詳細(xì)討論,大家可參考struts手冊(cè)之類的資料。只是心里要明白所謂標(biāo)簽其后面的東西就是一些類,這點(diǎn)與bean有些相似,它們?cè)诤蠖诉\(yùn)行,生成標(biāo)準(zhǔn)的html標(biāo)簽返回給瀏覽器。

    要使用它們顯然要把它們的標(biāo)簽庫(kù)描述文件引入到我們的系統(tǒng)中,這是些以.tld為擴(kuò)展名的文件,我們要把它們放在/webapps/mystruts/WEB-INF/目錄下。引入struts標(biāo)簽后原來(lái)普通的html標(biāo)簽如文本框的標(biāo)簽變成了這樣的形式

    Jsp文件的第二個(gè)特點(diǎn),就是頁(yè)面上根本沒有直接寫用于顯示的文字如:username,password等東西,而是用這種形式出現(xiàn)。這個(gè)特點(diǎn)為國(guó)際化編程打下了堅(jiān)實(shí)的基礎(chǔ),關(guān)于國(guó)際化編程后面的文章還會(huì)專門討論。

    這個(gè)簡(jiǎn)單的應(yīng)用所用到的ActionForm為UserInfoForm,代碼清單如下:

    package entity;
    import org.apache.struts.action.ActionForm;
    import org.apache.struts.action.ActionMapping;
    import javax.servlet.http.HttpServletRequest;
    
    public class UserInfoForm extends ActionForm{
    
      private String username;
      private String password;
    
    
      public String getUsername() {
        return (this.username);
      }
      public void setUsername(String username) {
        this.username = username;
      }
    
      public String getPassword() {
        return (this.password);
      }
      public void setPassword(String password) {
        this.password = password;
      }
    }


    在你的應(yīng)用程序的WEB-INF目錄下再建一個(gè)classes目錄,在新建的這個(gè)classes目錄下再建如下幾個(gè)目錄entity(用于存放ActionForm類)、action目錄(用于存放Action類)、bussness目錄(用于存放作為Model的業(yè)務(wù)對(duì)象類)。Classes目錄下的子目錄就是所謂的包,以后,還會(huì)根據(jù)需要增加相應(yīng)的包。

    現(xiàn)在,將UserInfoForm.java保存到entity目錄中。

    把如下代碼添加到/webapps/mystruts/WEB-INF/struts-config.xml文件中

    <form-beans>
        <form-bean name="userInfoForm" type="entity.UserInfoForm" />
      </form-beans>


    特別要提醒一下的是:關(guān)于ActionForm的大小寫,一定要按照上面的寫,以免造成不必要的麻煩。

    到此,我們完成了第一步工作。

    第二步,我們建一個(gè)名為ApplicationResource.properties的文件,并把它放在/webapps/mystruts/WEB-INF/classes目錄下。它在struts-config.xml的配置信息我們已在第一篇文章的末尾說(shuō)了,就是:


    目前我們?cè)贏pplicationResource.properties文件中加入的內(nèi)容是:

    #Application Resource for the logon.jsp
    logon.jsp.title=The logon page
    logon.jsp.page.heading=Welcome World!
    logon.jsp.prompt.username=Username:
    logon.jsp.prompt.password=Password:
    logon.jsp.prompt.submit=Submit
    logon.jsp.prompt.reset=Reset
    
    #Application Resource for the main.jsp
    main.jsp.title=The main page
    main.jsp.welcome=Welcome:


    到此,我們已完成了第二個(gè)步驟。

    第三步,我們開始生成和配置Controller組件。

    在前面我們已經(jīng)提到,Struts應(yīng)用程序的控制器由org.apache.struts.action.ActionServlet和org.apache.struts.action.Action類組成,其中,前者已由Struts準(zhǔn)備好了,后者Struts只是為我們提供了個(gè)骨架,我們要做的是為實(shí)現(xiàn)應(yīng)用程序的特定功能而擴(kuò)展Action類,下面是實(shí)現(xiàn)我們登錄程序的Action類的代碼清單:

    package action;
    import java.io.IOException;
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpSession;
    import javax.servlet.http.HttpServletResponse;
    import org.apache.struts.action.Action;
    import org.apache.struts.action.ActionError;
    import org.apache.struts.action.ActionErrors;
    import org.apache.struts.action.ActionForm;
    import org.apache.struts.action.ActionForward;
    import org.apache.struts.action.ActionMapping;
    import org.apache.struts.action.ActionServlet;
    import bussness.UserInfoBo;
    import entity.UserInfoForm;
    public final class LogonAction extends Action {
      
      public ActionForward execute(ActionMapping mapping,
             ActionForm form,
             HttpServletRequest request,
             HttpServletResponse response)
             throws IOException, ServletException {
        UserInfoForm userInfoForm = (UserInfoForm) form;     	
        //從web層獲得用戶名和口令
        String username = userInfoForm.getUsername().trim();
        String password = userInfoForm.getPassword().trim();
        //聲明錯(cuò)誤集對(duì)象
        ActionErrors errors = new ActionErrors();
        //校驗(yàn)輸入
        if(username.equals("")){
          ActionError error=new ActionError("error.missing.username");
          errors.add(ActionErrors.GLOBAL_ERROR,error);
        }
        if(password.equals("")){
          ActionError error=new ActionError("error.missing.password");
          errors.add(ActionErrors.GLOBAL_ERROR,error);
        }
        
        //調(diào)用業(yè)務(wù)邏輯
        if(errors.size()==0){
          String validated = "";
          try{
            UserInfoBo userInfoBo=new UserInfoBo();
            validated =userInfoBo.validatePwd(username,password);
            if(validated.equals("match")){
              //一切正常就保存用戶信息并轉(zhuǎn)向成功的頁(yè)面	
              HttpSession session = request.getSession();
              session.setAttribute("userInfoForm", form);          
          	  return mapping.findForward("success");
            } 
          }
          
          catch(Throwable e){
            //處理可能出現(xiàn)的錯(cuò)誤
            e.printStackTrace();
            ActionError error=new ActionError(e.getMessage());
            errors.add(ActionErrors.GLOBAL_ERROR,error);
          }
        }  
        //如出錯(cuò)就轉(zhuǎn)向輸入頁(yè)面,并顯示相應(yīng)的錯(cuò)誤信息
        saveErrors(request, errors);    
        return new ActionForward(mapping.getInput());    
      } 
    }


    這個(gè)action類中有兩個(gè)錯(cuò)誤消息鍵要加到ApplicationResource.properties文件中,清單如下:

    #Application Resource for the LogonAction.java
    error.missing.username=<li><font color="red">missing username</font></li>
    error.missing.password=<li><font color="red">missing password</font></li>>


    第四步:在struts-config.xml文件中定義Views與 Controller的關(guān)系,也就是配置所謂的ActionMapping。它們?cè)趕truts-config.xml中的位置是排在標(biāo)簽后,我們的登錄程序的配置清單如下:

    <action-mappings>
        <action input="/logon.jsp" name="userInfoForm" path="/logonAction" scope="session" 
    	type="action.LogonAction" validate="false">
          <forward name="success" path="/main.jsp" />      
        </action>
      </action-mappings>


    第五步:生成應(yīng)用程序所需要的model組件,該組件是完成應(yīng)用程序業(yè)務(wù)邏輯的地方,現(xiàn)在我的登錄程序的業(yè)務(wù)邏輯很簡(jiǎn)單,就是判斷用戶是不是lhb并且其口令是不是awave如果是就返回一個(gè)表示匹配的字符串"match",否則,就拋出出錯(cuò)信息。其代碼清單如下:

    package bussness;
    
    import entity.UserInfoForm;
    
    public class UserInfoBo {
    
      public UserInfoBo(){
        
      }  	
    
      public String validatePwd(String username,String password){
        	
        String validateResult=""; 
           
        if(username.equals("lhb")&&password.equals("awave")){
          validateResult="match";
        }
        else{
          
          throw new RuntimeException("error.noMatch");
        }    	
        
        return validateResult;   
        
      }
    }


    將其放在bussness包中。

    我們同樣要將其表示錯(cuò)誤信息的鍵值設(shè)置在ApplicationResource.properties文件中,清單如下:

    #Application Resource for the UserInfoBo.java
    error.noMatch=<li><font color="red">no matched user</font></li>


    到此為止,我們已經(jīng)完成了這個(gè)簡(jiǎn)單登錄程序的所有組件。下面就可以享受我們的勞動(dòng)成果了。

    第六步、編譯運(yùn)行應(yīng)用程序。

    常規(guī)的做法是用Ant來(lái)裝配和部署Struts應(yīng)用程序,如果按這個(gè)套路,這篇文章就會(huì)顯得十分冗長(zhǎng)乏味,同時(shí)也沒有太大的必要,因?yàn)椋靡粋€(gè)IDE一般可以很方便地生成一個(gè)應(yīng)用。因此,我們采用簡(jiǎn)便的方法,直接編譯我們的.java文件。不過這里要注意一點(diǎn)的是:實(shí)踐證明,要使得編譯過程不出錯(cuò),還必須將struts.jar文件放一份拷貝到/common/lib目錄中,并在環(huán)境變量中設(shè)置CLASSPATH 其值是/common/lib/struts.jar;配置好后就可以分別編譯entity、bussness及action目錄下的.java文件了。編譯完成后:打開/conf目錄下的server.xml文件,在前加上如下語(yǔ)句為我們的應(yīng)用程序建一個(gè)虛擬目錄:

    <Context path="/mystruts" docBase="mystruts" debug="0"
                     reloadable="true">                 
    		</Context>


    啟動(dòng),tomcat。在瀏覽器中輸入:http://localhost:8080/mystruts/logon.jsp
    如果前面的步驟沒有紕漏的話,一個(gè)如圖所示的登錄畫面就會(huì)出現(xiàn)在你的眼前。



    如果,不輸入任何內(nèi)容直接點(diǎn)擊Submit按鈕,就會(huì)返回到logon.jsp并顯示missing username和missing password錯(cuò)誤信息;如果輸入其他內(nèi)容,則會(huì)返回no matched user的錯(cuò)誤;如果輸入的用戶名是lhb且口令是awave則會(huì)顯示表示登錄成功的歡迎頁(yè)面。

    上面雖然是一個(gè)功能很簡(jiǎn)單的應(yīng)用程序,但麻雀雖小,五臟俱全,基本涉及到了struts的主要組成部分。下面我們就來(lái)分析一下程序的特點(diǎn)和基本的工作原理。

    首先,我們?cè)跒g覽器中輸入.jsp文件時(shí),后臺(tái)將struts的自定義標(biāo)簽"翻譯"成普通的html標(biāo)簽返回給瀏覽器,而一些提示信息如作為輸入框label的username、password還有按鈕上提示信息還有錯(cuò)誤信息等都來(lái)自MessageResources即ApplicationResource.properties文件中對(duì)應(yīng)的鍵值。當(dāng)我們點(diǎn)擊Submit按鈕時(shí),從web.xml的配置可以看出,請(qǐng)求將被ActionServlet截獲。它通過表單中提供的action參數(shù)在struts-config.xml文件中查找對(duì)應(yīng)的項(xiàng)目,如果有對(duì)應(yīng)的ActionForm,它就用表單中數(shù)據(jù)填充ActionForm的對(duì)應(yīng)屬性,本例中的ActionForm為userInfoForm,相應(yīng)的屬性是username和password,這就是所謂的實(shí)例化ActionForm。然后,將控制交給對(duì)應(yīng)的Action,本例中是LogonAction,它做的主要工作是對(duì)ActionForm中取出的username和password做了一下校驗(yàn),這里只是簡(jiǎn)單檢驗(yàn)它們是否為空(這些簡(jiǎn)單的格式化方面的校驗(yàn)應(yīng)該放在客戶端進(jìn)行,而且struts也為我們提供了一個(gè)很好的模式,后面如果有可能會(huì)詳細(xì)介紹)。如果不為空則調(diào)用判斷用戶及口令是否正確的業(yè)務(wù)邏輯模塊UserInfoBo,同時(shí),它會(huì)捕獲可能出現(xiàn)的錯(cuò)誤,然后根據(jù)業(yè)務(wù)邏輯返回的結(jié)果將程序?qū)虿煌捻?yè)面,本例中如果業(yè)務(wù)邏輯返回的結(jié)果是"match"則依據(jù)中的返回main.jsp頁(yè)面給瀏覽器同時(shí)在session對(duì)象中保存了用戶的登錄信息;否則,返回輸入頁(yè)面并顯示相應(yīng)的出錯(cuò)信息,完成了上篇文章所說(shuō)的它的四個(gè)主要職責(zé)。

    大家一定注意到了,在本例的業(yè)務(wù)邏輯模塊UserInfoBo中,將用戶與密碼是寫死在程序中的,在一個(gè)真實(shí)的應(yīng)用程序中是不會(huì)這樣做的,那些需要永久保存的信息如,username及口令等都會(huì)保存在數(shù)據(jù)庫(kù)文件之類的永久介質(zhì)中,下一篇文章我們將介紹在struts中如何訪問數(shù)據(jù)庫(kù)。
  • 主站蜘蛛池模板: 亚洲综合色婷婷七月丁香| 四虎免费影院ww4164h| 日韩在线a视频免费播放| 亚洲成在人线电影天堂色| 国产精品视频白浆免费视频| 亚洲精品无码久久千人斩| 五级黄18以上免费看| 亚洲黄片毛片在线观看| 在线精品自拍亚洲第一区| 四虎永久成人免费影院域名| 美女被免费视频网站a| 亚洲国产一级在线观看 | 亚洲Av永久无码精品一区二区| 美女视频黄a视频全免费| 亚洲成A∨人片天堂网无码| 亚洲国产无套无码av电影| 国产一区二区免费| 亚洲精品美女久久久久| 免费国产作爱视频网站| 国产天堂亚洲国产碰碰| 中国亚洲女人69内射少妇| 日韩精品内射视频免费观看| 亚洲一级毛片在线播放| 美女被免费视频网站a国产| sss在线观看免费高清| 亚洲国产综合自在线另类| 国产大片51精品免费观看| 国产免费无码AV片在线观看不卡| 亚洲宅男精品一区在线观看| 亚洲男女内射在线播放| 在线观看永久免费| 一进一出60分钟免费视频| 亚洲欧洲国产经精品香蕉网| 国产免费卡一卡三卡乱码| 18禁无遮挡无码国产免费网站| 久久亚洲精品无码gv| 亚洲综合久久久久久中文字幕| 日韩亚洲国产二区| 一本色道久久88亚洲综合 | 免费一级毛片在线观看| 18观看免费永久视频|