從 struts2.1 版本開始, Convention Plugin 作爲替換替換 Codebehind Plugin 來實現 Struts2 的零配置。 零配置並不是沒有配置,而是通過約定大於配置的方式,大量通過約定來調度頁面的跳轉而使得配置大大減少 ,我們也可以在類中複寫其中的方法來達到擴展的目的。
使用 Convention 插件,需要將其 JAR 文件放到你應用的 WEB-INF/lib 目錄中,你也可以在你 maven項目的 POM 文件中添加下面包依賴
- <dependency>
- <groupId>org.apache.struts</groupId>
- <artifactId>struts2-convention-plugin</artifactId>
- <version>2.1.6</version>
- </dependency
convention-plugin的約定
1. 默認情況下,Convention會默認所有的結果頁面都存儲在WEB-INF/content下,你也可以在struts的配置文件中設定struts.convention.result.path的值到一個新的路徑。如
- <constant name="struts.convention.result.path" value="/WEB-INF/page" />
這樣的話所有結果頁面的會存儲在 WEB-INF/page 下了,把 jsp 放在 WEB-INF 下有一個好處 ,別人就沒有辦法直接訪問了,這樣就可以簡化 spring security 的配置工作。
2. 默認 情況下, 包 的 路徑包含 action,actions,struts,struts2 的所有包都會被 struts 作爲含有 Action 類的路徑來搜索。你可以通過設置 struts.convention.package.locators 屬性來修改這個配置,如 springside 的 struts.xml 中是這樣配置的,
- <constant name="struts.convention.package.locators" value="web" />
則在項目中,包 的 路徑 含有 web的將被視爲Action存在的路徑來進行搜索。
3. 接着, Convention 從前一步找到的 package 以及其子 package 中尋找 com.opensymphony.xwork2.Action 的實現以及以 Action 結尾的類,如:
com.courseonline.test.web.account.UserAction 就會被掃描到。
4. 命名空間。從定義的 .package.locators 標示開始到包結束的部分,就是命名空間。舉個例子 ,上面我們定義了
- <constant name="struts.convention.package.locators" value="web" />
所以 com.courseonline.test.web.account.UserAction的命名空間是: “ / account ” 。
5. Convention 通過如下規則確定 URL 的具體資源部分 : 去掉類名的 Action 部分。然後將每個分部的首字母轉爲小寫,用‘ - ’分割,你可以設置 struts.convention.action.name.separator 如
- <constant name="struts.convention.action.name.separator" value="-" />
比如上面的例子 com.courseonline.test.web.account.UserAction 對應的 jsp 爲 /WEB-INF/content/account/use.jsp
如果是 com.courseonline.test.web.account.User Detail Action 對應的 jsp 爲 /WEB-INF/content/account/use-detail.jsp
下面是 convention 的一些常用註解
1.@Action 註解
- public class UserAction extends ActionSupport {
- @Action("url1")
- public String method1() {
- return SUCCESS;
- }
- @Action("/account/url2")
- public String method2() {
- return SUCCESS;
- }
- }
未用 @Action 註解前
默認調用路徑 |
訪問方法 |
默認映射路徑 |
/user!method1.action |
method1 |
/WEB-INF/content/user.jsp |
/user!method2.action |
method2 |
/WEB-INF/content/user.jsp |
|
|
|
使用 @Action 註解後
@Action 註解後調用的路徑 |
訪問方法 |
@Action 註解後映射的路徑 |
/url1!method1.action |
method1 |
/WEB-INF/content/url1.jsp |
/account/url2!method2.action |
method2 |
/WEB-INF/content/account/url2.jsp |
2. @Namespace 註釋
- @Namespace("/account")
- public class UserDetailAction extends ActionSupport {
- public String method1() {
- return "error";
- }
- @Action("url")
- public String method2() {
- return “error”;
- }
- @Action("/different/url2")
- public String method3() {
- return “error”;
- }
- }
調用路徑 |
訪問方法 |
映射路徑 |
/account/user-detail!method1.acton |
method1 |
/WEN-INF/content/account/user-detail-error.jsp |
/account/url!method2.acton |
method2 |
/WEN-INF/content/account/url.jsp |
/different/url2!method3.action |
method3 |
/WEN-INF/content/different/url2.jsp |
與@Action 註釋不同的是,該註釋覆蓋了默認的namespace( 默認的 是’/’),此時再用 user-detail !method1.action已經不能 訪問 method1 了 .
3. @Result
Convention 允許action類爲每個action定義不同的results,results分爲兩類,全局的(global)和本地的(local),全局results可以被action類中所有的action分享,這種results在action類上使用註解進行聲明。本地results只能在action方法上進行聲明。下面是兩種results註解的例子 .
1 )全局的 (global)。
- @Results({@Result(name="failure", location="/WEB-INF/fail.jsp") })
- public class UserAction extends ActionSupport {
- String method1() {
- return “failure”;
- }
- @Action("/different/url")
- public String method2() {
- return “failure”;
- }
- }
調用路徑 |
訪問方法 |
映射路徑 |
/user!method1.action |
method1 |
/WEB-INF/fail.jsp |
/different/url!method2.action |
method2 |
/WEB-INF/fail.jsp |
2 本地的(local)。
- public class UserAction extends ActionSupport {
- @Action(value="/other/ url ",results={@Result(name = "error", location = " /WEB-INF/fail",type="redirect")})
- public String method1() {
- return “error”;
- }
- }
調用路徑 |
訪問方法 |
映射路徑 |
/user!method1.action |
method1 |
/WEB-INF/content/user-error.jsp |
/other/url!method2.action |
method1 |
/WEB-INF/fail.jsp |
有了上面的知識,現在來看看 springside 3 的 mini-web 項目中部分用到的 convention 插件的地方,理解起來就不難了。
比較典型的是 UserAction.java 。
- @Namespace("/account")
- @Results( { @Result(name = CrudActionSupport.RELOAD, location = "user.action", type = "redirect") })
- public class UserAction extends CrudActionSupport<User> {
- ………………
- @Override
- public String list() throws Exception {
- …………
- return SUCCESS;
- }
- @Override
- public String input() throws Exception {
- …………
- return INPUT;
- }
- @Override
- public String save() throws Exception {
- …………
- return RELOAD;
- }
- ………………
- }
這裏我只選了三個返回結果分別爲 SUCCESS 、 INPUT 、和 RELOAD 的方法來做例子。
調用路徑 |
訪問方法 |
映射路徑 |
/account/user!list.action |
list |
/WEB-INF/content/account/user.jsp |
/account/user!input.action |
input |
/WEB-INF/content/account/user-input.jsp |
/account/user!save.action |
save |
/WEB-INF/content/account/user.jsp |
在調用 save 方法後,爲什麼會返回 /WEB-INF/content/account/user.jsp 這個頁面 呢?因爲在全局的 Result 定義名爲reload的result重定向到user.action, 其他result則按照convention默認 ,所以當調用完 save 方法後,返回的是RELOAD ,又被重定向到 user.action ,然後返回到 /WEB-INF/content/account/user.jsp 了;同理,訪問 input 方法時,返回的是 INPUT ,所以會返回 /WEB-INF/content/account/user-input.jsp
@Namespace("/account") 表示 定義URL映射對應/account/user.action
@Results( { @Result(name = CrudActionSupport.RELOAD, location = "user.action", type = "redirect") })
定義名爲reload的result重定向到user.action, 其他result則按照convention默認.
參考資料: http://www.blogjava.net/libin2722/articles/256525.html