一、約定大於配置
從struts2.1開始,struts2不再推薦使用Codebehind作爲零配置插件,而是改爲使用Convention插件來支持零配置,和Codebehind相比,Convention插件更徹底,該插件完全拋棄配置信息,不僅不需要是使用struts.xml文件進行配置,甚至不需要使用Annotation進行配置,而是由struts2根據約定自動配置。
使用Convention:1. 將struts-Convention-plugin-2.1.6.jar文件複製到WEB-INF/lib路徑下
2. 對於Convention插件而言,它會自動搜索位於action,actions,struts,struts2包下的所有java類,Convention插件會把如下兩種java類當成Action處理:
2.1、 所有實現了com.opensymphony.xwork2.Action的java類
2.2、 所有類名以Action結尾的java類
3. Convention插件還允許設置如下三個常量:
3.1、 struts.Convention.exclude.packges:指定不掃描哪些包下的java類,位於這些包結構下的java類將不會自動映射成Action;
3.2、 struts.convention.package.locators:Convention插件使用該常量指定的包作爲搜尋Action的根包。對於actions.fore.LoginAction類,按約定原本應映射到/fore/login;如果將該常量設爲fore,則該Action將會映射到/login
3.3、 struts.convention.action.packages:Convention插件以該常量指定包作爲根包來搜索Action類。Convention插件除了掃描action,actions,struts,struts2四個包的類以外,還會掃描該常量指定的一個或多個包,Convention會試圖從中發現Action類。
注意:struts.convention.package.locators和struts.convention.action.packages兩個常量的作用比較微妙,開發者在利用這兩個常量時務必小心。
如下面Action所在包被映射的命名空間如下:
com.example.actions.MainAction ->映射 /
com.example.actions.products.Display -> 映射 /products
com.example.struts.company.details.ShowCompanyDetailsAction ->映射 /company/details
4. 映射Action的name時,遵循如下兩步規則:
4.1、 如果該Action類名包含Action後綴,將該Action類名的Action後綴去掉。否則不做任何處理。
4.2、 將Action類名的駝峯寫法(每個單詞首字母大寫、其他字母小寫的寫法)轉成中畫線寫法(所有字母小寫,單詞與單詞之間以中畫線隔開)
如:LoginAction映射的Acion的name屬性爲login,GetBooks映射的Action的name的屬性爲get-books,AddEmployeeAction映射的Action的name屬性爲add-employee
5. 默認情況下。Convention總會到WEB應用的WEB-INF/content路徑下定位物理資源,定位資源的約定是:actionRUL+resultCODE+suffix。當某個邏輯視圖找不到對應的試圖資源時,Convention會自動視圖使用ActionURL+suffix作爲物理視圖資源。
如:actions.fore.LoginAction 返回success字符串時,Convention優先考慮使用WEB-INF/content/fore目錄下的login-success.jsp作爲視圖資源。如果找不到該文件,login.jsp也可作爲對應的試圖資源。如果返回input字符串,Convention會將WEB-INF/content/fore裏面查找login-input.jsp
6. 爲了看到struts2應用裏的Action等各種資源的影射情況,struts2提供了Config Browser插件。使用方法,將struts2-config-browser-plugin-2.1.6.jar文件複製到struts2應用的WEB-INF\lib目錄中。
打開首頁地址:http://localhost:8080/applicationName/config-browser/actionNames.action這裏可以看到Config Browser插件的首頁。
注意:這裏不管開發者是否使用struts.xml文件進行配置,一樣可以看到struts的配置信息。
7.Action鏈的約定
如果希望一個Action處理結束後不是進入一個試圖頁面,而是進行另一個Action形成的Action鏈。通過Convention插件則只需遵守如下三個約定即可。
7.1、 第一個Action返回的邏輯視圖字符串沒有對應的視圖資源
7.2、 第二個Action與第一個Action處在同一個包下
7.3、 第二個Action影射的URL爲:firstActionURL+“-”+resultCODE
如:- 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;
- }
- }
<!--配置struts2應用於開發模式--!>
<constant name=”struts.devMode” value=”true”/>
<!—配置Convention插件自動重加載映射--!>
<constant name=”struts.convention.classes.reload” value=”true”/>
幾個重要的常量:
struts.convention.action.disableJarScanning---是否從包中搜索Action
struts.convention.action.package--------Convention插件以該常量指定包作爲根包
struts.convention.result.path ---設置Convention插件定位視圖資源的根路徑。默認值爲/WEB-INF/content
struts.convention.result.flatLayout—如果是爲false則可以將試圖放置Action對應的目錄下,無需放入WEB-INF/content
二、Convention註解
1. Convention的Annotation1.1、 與Action相關的兩個Annotation是@Action 和@Actions
1.2、@Action中可指定一個value屬性。類似於指定<action name=””/>屬性值
1.3、@Action中還可以指定一個params屬性,該屬性是一個字符串數組,用於該Acion指定的參數名和參數值。params屬性應遵守如下格式:{“name1”,”value1”,”name2”,”value2”}
1.4、 @Actions 也用於修飾Action類裏的方法,用於將該方法映射到多個URL.@Actions用於組織多個@Action.因此它可將一個方法映射成多個邏輯Action。
如:
- private String message;
- public String getMessage() {
- return message;
- }
- public void setMessage(String message) {
- this.message = message;
- }
- @Actions({ @Action(value = "login1", params = { "message", "指定Result!" }),
- @Action(value = "login2") })
- public String login() {
- return "str";
- }
- @Action(value = "other")
- public String abc() {
- return "abc";
- }
當我們用/login2.action訪問時,str的值爲null。返回的視圖爲 login2-str.jsp;
而我們通過/other.action調用的是abc()方法,返回的視圖爲/other-abc.jsp;
2. @Result 和@Results、@ResultPath
2.1、@Result 和@Results
2.1.1、@Results用於組織多個@Result因此它只需指定一個value屬性值,該value屬性值爲多個@Result
2.1.2、@Result相當於struts.xml文件的<result/>元素。使用@Result必須指定一個name屬性,相當於<result name=””/>。
2.1.3、@Result可選的屬性:
① type 相當於<result type=””/>指定返回視圖資源的類型
② location 相當於<result>…..</result>中間部分,用於指定實際視圖位置② params:該屬性相當於<result/>元素裏多個<param../>子元素的作用,用於爲該Result指定參數值。該屬性應滿足{“name1”,”value1”,”name2”,”value2”}格式
2.1.4、@Result有以下兩種用法:
① Action級的Result映射:以@Actions組合多個@Action後修飾的Action類。這種Result映射對該Action裏的所有方法都有效。
②方法級Result映射:將多個@Result組成數組後作爲@Action的results屬性值。這種Result映射僅對被修飾的方法有效。
- @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;
- }
- }
- @ResultPath("/WEB-INF/jsps")
- public class HelloWorld extends ActionSupport {
- public String execute() {
- return SUCCESS;
- }
- }
@Namespace:修飾Action類或其所在的包。該Annotation中指定一個value屬性值,用於指定被修飾的Action所在的命名空間
@Namespaces:修飾Action類或其所在的包,用於組合多個@Namespace
@ParentPackage: 用於指定被修飾的Action所在包的父包。
4、 異常處理相關的Annotation
4.1、@ExceptionMappings 用於組織多個@ExceptionMapping,因此它只需指定一個value屬性值,該value屬性值爲多個@ExceptionMapping。
4.2、@ExceptionMapping 用於定義異常類和物理視圖之間的對應關係,也相當於struts.xml文件裏<exception-mapping../>元素的作用 使用時,必須注意以下兩個屬性:
①exception: 用於指定異常類
②result : 用於指定邏輯視圖
4.3、@ExceptionMpping有如下兩種用法
①Action級的異常定義:以@ExceptionMappings組合多個@ExceptionMapping後修飾的Action類。這種異常定義對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;
- }
- }
5、攔截器配置相關的Annotation
5.1、與攔截器配置的Annotation有@InterceptorRef、@InterceptorRefs和@DefaultInterceptorRef
@InterceptorRefs用於組織多個@InterceptorRef,因此它只需要指定一個value屬性值,該value屬性值爲多個@InterceptorRef
@InterceptorRef用於爲指定Action引用lanjieq或者是攔截器棧。也就相當於strut.xml中位於<action../>元素內部的<interceptor-ref../>子元素的作用。使用@InterceptorRefAnnotation時,必須制定一個value屬性,用於指定所引用的攔截器或攔截器棧的名字。相當於<interceptor-ref../>子元素裏name屬性的作用。
- @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;
- }
- }
三、struts-plugin.xml 常量
默認常量:
- <constant name="struts.convention.actionConfigBuilder" value="convention"/>
- <constant name="struts.convention.actionNameBuilder" value="convention"/>
- <constant name="struts.convention.resultMapBuilder" value="convention"/>
- <constant name="struts.convention.interceptorMapBuilder" value="convention"/>
- <constant name="struts.convention.conventionsService" value="convention"/>
- <constant name="struts.convention.result.path" value="/WEB-INF/content/"/>
- <constant name="struts.convention.result.flatLayout" value="true"/>
- <constant name="struts.convention.action.suffix" value="Action"/>
- <constant name="struts.convention.action.disableScanning" value="false"/>
- <constant name="struts.convention.action.mapAllMatches" value="false"/>
- <constant name="struts.convention.action.checkImplementsAction" value="true"/>
- <constant name="struts.convention.default.parent.package" value="convention-default"/>
- <constant name="struts.convention.action.name.lowercase" value="true"/>
- <constant name="struts.convention.action.name.separator" value="-"/>
- <constant name="struts.convention.package.locators" value="action,actions,struts,struts2"/>
- <constant name="struts.convention.package.locators.disable" value="false"/>
- <constant name="struts.convention.package.locators.basePackage" value=""/>
- <constant name="struts.convention.exclude.packages" value="org.apache.struts.*,org.apache.struts2.*,org.springframework.web.struts.*,org.springframework.web.struts2.*,org.hibernate.*"/>
- <constant name="struts.convention.relative.result.types" value="dispatcher,velocity,freemarker"/>
- <constant name="struts.convention.redirect.to.slash" value="true"/>
- <constant name="struts.convention.action.alwaysMapExecute" value="true"/>
- <constant name="struts.mapper.alwaysSelectFullNamespace" value="true"/>
- <!-- <constant name="struts.convention.action.includeJars" /> -->
- <constant name="struts.convention.action.fileProtocols" value="jar" />
- <constant name="struts.convention.classes.reload" value="false" />
- <constant name="struts.convention.exclude.parentClassLoader" value="true" />
Add a constant element to your struts config file to change the value of a configuration setting, like:
<constant name="struts.convention.result.path" value="/WEB-INF/mytemplates/"/>
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 |
四、注意細節
1、當使用@Namespace將會覆蓋類包定義的Namespace,其他定義的有效Namespace將不通過Action直接找該命名空間下的對應的視圖。
2、當使用@Action(value = "/url")時,使用@Namespace定義的命名空間無效,該命名空間爲content。
3、使用@Action(value = "url")時,同時使用了@Namespace,完整路徑就是@Namespace+url