Struts2 - Conversion Plugin

轉載: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
相關文章
相關標籤/搜索