struts2 convention插件


1、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修改)
2、results和resultcodes
①容器啟動后,convention會自動加載所有action和jsp
②可以指定不同的結果頁面,action-resultcode.jsp
③可以認為默認匹配順序為actionName+resultcode+suffix>actionName+suffix 

URL

Result

File that could match

Result Type

/hello

success

/WEB-INF/content/hello.jsp

Dispatcher

/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

3、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。
4、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"/>

5、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" /> 

生產環境下,強烈建議不使用該功能
6、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)指定
7、重寫convention實現rent.package)指定

<bean type="org.apache.struts2.convention.ActionNameBuilder" name="MyActionNameBuilder" class="example.SultansOfSwingNameBuilder"/>
<constant name="struts.convention.actionNameBuilder" value="MyActionNameBuilder"/>

8、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

參見:http://struts.apache.org/release/2.1.x/docs/convention-plugin.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM