CONAN ZONE

          你越掙扎我就越興奮

          BlogJava 首頁 新隨筆 聯系 聚合 管理
            0 Posts :: 282 Stories :: 0 Comments :: 0 Trackbacks
          背景

          Struts2已經日益成為Web層比較主流的開發框架,它來源于Webwork2,是一個非常優秀的MVC框架。在Webwork2設計之處,Annotation和Ruby on Rails還沒有像現在那么火,所以整個框架在配置方面還是沿用了Web框架慣用的XML作為主要的配置方式。

          隨著時代的發展,對于Web程序員來說,如何簡化配置成了一個很重要的課題。在這方面,Struts2也有一些探索。在Struts2的官方網站上,我們可以找到一些優秀的plugin來做這些工作:

          http://cwiki.apache.org/S2PLUGINS/codebehind-plugin.html

          http://cwiki.apache.org/S2PLUGINS/smarturls-plugin.html

          LightURL的目的是為了吸取這些優秀的plugin的優點,并支持更方便的配置方式。

          安裝

          1. 將struts2-lighturl-plugin.jar加入到classpath下

          2. 配置你的web.xml

          Java代碼 復制代碼
          1.        
          2.     <!-- Struts Filter -->   
          3. <filter>   
          4.     <filter-name>struts</filter-name>   
          5.     <filter-class>com.demo2do.lighturl.LightURLFilter</filter-class>   
          6. </filter>   
          7.   
          8. <!-- Struts URL Definition -->   
          9. <filter-mapping>   
          10.     <filter-name>struts</filter-name>   
          11.     <url-pattern>/*</url-pattern>   
          12. </filter-mapping>      


          3. 需要指定你的action package所在位置和一些基本配置

          這一步一般在struts.properties中完成。你可以建一個struts.properties的配置文件,并放到classpath下,并指定如下配置

          Java代碼 復制代碼
          1. ## action package config   
          2. lighturl.action.packages=com.demo2do.lighturl.action   
          3.   
          4. ## action mapping implementation class  
          5. struts.mapper.class=com.demo2do.lighturl.LightURLActionMapper   
          6.   
          7. ## default parent package  
          8. lighturl.action.default.parent.package=struts-config   
          9.   
          10. ## define your entity package (optional)   
          11. # lighturl.entity.package=com.demo2do.lighturl.entity  


          在完成以上的步驟后,lighturl的所有配置即告完成,現在你已經可以使用所有lighturl所提供的特性。

          Namespace, ActionName和URL映射

          lighturl所提供的最基本的特性是根據你的Action所在的package,確定namespace和actionName,并進行對應的URL映射。

          舉例說明,你在上面所講述的struts.properties中,已經指定了你的action package

          Java代碼 復制代碼
          1. lighturl.action.packages=com.demo2do.lighturl.action  


          那么,如果你有以下的Action類,那么lighturl將根據如下的規則來確定每個Action類所對應的namespace,actionName和url映射關系

          1. 根據lighturl.action.packages的配置的package到你的Action類的相對package來確定namespace,如果其中有駝峰法命名,那么轉化成"-"連接的單詞
          • com.demo2do.lighturl.action.Index  ----> /
          • com.demo2do.lighturl.action.user.Search ----> /user
          • com.demo2do.lighturl.action.blog.category.Index ----> /blog/category
          • com.demo2do.lighturl.action.accoutDetail.View ----> /account-detail

          2. 將Action類的類名轉化成actionName。如果碰到的Action類以"Action"結尾,則去掉末尾的"Action",如果其中有駝峰法命名,那么轉化成"-"連接的單詞
          • com.demo2do.lighturl.action.Index ----> index
          • com.demo2do.lighturl.action.user.SearchAction ----> search
          • com.demo2do.lighturl.action.blog.CategoryBlog ----> category-blog

          3. 將namespace與actionName拼起來,就成構成映射到具體Action類的url
          • http://host:port/app/user/index ---> com.demo2do.lighturl.action.user.Index
          • http://host:port/app/blog/category-blog ---> com.demo2do.lighturl.action.blog.CategoryBlog

          上面的這種URL匹配方式,我稱之為:package匹配

          特殊形式的URL

          應該說根據package來進行Action映射,可以解決絕大多數從url到action的映射配置問題。不過有的時候,我們可能需要支持一些特殊形式的url。LightURL在默認情況下,支持下列2種特殊形式的URL

          1. 支持將名為Index的Action直接映射到package上

          這種匹配我稱之為:Namespace匹配。這一個特性很直觀。如果你在某個Action的package下面有一個名為Index的Action類,那么如果你直接訪問這個package,那么你可以訪問到這個類:
          • com.demo2do.lighturl.action.Index ---> http://host:port/app/
          • com.demo2do.lighturl.action.user.Index ---> http://host:port/app/user
          • com.demo2do.lighturl.action.blog.category.Index ---> http://host:port/app/blog/category

          2. 支持類似: /entity/${id}形式的URL

          這種匹配我通常稱之為:entity匹配。這個特性也比較簡單,如果你有某個entity,并且在你的Action package下有一個與entity同名的package。同時在這個package下有一個叫View的Action,那么上述形式的URL會被映射到該Action。
          • com.demo2do.lighturl.action.user.View ---> http://host:port/app/user/3456
          • com.demo2do.lighturl.action.blog.View ---> http://host:port/app/user/1113

          你可以通過在struts.properties中指定你entity所在的package來對哪些url可以具備這些特性,如果你輸入的url不在你所指定的package中含有entity,那么這個url將無法被識別。
          針對有些情況,數據庫的主鍵可能不是數字。此時,你可以通過自己實現com.demo2do.lighturl.config.EntityPrimaryKeyIdentifier的接口來指定你的url中id具備什么特點。默認的實現是將主鍵識別為數字。

          使用Annotation來指定映射

          除了上述這些基本特性以外,還可以通過Annotaion來指定URL映射。目前情況下,LightURL所支持的Annotation有兩種類型:

          1. URL完整匹配

          URL完整匹配是指如果某個url完整匹配于Annotation中所指定的內容,那么這個URL將被映射到Annotation所在的Action類的method

          Java代碼 復制代碼
          1. package com.demo2do.lighturl.action.user;   
          2.   
          3. import com.demo2do.lighturl.annotation.Action;   
          4. import com.opensymphony.xwork2.ActionSupport;   
          5.   
          6. /**  
          7.  * @author Downpour  
          8.  *  
          9.  */  
          10. public class Search extends ActionSupport {   
          11.        
          12.     private static final long serialVersionUID = -1728616675239859226L;   
          13.   
          14.     /* (non-Javadoc)  
          15.      * @see com.opensymphony.xwork2.ActionSupport#execute()  
          16.      */  
          17.     @Override  
          18.     @Action("/all/search-user")   
          19.     public String execute() throws Exception {   
          20.         return super.execute();   
          21.     }   
          22.   
          23. }  


          例如,上述的Action類有一個Annotation,那么這個Action和method將被映射到對應的URL:http://host:port/app/all/search-user。

          注意,此時,雖然從url上來看,這是一個沒有什么規則的url,但是其所對應的namespace和actionName還是根據com.demo2do.lighturl.action.user.Search來進行計算的。

          2. URL Template

          URL Template是指,url可以匹配Annotaion中指定的某種URL Template,并將其中的可變部分作為參數映射到Action中。

          Java代碼 復制代碼
          1. package com.demo2do.lighturl.action.blog;   
          2.   
          3. import com.demo2do.lighturl.annotation.Action;   
          4. import com.opensymphony.xwork2.ActionSupport;   
          5.   
          6. /**  
          7.  * @author Downpour  
          8.  *  
          9.  */  
          10. public class Category extends ActionSupport {   
          11.   
          12.     private static final long serialVersionUID = -1535992103374733252L;   
          13.   
          14.         private Long id;   
          15.        
          16.     private int year;   
          17.        
          18.     private int month;   
          19.        
          20.     private int day;   
          21.   
          22.     /* (non-Javadoc)  
          23.      * @see com.opensymphony.xwork2.ActionSupport#execute()  
          24.      */  
          25.     @Override  
          26.     @Action("/blogs/${year}/${month}/${day}")   
          27.     public String execute() throws Exception {   
          28.         return super.execute();   
          29.     }   
          30.            
          31.         @Action("/blog/${id}/edit")   
          32.     public String edit() throws Exception {   
          33.         return super.execute();   
          34.     }   
          35.         // setters and getters   
          36.        
          37. }  


          在上述的例子中,可以發現,在Annotation中所指定的內容是一個URL Template,如果你有一個url,可以匹配上面的URL Template,那么url將匹配到這個Action的method,并且將對應位置的值注入到Action中的同名參數中。

          針對上面的例子:
          http://host:port/app/blogs/2008/08/07將被映射到這個Action的execute,并且2008,08和07分別映射到year,month和day中。
          http://host:port/app/blog/2345/edit將被映射到Action的edit方法,并且2345映射到id中作為參數

          URL的匹配順序與重復配置的校驗

          在上面的例子中,介紹了那么多的url映射到Action中的方式。他們之間可能會出現沖突,有些沖突,LightURL會在系統啟動時為你檢查出來,并強制要求你糾正它,而有些沖突,則通過優先級匹配的方式進行。

          下列沖突將被認為是你必須在系統啟動前就進行糾正的:
          1. Annotation中定義的URL Template互相之間沖突

          例如:/blogs/${year}/${month}/${day}和/blogs/${category}/${id}/edit就是沖突的。

          2. Annotation中定義的URL Template與其他Annotation中定義的完全匹配URL沖突

          例如:/blogs/${year}/${month}和/blogs/category/index就是沖突的。

          3. Annotation中定義的URL Template與形如/entity/${id}的url定義沖突

          例如:/user/${id}形式的Annotation定義可能會與系統默認支持的沖突。

          在其他情況下,如果你定義的URL映射互相直接有沖突,那么LightURL將根據某個順序進行URL匹配,并找到第一個匹配的映射方式,然后放棄查找。這個順序為:
          1. 首先進行Namespace匹配,如果url恰好能匹配某個namespace,并且其對應的package下有Index作為Action,那么直接進行匹配。
          2. 其次查看所有的Annotation定義中,是否存在完整的URL匹配,如果找到,那么進行直接匹配。
          3. 接著進行package匹配,將url分解成相應的namespace和actionName,與已有的配置進行匹配,如果找到,那么直接匹配。
          4. 然后進行entity匹配,看看url是否形如:/entity/${id},如果是,那么直接匹配。
          5. 最后進行Annotation定義的Url Template匹配

          如果所有的五種情況都無法進行匹配,那么這個URL將無法被LightURL識別,繼續交由Struts2進行后續處理。


          上面所描述的內容都是Url到Action的映射。下面的部分,描述的是如何在Action執行完畢之后,轉到相應的結果view。

          Codebehind

          LightURL支持codebehind。有關codebehind的相關知識,可以參考struts2的相關文檔:
          http://struts.apache.org/2.x/docs/codebehind-plugin.html

          有了codebehind的支持,那么從Action轉到類似jsp,ftl或者vm的view層組件就不需要任何配置,只要符合一定的命名規范,就可以直接進行轉向。

          ResultCode的識別

          但是在很多情況下,我們需要的是全方位的Result類型的支持。例如,有的時候我們需要返回JSON Result,有的時候,我們可能需要Redirect到一個新的Action。此時,我們不得不為此增加一些配置,或者借助Annotation來完成。

          為此,LightURL提供了一種根據ResultCode進行識別的命名方式來匹配你所指定的Result。

          以JSON Result為例,你可以這么寫:

          Java代碼 復制代碼
          1. package com.demo2do.lighturl.action.user;   
          2.   
          3. import com.demo2do.lighturl.entity.User;   
          4. import com.opensymphony.xwork2.ActionSupport;   
          5.   
          6. /**  
          7.  * @author Downpour  
          8.  *  
          9.  */  
          10. public class Index extends ActionSupport {   
          11.   
          12.     private static final long serialVersionUID = -5017825114664788765L;   
          13.   
          14.     private User user;   
          15.        
          16.     /* (non-Javadoc)  
          17.      * @see com.opensymphony.xwork2.ActionSupport#execute()  
          18.      */  
          19.     @Override  
          20.     public String execute() throws Exception {   
          21.         return "j:user";   
          22.     }   
          23.   
          24.         // setters and getters   
          25. }  


          在這里,你可以發現,resultCode變成了j:user。那么此時,LightURL會將這個resultCode識別成:請返回JSON Result,并且JSON的Result的root為user對象。

          再例如:

          Java代碼 復制代碼
          1. package com.demo2do.lighturl.action.user;   
          2.   
          3. import com.demo2do.lighturl.entity.User;   
          4. import com.opensymphony.xwork2.ActionSupport;   
          5.   
          6. /**  
          7.  * @author Downpour  
          8.  *  
          9.  */  
          10. public class Index extends ActionSupport {   
          11.   
          12.     private static final long serialVersionUID = -5017825114664788765L;   
          13.   
          14.     private User user;   
          15.        
          16.     /* (non-Javadoc)  
          17.      * @see com.opensymphony.xwork2.ActionSupport#execute()  
          18.      */  
          19.     @Override  
          20.     public String execute() throws Exception {   
          21.         return "r:/user/add-user";   
          22.     }   
          23.   
          24.         // setters and getters   
          25. }  


          在這里,"r:/user/add-user"會被識別成:請返回Redirect Result。Redirect的URL為/user/add-user。

          LightURL默認情況下,實現了對Redirect Result和JSON Result的ResultCode識別,并將他們的前綴分別定制為:"r:"("redirect:")或者"j:"("json:")。

          當然,你可以根據你自己的情況,實現你自己的ResultCode的識別程序,你只需要實現com.demo2do.lighturl.result.ResultCodeConfig接口即可。并在struts.properties中指定你希望LightURL進行ResultCode匹配的順序。

          Java代碼 復制代碼
          1. lighturl.result.code.config=yourpackage.ResultCodeConfigImpl1,yourpackage.ResultCodeConfigImpl2  


          這樣,LightURL會根據你所指定的順序,依次進行ResultCode的匹配,直到找到第一個匹配的Result Type為之。

          當然,默認情況下,LightURL的匹配順序為:

          codebehind -> 你自定義的ResultCode識別實現 -> json -> redirect
          posted on 2008-09-26 20:03 CONAN 閱讀(262) 評論(0)  編輯  收藏 所屬分類: Struts2/Webwork
          主站蜘蛛池模板: 宁强县| 孙吴县| 温宿县| 瑞安市| 呼图壁县| 磐安县| 汶川县| 平乡县| 栖霞市| 房产| 日土县| 九台市| 留坝县| 色达县| 平南县| 荣昌县| 安乡县| 韶关市| 东平县| 柘荣县| 乌海市| 台中市| 札达县| 安丘市| 肃北| 潮安县| 赣州市| 多伦县| 廉江市| 榆社县| 兴仁县| 康平县| 滕州市| 广安市| 汉沽区| 无棣县| 千阳县| 阿克陶县| 克什克腾旗| 新竹市| 酉阳|