轉載:http://www.cnblogs.com/ikuman/archive/2013/11/04/3403073.htmlhtml
一、struts2自2.1之後推薦使用Convention Plugin支持struts零配置支持(引入jar:struts2-convention-plugin-2.x.x.jar)
①convention默認掃描全部實現com.opensymphony.xwork2.Action的類和指定包路徑下以Action結尾的類名
②struts.convention.package.locators指定默認的根packages,struts.convention.action.packages指定搜索的packages下的action,
struts.convention.exclude.packages指定忽略的packages
③默認視圖路徑:WEB-INF/content(可經過struts.convention.result.path修改)
二、results和resultcodes
①容器啓動後,convention會自動加載全部action和jsp
②能夠指定不一樣的結果頁面,action-resultcode.jsp
③能夠認爲默認匹配順序爲actionName+resultcode+suffix>actionName+suffix java
URLweb |
Result正則表達式 |
File that could matchspring |
Result Typeexpress |
/helloapache |
successapp |
/WEB-INF/content/hello.jspjsp |
Dispatcherui |
/hello |
success |
/WEB-INF/content/hello-success.htm |
Dispatcher |
/hello |
success |
/WEB-INF/content/hello.ftl |
FreeMarker |
/hello-world |
input |
/WEB-INF/content/hello-world-input.vm |
Velocity |
/test1/test2/hello |
error |
/WEB-INF/content/test/test2/hello-error.html |
Dispatcher |
三、chain鏈
①一個action調用同一個包中的另外一個action
②若一個action未定義相對應的resultcode的result,且同一個包中有形如action-resultcode的action,如:
package com.example.actions; import com.opensymphony.xwork2.Action; import com.opensymphony.xwork2.ActionSupport; public class HelloAction extends ActionSupport { @Action("foo") public String foo() { return "bar"; } @Action("foo-bar") public String bar() { return SUCCESS; } }
此時,若未定義"foo-bar"的result,則convention嘗試在同一個包下尋找action名爲」foo-bar」的action。若是找到這樣的action,
convention將會調用並返回相關聯的result。
四、XWork packages
①爲了不衝突,可將action放在一個自定義XWORK的package下
②package命名由action所在的Java包,action對應的URL中namespace部分以及action的parent XWork package三個部分組成,即:
<java-package>#<namespace>#<parent-package>
③parent XWork package 值在屬性 struts.convention.default.parent.package 中指定(默認爲convention-default)
<constant name="struts.convention.default.parent.package" value="convention-default"/>
五、Annotation reference
Convention使用不少註解來重寫默認插件的action到url的映射和result路徑。同時,也能夠經過修改parent XWork package
經過使用@Action註解,Convention plugin能夠改變action映射的url,同時也能夠使一個action對應多個url地址,例如:
package com.example.actions; import com.opensymphony.xwork2.ActionSupport; import org.apache.struts2.convention.annotation.Action; public class HelloWorld extends ActionSupport { @Action("/different/url") public String execute() { return SUCCESS; } }
這時,action映射的url地址將是/different/url,若是沒有定義@Result,則該namespace下的action路徑將被看成result path,即WEB-
INF/content/different/url.jsp
經過@Actions註解,一個方法能夠對應多個url路徑,如:
package com.example.actions; import com.opensymphony.xwork2.ActionSupport; import org.apache.struts2.convention.annotation.Action; import org.apache.struts2.convention.annotation.Actions; public class HelloWorld extends ActionSupport { @Actions({ @Action("/different/url"), @Action("/another/url") }) public String execute() { return SUCCESS; } }
另一種使用@Action和@Actions的例子是在一個Action類中定義多個方法,使用不一樣的註解,對應不一樣的url,如:
package com.example.actions; import com.opensymphony.xwork2.ActionSupport; import org.apache.struts2.convention.annotation.Action; import org.apache.struts2.convention.annotation.Actions; public class HelloWorld extends ActionSupport { @Action("/different/url") public String execute() { return SUCCESS; } @Action("url") public String doSomething() { return SUCCESS; } }
第二個方法中的相對路徑註解不推薦使用,它的路徑將取決與package對應的namespace而不是由Action註解決定
Interceptor和interceptor stacks一樣能夠使用註解,下面的例子使用了validation interceptor和defaultStack interceptor stack:
package com.example.actions; import com.opensymphony.xwork2.ActionSupport; import org.apache.struts2.convention.annotation.Action; import org.apache.struts2.convention.annotation.Actions; public class HelloWorld extends ActionSupport { @Action(interceptorRefs={@InterceptorRef("validation"), @InterceptorRef("defaultStack")}) public String execute() { return SUCCESS; } @Action("url") public String doSomething() { return SUCCESS; } }
InterceptorRefs可用於方法或Action類,若用於類上,則對全部方法有效
package com.example.actions; import com.opensymphony.xwork2.ActionSupport; import org.apache.struts2.convention.annotation.Action; import org.apache.struts2.convention.annotation.Actions; @InterceptorRefs({ @InterceptorRef("interceptor-1"), @InterceptorRef("defaultStack") }) public class HelloWorld extends ActionSupport { @Action(value="action1", interceptorRefs=@InterceptorRef("validation")) public String execute() { return SUCCESS; } @Action(value="action2") public String doSomething() { return SUCCESS; } }
注意:若是遇到"Unable to find interceptor class referenced by ref-name XYZ",則說明在convention掃描Action類時,沒有Interceptor指定的攔截器。處理方式爲:1使用@ParentPackage註解(或者指定struts.convention.default.parent.package)指定定義了該Interceptor的package;2建立一個package並繼承定義了該Interceptor的package,同時使用@ParentPackage(或者 struts.convention.default.parent.package)指定該package
同時也能夠指定params參數,使用 {"key0", "value0, "key1", "value1" ... "keyN", "valueN"}形式
package com.example.actions; import com.opensymphony.xwork2.ActionSupport; import org.apache.struts2.convention.annotation.Action; import org.apache.struts2.convention.annotation.Actions; public class HelloWorld extends ActionSupport { @Action(interceptorRefs=@InterceptorRef(value="validation",params={"programmatic", "false", "declarative", "true})) public String execute() { return SUCCESS; } @Action("url") public String doSomething() { return SUCCESS; } }
若未指定interceptors,則使用default stack
若是將@Action,@Actions用於Action類,若該類中定義了execute,則該方法將用於action映射,不然應用的方法取決於請求
對於結果註解@Results可分爲全局和局部,全局@Results定義在Action類,對全部方法有效,局部@Results定義在方法上,只對該方法有效
package com.example.actions; import com.opensymphony.xwork2.ActionSupport; import org.apache.struts2.convention.annotation.Action; import org.apache.struts2.convention.annotation.Actions; import org.apache.struts2.convention.annotation.Result; import org.apache.struts2.convention.annotation.Results; @Results({ @Result(name="failure", location="fail.jsp") }) public class HelloWorld extends ActionSupport { @Action(value="/different/url", results={@Result(name="success", location="http://struts.apache.org", type="redirect")} ) public String execute() { return SUCCESS; } @Action("/another/url") public String doSomething() { return SUCCESS; } }
在@Results註解中能夠使用@params, {"key0", "value0, "key1", "value1" ... "keyN", "valueN"}
package com.example.actions; import com.opensymphony.xwork2.ActionSupport; import org.apache.struts2.convention.annotation.Action; import org.apache.struts2.convention.annotation.Actions; import org.apache.struts2.convention.annotation.Result; import org.apache.struts2.convention.annotation.Results; public class HelloWorld extends ActionSupport { @Action(value="/different/url", results={@Result(name="success", type="httpheader", params={"status", "500", "errorMessage", "Internal Error"})} ) public String execute() { return SUCCESS; } @Action("/another/url") public String doSomething() { return SUCCESS; } }
從2.1.7版本後,@Results能夠被子類繼承
對於@Namespace註解可應用於Action類和packages中,在類上使用時爲非徹底限定
package com.example.actions; import com.opensymphony.xwork2.ActionSupport; import org.apache.struts2.convention.annotation.Action; import org.apache.struts2.convention.annotation.Namespace; @Namespace("/custom") public class HelloWorld extends ActionSupport { @Action("/different/url") public String execute() { return SUCCESS; } @Action("url") public String doSomething() { return SUCCESS; } }
該Action類對應兩個url: /different/url和/custom/url
@org.apache.struts2.convention.annotation.Namespace("/custom")
package com.example.actions;
應用於package時,子包不繼承該namespace
對於@ResultPath容許改變默認的結果存放地址,該註解可用於Action類和package
package com.example.actions; import com.opensymphony.xwork2.ActionSupport; import org.apache.struts2.convention.annotation.Action; import org.apache.struts2.convention.annotation.ResultPath; @ResultPath("/WEB-INF/jsps") public class HelloWorld extends ActionSupport { public String execute() { return SUCCESS; } }
通過註解,該Action類對應的result地址爲/WEB-INF/jsps,而不是默認的/WEB-INF/content
對於@ParentPackage容許應用爲Action類或java package定義不一樣的parent Struts package,也能夠經過struts.convention.default.parent.package指定
package com.example.actions; import com.opensymphony.xwork2.ActionSupport; import org.apache.struts2.convention.annotation.Action; import org.apache.struts2.convention.annotation.ParentPackage; @ParentPackage("customXWorkPackage") public class HelloWorld extends ActionSupport { public String execute() { return SUCCESS; } }
對於@ExceptionMappings能夠指定Action類或方法的異常映射
@ExceptionMappings({
@ExceptionMapping(exception = "java.lang.NullPointerException", result = "success", params = {"param1", "val1"}) }) public class ExceptionsActionLevelAction { public String execute() throws Exception { return null; } }
public class ExceptionsMethodLevelAction { @Action(value = "exception1", exceptionMappings = { @ExceptionMapping(exception = "java.lang.NullPointerException", result = "success", params = {"param1", "val1"}) }) public String run1() throws Exception { return null; } }
對於jar包,Convention plugin默認不會掃描其中的Action,若但願掃描,則須要配置struts.convention.action.includeJars
<constant name="struts.convention.action.includeJars" value=".*?/myjar1.*?jar(!/)?,.*?/myjar2*?jar(!/)?">
注意,此處正則表達式匹配的是jar的路徑而不是文件名,該路徑下應包含jar並以"!/"結尾
Convention plugin能夠自動重載配置的修改,掃描Action的改動,若要啓用該功能,須要配置
<constant name="struts.devMode" value="true"/> <constant name="struts.convention.classes.reload" value="true" />
生產環境下,強烈建議不使用該功能
六、Tips
①確保action的namespace與locators中的一個匹配,在locators後面的包路徑後面,將做爲action的namespace,同時將用於定位results。例如對於位
於"my.example.actions.orders"路徑下的ViewAction將對應映射'/orders/view.action',而且結果必將位於/WEB-INF/content/orders,相似/WEB-
INF/content/orders/view-success.jsp
②使用Configuration Browser查看action映射
③打開跟蹤或調試,如log4j中增長:log4j.logger.org.apache.struts2.convention=DEBUG
常見問題
①'There is no Action mapped for namespace /orders and action name view.'這意味着URL /orders/view.action爲對應任何一個action類,檢查namespace和該
名稱的action
②'No result defined for action my.example.actions.orders.ViewAction and result success'這意味者action已成功映射到Url,可是Convention插件沒有找到
success result,檢查視圖文件是否存在,相似/WEB-INF/content/orders/view-success.jsp
③'java.lang.Exception: Could not load org/apache/velocity/runtime/resource/loader/ClasspathResourceLoader.class'這發生在
struts.convention.action.includeJars匹配外部jar包時
④當使用自定義interceptor stack時,發生'Unable to find interceptor class referenced by ref-name XYZ'這意味着convention插件在解析actions時,沒有繼
承該Interceptor定義的那個package,解決方式有兩種1)使用 @ParentPackage(或struts.convention.default.parent.package)指定定義了該攔截器的package;2)自
定義package並繼承定義了該Interceptor的package,並使用@ParentPackage(或struts.convention.default.parent.package)指定
七、重寫convention實現rent.package)指定
<bean type="org.apache.struts2.convention.ActionNameBuilder" name="MyActionNameBuilder" class="example.SultansOfSwingNameBuilder"/>
<constant name="struts.convention.actionNameBuilder" value="MyActionNameBuilder"/>
八、convention插件配置:
Name | Default Value | Description |
---|---|---|
struts.convention.action.alwaysMapExecute | true | Set to false, to prevent Convention from creating a default mapping to "execute" when there are other methods annotated as actions in the class |
struts.convention.action.includeJars | Comma separated list of regular expressions of jar URLs to be scanned. eg. ".*myJar-0\.2.*,.*thirdparty-0\.1.*" | |
struts.convention.action.packages | An optional list of action packages that this should create configuration for (they don't need to match a locator pattern) | |
struts.convention.result.path | /WEB-INF/content/ | Directory where templates are located |
struts.convention.result.flatLayout | true | If set to false, the result can be put in its own directory: resultsRoot/namespace/actionName/result.extension |
struts.convention.action.suffix | Action | Suffix used to find actions based on class names |
struts.convention.action.disableScanning | false | Scan packages for actions |
struts.convention.action.mapAllMatches | false | Create action mappings, even if no @Action is found |
struts.convention.action.checkImplementsAction | true | Check if an action implements com.opensymphony.xwork2.Action to create an action mapping |
struts.convention.default.parent.package | convention-default | Default parent package for action mappins |
struts.convention.action.name.lowercase | true | Convert action name to lowercase |
struts.convention.action.name.separator | - | Separator used to build the action name, MyAction -> my-action. This character is also used as the separator between the action name and the result in templates, like action-result.jsp |
struts.convention.package.locators | action,actions,struts,struts2 | Packages whose name end with one of these strings will be scanned for actions |
struts.convention.package.locators.disable | false | Disable the scanning of packages based on package locators |
struts.convention.exclude.packages | org.apache.struts.*, org.apache.struts2.*, org.springframework.web.struts.*, org.springframework.web.struts2.*, org.hibernate.* |
Packages excluded from the action scanning |
struts.convention.package.locators.basePackage | If set, only packages that start with its value will be scanned for actions | |
struts.convention.relative.result.types | dispatcher,velocity,freemarker | The list of result types that can have locations that are relative and the result location (which is the resultPath plus the namespace) prepended to them |
struts.convention.redirect.to.slash | true | A boolean parameter that controls whether or not this will handle unknown actions in the same manner as Apache, Tomcat and other web servers. This handling will send back a redirect for URLs such as /foo to /foo/ if there doesn't exist an action that responds to /foo |
struts.convention.classLoader.excludeParent | true | Exclude URLs found by the parent class loader from the list of URLs scanned to find actions (needs to be set to false for JBoss 5) |
struts.convention.action.eagerLoading | false | If set, found action classes will be instantiated by the ObjectFactory to accelerate future use, setting it up can clash with Spring managed beans |