《研磨struts2》第二十一章 零配置 之 21.2 約定大於配置

21.2  約定大於配置

21.2.1約定大於配置的HelloWorld

先來做一個示例,讓大家體會一下什麼是約定大於配置。

1:Convention Plugin

從Struts2.1版本起,Struts2官方就推薦使用Convention Plugin替換Codebehind Plugin來實現零配置。相對Codebehind Plugin而言,Convention Plugin有如下一些特點:

  • 通過包的命名習慣來指定Action的位置

  • 通過命名習慣來約定Result(包括Jsp、FreeMarker等)的路徑

  • 類名對應於URL的約定轉換

  • 包名對應於命名空間的約定轉換

  • 遵循SEO規範的鏈接地址,比如:使用test-action來替換TestAction

  • 基於註解的Action名稱約定

  • 基於註解的攔截器約定

  • 基於註解的命名空間約定

  • 基於註解的XWork包

  • 默認action以及默認的Result

等等。總之,使用Convention Plugin來實現零配置,會更靈活、更徹底,基本上可以做到不需要struts.xml來進行配置,甚至不需要註解進行配置,完全由Struts2依靠約定進行自動配置即可。

2:設置環境

要使用Convention Plugin,需要把struts2-convention-plugin-2.1.8.1.jar包拷貝到web工程的WEB-INF\lib包裏面。

3:最簡單的HelloWorld

要示範零配置,當然首先去掉struts.xml文件,缺省情況下,Convention Plugin會約定所有的結果頁面都存放在WEB-INF\content文件夾下。

在WEB-INF文件夾下新建一個content文件夾,然後在content文件夾下新建一個名稱爲helloworld.jsp的文件,內容示例如下:


java代碼:
  1. <%@ page contentType="text/html; charset=gb2312" pageEncoding="gb2312"%>  

  2. <html>  

  3. <head>  

  4. <meta http-equiv="Content-Type" content="text/html; charset=gb2312">  

  5. <title>Insert title here</title>  

  6. </head>  

  7. <body>  

  8.    約定配置,Hell World  

  9. </body>  

  10. </html>  

訪問的方式是:在web上下文後面直接訪問這個頁面,不用加後綴,直接用名字就可以了,也就是URL爲:http://localhost:9080/helloworld/helloworld,運行結果如下:

圖21.1  約定配置示例

4:說明

在這個HelloWorld裏面,根本就沒有寫Action,當然也不存在struts.xml文件,完全是按照Convention Plugin的約定來運行,直接到WEB-INF/content文件夾下面,根據請求的url來找到對應的helloworld.jsp,然後直接運行這個頁面就得到了如上的運行結果。

那麼對於Convention Plugin來說,到底有哪些約定呢?

21.2.2常見的約定

1默認把所有的結果頁面都存儲在WEB-INF/content文件夾下,這個值可以通過在struts.xml或者struts.properties文件中設置struts.convention.result.path這個屬性的值來改變到其他路徑。示例如下:


java代碼:
  1. <constant name="struts.convention.result.path" value="/WEB-INF/mypage" />  

      這樣就將默認的result頁面路徑設置到了WEB-INF/mypage文件夾裏面。

2在應用啓動的時候,Convention插件會自動搜索位於action、actions、struts、struts2的包及其子包下的所有Java類,以搜索Action類。

      可以通過在struts.xml或者struts.properties文件中設置struts.convention.package.locators這個屬性的值來改變搜索的文件夾。示例如下:


java代碼:
  1. <constant name="struts.convention.package.locators" value="web,s2" />  

      上面的示例定義了:在項目中,包路徑中包含web和s2的將被視爲包含Action類的路徑而被搜索。

3在應用啓動的時候,Convention插件在上述包及其子包的路徑下搜索滿足如下條件的類來作爲Action類:

(1)       實現com.opensymphony.xwork2.Action的類

(2)       類名以Action結尾的Java類

比如:在cn.javass.testproject.action包下面,有一個HelloAction的類,那麼Convention插件會自動把這個HelloAction類當作Action來進行處理。

4在映射Action的名稱的時候,通常遵循如下規則:

(1)       如果該Action類名以Action作爲後綴,那麼會將後綴的Action去掉,其他的不做處理。

(2)       如果該Action類名採用駝峯式的寫法,也就是每個單詞首字母大寫的寫法,那麼需要把所有字母變成小寫,單詞與單詞之間以中畫線隔開。
   比如有一個Action的名稱爲HelloWorldAction,那麼對應的映射資源的名稱爲hello-world。

(3)       如果是單個詞的Action名稱,那麼把它的所有字母變成小寫,作爲對應的映射資源的名稱。比如Action類名爲HelloAction,它是以Action作爲後綴的,那麼對應的映射資源的名稱爲先去掉Action後綴,得到Hello,又是單個詞的名稱,變成小小,那麼最終對應的映射資源的名稱爲hello。

5:命名空間

從定義的package.locators開始到包結束的部分,就是命名空間。比如有一個Action類位於如下包中:cn.javass.testproject.action.t1.t2,那麼命名空間就是/t1/t2。

命名空間對應着訪問的url中的path部分,位於web上下文之後,具體的資源名稱之前的部分,比如訪問的url爲:http://localhost:9080/helloworld/t1/t2/hello-world,其中的helloworld就是web上下文,而後面的hello-world就是要訪問的資源的名稱,中間的/t1/t2就是url的path部分。

命名空間還對應着WEB-INF/content文件夾下的子文件夾路徑,如果命名空間爲/t1/t2,那就以爲着對應的result頁面,應該放在WEB-INF/content/t1/t2文件夾下。

6:對應resutl頁面的約定

(1)       Result頁面默認的都以WEB-INF/content作爲定位的起點。

(2)       如果沒有對應的Action存在,那麼訪問資源的名稱就直接和頁面的名稱對應,要注意都是小寫的

(3)       如果有對應的Action存在,那麼對應的方式是:優先按照“Action的URL+Result的字符串+文件類型的後綴”的方式進行對應,如果沒有對應的頁面,那麼也可以按照“Action的URL+文件類型的後綴”的方式進行對應。

7:Action鏈的約定

如果一個Action執行完成後,希望進入到另外一個Action,從而形成Action鏈,基本的約定如下:

(1)       第一個Action返回的result沒有對應的頁面存在。

(2)       第二個Action和第一個Action在同一個包中,而且第二個Action映射的URL爲:第一個Action映射的URL+返回的result字符串,而且名稱採用駝峯式的寫法,也就是首字母大寫。

21.2.3  示例常見的約定

看了上面的約定,感覺如何,很糟糕是不是,這些約定的規則太抽象了,具體怎麼使用呢?接下來就通過示例來說明。

1:沒有Action的時候,就如同前面約定大於配置的HelloWorld那樣,訪問的URL爲:http://localhost:9080/helloworld/helloworld,由於沒有對應的Action,因此直接到WEB-INF的content文件夾下面,尋找名稱爲“helloworld”,後綴可以爲“.jsp”、“.htm”、“.html”等的頁面,找到後就直接運行。

2:如果有如下的包結構和類的定義:

圖21.2  示例的包結構

(1)如果要運行HelloWorldAction的話,對應的URL應該爲:http://localhost:9080/helloworld/t1/t2/hello-world,而且在content文件夾下應該有t1文件夾,t1文件夾下應該有t2文件夾,t2文件夾下應該有相應的result頁面,如下圖:

圖21.3  t2文件夾示例

像這個示例中,同時存在hello-world-success.jsp和hello-world.jsp,那麼會優先匹配到hello-world-success.jsp,如果不存在hello-world-success.jsp才匹配hello-world.jsp。

(2)先看看ConventionAction的實現,示例代碼如下:


java代碼:
  1. publicclass ConventionAction extends ActionSupport{  

  2. public String msg = "";  

  3. public String userId = "";    

  4. public String execute() throws Exception {  

  5.        System.out.println("now in ConventionAction");  

  6. if(userId==null || userId.trim().length()==0){  

  7.            msg = "用戶編號不能爲空";  

  8. return"toadd";  

  9.        }  

  10.        msg = "用戶編號輸入正確";  

  11. return SUCCESS;  

  12.    }  

  13. }  

此時在content文件夾下,有如下圖所示的頁面:

圖21.4 content文件夾

如果運行的URL爲:http://localhost:9080/helloworld/convention?userId=22,那麼會匹配到ConventionAction這個類,運行結束後,返回success。接下來到content文件夾下去優先匹配到convention-success.jsp,然後運行這個頁面,展示給用戶。

如果運行的URL爲:http://localhost:9080/helloworld/convention,那麼會匹配到ConventionAction這個類,運行結束後,返回toadd。接下來到content文件夾下去優先匹配到convention-toadd.jsp,然後運行這個頁面,展示給用戶。

如果此時把convention-toadd.jsp文件去掉,然後再次運行,運行的URL同樣爲:

http://localhost:9080/helloworld/convention,那麼會匹配到ConventionAction這個類,運行結束後,返回toadd。接下來到content文件夾下去尋找匹配的頁面,沒有能匹配上的,那麼就會到ConventionAction這個類的同包下,尋找是否有ConventionToaddAction這個類,有這個類,那麼就會運行這個類,相當於是Action鏈了。



From : http://sishuok.com/forum/blogPost/list/0/4184.html


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