Struts2.1.6+Spring2.5.6+Hibernate3.3.1全註解實例詳解(五)

 這是本系列的最後一章,大象對示例進行適當的擴充並說明。

    其實到第四篇,對於示例的說明就已經全部講完了,如果按照這樣的例子,很難有什麼值得學習的地方。大象本着寫點有用東西的原則,在這章,對示例進行一下適當的擴充並說明。

    第五部分:擴展框架

    paramsPrepareParamsStack攔截器棧

    paramsPrepareParamsStack這個攔截器棧是在struts2-default.xml中定義的,裏面包含了很多個攔截器,最重要的是這三個:paramspreparemodelDriven。我們只要記住這樣幾點。

    params:它負責將請求參數值設置到Action中與之同名的屬性中。

    prepare:當Action實現了Preparable接口時,這個攔截器就會調用prepare()方法。如果你有想在execute()方法之前執行的邏輯處理,它就可以幫你完成這個功能。

    modelDriven:如果Action實現了ModelDriven接口,這個攔截器就會把getModel()方法中的返回結果壓入值棧。這就意味着,可以在結果頁面上直接使用model對象的屬性。

    它的執行順序是這樣的

    首先,params攔截器會給action中的相關參數賦值,如idusernamepassword等等。

    然後,prepare攔截器執行prepare()方法,prepare()會根據參數,如id,去調用相關的方法,設置model對象。當然,實現的這個接口方法由你自己來定義,不侷限只設置model之類的功能。

    接着,modelDriven攔截器會將model對象壓入值棧,因爲它是把getModel()方法中的返回結果放到值棧中,而這個方法的返回類型是個泛型參數,在實現ModelDriven接口的時候,可以給它指定一個具體的對象類型,因此返回類型也將是這個指定的對象類型,如ModelDriven<User>

    最後,params攔截器會將參數再賦值給model對象。

    思考修改與保存這兩種動作。當點擊人員修改時,請求爲:user!input.action?id=1params攔截器會將id參數值設置到Action中的id屬性,請一定注意,id屬性要有set()方法,然後prepare攔截器開始在prepare()方法中,根據這個id值取得User對象,接着modelDriven會調用getModel()方法,此時,方法中返回的是user對象,所以會把user加入到值棧中,最後再執行一次params攔截器,但這時沒有其它的參數值需要賦值給user對象,所以程序會接着往下走,這裏假定沒有其它的業務邏輯,執行返回,字符串爲input,根據前面講的插件知識,結果頁面爲user-input.jsp,那麼就跳轉到修改頁面了,而且頁面中表單域將顯示數據庫中的值。如果理解了修改,那麼保存也就清楚了。

    prepare()方法雖然不錯,但是也有弊端,那就是它會對Action中的每個方法都進行攔截,不管你是執行execute還是input,還是其它的自定義方法,它都會對其攔截,這當然不是我們所希望的。那有沒有更好的方式?答案是肯定的,請接着往下看。

    prepareMethedName

    使用prepare攔截器的另一種形式,在prepare名稱後面加上需要攔截的方法名。比如,你要攔截input方法,可以寫成prepareInput,需要攔截save方法,就寫上prepareSave。採取這樣的方式後,將會在執行這些方法之前時,纔對它們進行攔截。

    例如,請求role!input.action,會執行RoleAction中的input方法,如果我們設置了prepareInput方法,則會先進入此方法執行,執行完後再回到input方法往下執行。

    請注意,在使用這種方式時,Preparable接口定義的prepare()方法體內不要含有任何代碼,就是說給這個方法一個空實現。這樣,它就什麼都不做,所有的攔截處理就全部交由相應的prepareMethedName來完成。

    

    

    它們在每個對應的方法之前執行。prepareEntity就是來初始化實體對象,然後由modelDriven攔截器將getModel()方法中的返回結果放入值棧,當返回頁面時,就可以直接取值了。

    StrutsAction

    重新定義一個基類,裏面封裝大部分的通用操作,主要依靠泛型來實現,將hibernateDao註解進來,通過繼承這個基類進行基本的CRUD操作。本文末尾提供示例源碼下載,裏面有詳細的註釋,這裏我只貼出部分重要代碼進行說明,爲了行文需要,有些註釋去掉了,但源碼裏面都有,請大家放心。

    

    通過擴展ActionSupport,使用泛型參數,構造函數根據反射得到T的具體類型。

    

    這就是默認的執行方法,基本的操作,在這個超類裏面都進行了定義,每個方法裏面設置的以do開頭的方法,是方便讓子類進行覆蓋,當基本的業務邏輯無法滿足我們的需求時,就可以在子類重寫這些方法。

    

    方法有默認實現,主要是列表顯示,保存和刪除,新增和修改已經有getModel()方法取得實體,在頁面上使用s標籤就可以直接取值,除非有特殊的業務需求,否則不用覆蓋doInputEntity()doViewEntity()方法。請注意,當需要實現自己的邏輯時,只需要覆蓋上面定義的這些方法,而不用重寫executeinput之類。

    我對HibernateDao又進行了適當的擴展與修改,提供了更多的基本封裝方法,不過大家還可以繼續添加。裏面都有詳細的註釋,這裏就不在贅述了。

    功能擴展

    我對例子做了兩個功能,一個是角色表的增加、修改、刪除、查看,另一個就是用戶表的查詢。可以從源碼中看到,我在RoleAction中沒有寫一行關於增刪改查的代碼,因爲它屬於基本操作,超類中已經封裝好了,所以這部分的代碼都省了。對於用戶表的查詢,我覆蓋了doListEntity()方法,在業務層進行條件封裝,執行查詢,返回結果。

    

    這個list就是在超類中定義的,因爲默認實現中也用到了list,另外list有一個get方法,用於在頁面中顯示。如果不想採取方式取得list集合,就重寫doListEntity()方法。這裏說明下,我是沒有加分頁功能的,大家可以按自己的方式添加分頁查詢。

    在用戶查詢方法中,我使用的是QBC對象查詢,因爲這種方式很簡潔,不過我在HibernateDao中也寫了HQLSQL方式的查詢方法,並進行了封裝,可以很方便的調用。

    

    

    這個queryResult方法的定義,你可以改爲傳遞用戶名與角色ID的參數,大象在這裏就是爲了方便,直接使用Request請求。這裏userDao調用的query方法是在HibernateDao裏面封裝的,因爲繼承了HibernateDao,就直接在Service層拿來用了。至於具體的,可以去看源碼。

    頁面部分沒有進行大的調整,主要是將role-list.jsp重命名爲role.jsp,因爲使用的是超類的默認實現。添加了role-input.jsprole-view.jsp兩個文件,並在user.jsp中,加入了查詢條件。這些代碼都很簡單就不再貼了,而且前一篇也貼過一部分。

    對於這個例子的完整講解說明就到此結束了。大象還想補充說明一下,這個例子只適用於學習,不適合商用,想在實際項目中運用,還需要對框架做大量的改造工作。本系列只是基於SSH2入門學習之用,源碼中不含jar包,下圖是本例中所需的最少jar文件,大家只要下載了springstrutshibernate三個完整壓縮包,那麼這些jar基本上都包含了。

    

    發佈並啓動Tomcat,然後輸入訪問地址:http://localhost:8080/ssh2 運行該示例,看看效果。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章