<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    傻子一個

    一路走來~~

     

    Strtus2 Convention Plugin


    轉(zhuǎn)載自:http://blog.163.com/lennon.wang/blog/static/2135606200942215038914/


    1.官方介紹的地址:

    http://struts.apache.org/2.1.6/docs/convention-plugin.html


    2.struts.xml文件配置

    只挑選幾個重要的常量說明:

    (1) <constant name="struts.locale" value="zh_CN"/>
          <constant name="struts.i18n.encoding" value="UTF-8"/>

          struts2.1.6  現(xiàn)在只需要一個struts.xml文件就可以了。以前配struts.locale=zh_CN,struts.i18n.encoding=UTF- 8,應(yīng)用起動時會報一個警告,說沒有配置locale,必須要在struts.properties里面配置才不會報錯,現(xiàn)在這個問題已經(jīng)解決了,所有配 置都可以在xml文件中指定了。


    (2) <constant name="struts.action.extension" value="action,do,,"/>

          擴展名可以指定為空。這樣地址欄比較好看。但也會有個問題,就是一些其他servlet映射,如cxf,我們會映射地址為/services/*,現(xiàn)在這 個地址也變成struts2控制范圍的地址了,如果按默認的配置會報找不到action的錯誤。解決辦法是修改mapper類。這在以后文章中會提到。


    (3)  <constant name="struts.enable.DynamicMethodInvocation" value="true"/>
           <constant name="struts.enable.SlashesInActionNames" value="true"/>

          開啟動態(tài)方法。要實現(xiàn)零配置,就是需要動態(tài)方法調(diào)用。開啟action名稱可以有 “/”,一個請求地址有多個“/”,struts2就不會再使用類路徑掃描的命名空間,只會使用配置的名稱。所以既想action名稱里使用“/”,又想用struts2默認搜索的命名空間,只能自己修改一下convention插件的實現(xiàn)類了。


    (4) <constant name="struts.ui.theme" value="simple"/>

          不用dojo的及struts2復雜標簽樣式的就把主題設(shè)置為simple,這樣可以不加載多余的模板。


    (5) <constant name="struts.devMode" value="true"/>
          <constant name="struts.i18n.reload" value="true"/>
          <constant name="struts.configuration.xml.reload" value="true"/>
          <constant name="struts.convention.classes.reload" value="true" />

           開啟開發(fā)者模式,在平時開發(fā)時修改action的annotation配置可以不重啟,但是修改struts.xml文件還是要重啟。修改類的具體內(nèi)容,debug模式下可以不重啟,或是使用javarebel,這個不在討論范圍。


    (6)  <constant name="struts.convention.result.path" value="/WEB-INF/pages/"/>

          指定結(jié)果頁面路徑。 convention插件會自動在此路徑中尋找文件。放到WEB-INF的目的的保護文件資源,只能通過程序內(nèi)部跳轉(zhuǎn)才能訪問,我們的權(quán)限攔截器或其他權(quán)限處理只要加到action上就可以了。


    (7) <constant name="struts.convention.action.suffix" value="Action"/>
         <constant name="struts.convention.action.name.lowercase" value="true"/>
         <constant name="struts.convention.action.name.separator" value="_"/>

         一個action名字的獲取。比如為HelloWorldAction。按照配置,actionName為hello_world。


    (8)<constant name="struts.convention.action.disableScanning" value="false"/>

         是否不掃描類。一定要設(shè)為false,否則convention插件不起作用,零配置也沒有意義。


    (9)<constant name="struts.convention.default.parent.package" value="default"/>

         設(shè)置默認的父包,一般我們都設(shè)置一個default包繼承自struts-default。大部分類再繼承default。如果有特殊的類需要特殊的包,只能在action中再指定父包了。


    (10) <constant name="struts.convention.package.locators" value="action"/>
           <constant name="struts.convention.package.locators.disable" value="false"/>
           <constant name="struts.convention.package.locators.basePackage" value=""/>

    確定搜索包的路徑。只要是結(jié)尾為action的包都要搜索。basePackage按照默認不用配置,如果配置,只會找以此配置開頭的包。locators及l(fā)ocators.basePackage都是一組以逗號分割的字符串。


    (11)  <constant name="struts.convention.exclude.packages" value="org.apache.struts.*,org.apache.struts2.*,org.springframework.web.struts.*,org.springframework.web.struts2.*,org.hibernate."/>

    排除哪些包不搜索。按默認配置即可。逗號分割字符串。


    (12)  <constant name="struts.convention.action.includeJars" value="" />

    包括哪些jar包中的action。逗號分割字符串。


    (13)<constant name="struts.convention.relative.result.types" value="dispatcher,freemarker,velocity"/>

    默認返回的結(jié)果類型搜索。按順序先找相關(guān)的dispatcher的jsp文件是否存在。然后再找freemarker,再找velocity。


    (14)<constant name="struts.convention.result.flatLayout" value="true"/>

          如果此值設(shè)為true,如果一個action的命名空間為/login,名稱為HelloWorldAction。result返回值是success, 默認會找到/WEB-INF/pages/login/hello_world.jsp(如果有hello_world_success.jsp就找這個 文件,連接符“_”是在<constant name="struts.convention.action.name.separator" value="_"/>中配置的)。如果有一個action的result返回值是“error”,就會找/WEB-INF/pages /login/hello_world_error.jsp。

          如果此值設(shè)為false,如果一個action的命名空間為/login,名稱為HelloWorldAction。result返回值是success,默認會找到/WEB- INF/pages/login/hello_world/index.jsp(如果有success.jsp就找這個文件)。如果有一個action的result返回值是“error”,就會找/WEB-INF/pages /login/hello_world/error.jsp。


    (15) <constant name="struts.convention.action.mapAllMatches" value="false"/>
           <constant name="struts.convention.action.checkImplementsAction" value="false"/>
       <constant name="struts.mapper.alwaysSelectFullNamespace" value="false"/>
       <constant name="struts.convention.redirect.to.slash" value="true"/>

          這幾個配置沒有太多的實際意義,本著最小檢查的原則就可以。


    (16)默認攔截器配置,已經(jīng)簡化了許多,一般不需要chain和 fileupload。modelDriven也沒什么用,如果我們要使用restfull插件會有用。其實最簡單只要一個params就可以了。我加入 exception是為了開發(fā)時的異常。servletConfig是為了包裝一下request,reponse等對象,staticParams是為 了可以配置${}形式參數(shù)。actionMappingParams是struts2.1新增的,我初步認為是可以在action配置中傳參數(shù),這個還有 些疑問。



    1.action配置

       按照第一篇中的配置,設(shè)置locator為action,則默認一個類的命名空間為:

                   類路徑                                             命名空間
    com.example.action.MainAction         ->    /
    com.example.action.products.Display ->    /products

        完整url為:

                    類路徑                                                                                      完整url
    com.example.action.MainAction                                       -> /main
    com.example.action.products.Display                               -> /products/display
    com.example.action.company.ShowCompanyDetailsAction -> /company/details/show_company_details



    3.action類寫法
        如果要實現(xiàn)基本零配置,命名空間和action名稱按照默認的類路徑搜索。默認執(zhí)行方法是execute。方法返回值是success,就會找。


    Java代碼 復制代碼
    1. package com.example.action;   
    2.   
    3. import com.opensymphony.xwork2.ActionSupport;   
    4.   
    5. public class HelloWorld extends ActionSupport {   
    6.   
    7.     private String message;   
    8.   
    9.     public String getMessage() {   
    10.         return message;   
    11.     }   
    12.   
    13.     public String execute() {   
    14.         message = "Hello World! excute";   
    15.         return SUCCESS;   
    16.     }   
    17.   
    18.     public String edit() {   
    19.             message = "Hello World! edit";   
    20.         return "xyz";   
    21.     }   
    22.   
    23.     public String delete() {   
    24.         message = "Hello World! delete";   
    25.         return "depp";   
    26.     }   
    27.   
    28. }  
    package com.example.action;
    import com.opensymphony.xwork2.ActionSupport;
    public class HelloWorld extends ActionSupport {
    private String message;
    public String getMessage() {
    return message;
    }
    public String execute() {
    message = "Hello World! excute";
    return SUCCESS;
    }
    public String edit() {
    message = "Hello World! edit";
    return "xyz";
    }
    public String delete() {
    message = "Hello World! delete";
    return "depp";
    }
    }



        返回結(jié)果對應(yīng):

                   類路徑                                   實際url(WEB-INF/pages)
    /hello_world                                     /hello_world.jsp或/hello_world_success.jsp
    /hello_world!edit                               /hello_world_xyz.jsp
    /hello_world!delete                            /hello_world_depp.jsp

        基本的零配置就是這樣,如果要有redirect、chain等跳轉(zhuǎn)方式,interceptor的配置,就要加入annotation。


    2.action類中的annotation

    convention插件的annotation都在annotation這個包中,基本和xml配置相對應(yīng)。

        annotation           意義                                                                        作用域
    ParentPackage   指定繼承的包(struts2)名                                              包,類
    Namespaces      給一個action指定多個命名空間(一般不用)                      包,類
    Namespace       指定一個命名空間(一般不用,按默認的類路徑即可)         包,類,Namespaces注解中
    actions              給一個action指定多個名稱                                            方法
    action               指定一個action名稱                                                      類,方法,actions注解中
    InterceptorRefs 一組攔截器集合(只能是名稱,必須先在xml文件中配置好)  類,action注解中 
    InterceptorRef   一個攔截器                                                                  類,InterceptorRefs注解中
    ResultPath        結(jié)果映射的路徑(已經(jīng)在struts.xml文件中指定)                 包,類
    Results             多個結(jié)果集合                                                               類,action注解中
    Result              一個結(jié)果定義                                                                類,Results注解中

        需要注意:

    1)包(java)級別是在package-info.java這個文件中配置,可以配置整個包的定義,但是命名空間就不能按默認的類路徑掃描了,必須也要顯式的配置。所以這個文件最好不要使用。

    2)不在包(java)級別配置就要在類(java)級別配置,可能每個類都要寫一句ParentPackage,指定繼承的包(struts2),以獲得父包中的攔截器配置及其他公用配置。如果沒有特殊的攔截器配置則不用配置ParentPackage。

    3)最好把annotation配到類級別,因為這樣action名稱及命名空間都可用默認的類路徑掃描,不用我們顯式的配置。只要配置 特殊的result和攔截器即可。類中的其他方法使用動態(tài)方法調(diào)用的方式使用同一個配置。我們知道struts2所有配置都是啟動加載到map中的,減少 配置,會提高一定性能。而動態(tài)方法這種模式是零配置必不可少的,但我很不喜歡嘆號出現(xiàn)在地址欄中,所以在后面的文章中我會結(jié)合restful插件及自己修 改源代碼實現(xiàn)意義上的動態(tài)方法調(diào)用,但形式上是別的方式,地址欄會比較美觀。

    Java代碼 復制代碼
    1. package com.example.action;   
    2.   
    3. import com.opensymphony.xwork2.ActionSupport;   
    4. import org.apache.struts2.convention.annotation.Result;   
    5. import org.apache.struts2.convention.annotation.Results;   
    6. import org.apache.struts2.convention.annotation.InterceptorRef;   
    7. import org.apache.struts2.convention.annotation.InterceptorRefs;   
    8.   
    9. @InterceptorRefs({   
    10.     @InterceptorRef("interceptor-1"),   
    11.     @InterceptorRef("defaultStack")   
    12. })   
    13. @Results({   
    14.     @Result(name="reload",location="hello_world",type="redirectAction",params={key1,value1,key2,value2}),   
    15.     @Result(name="chainact",location="hello_world!edit",type="chain")   
    16. })   
    17. public class HelloWorld extends MyBaseAction {   
    18.   
    19.     private String message;   
    20.   
    21.     public String getMessage() {   
    22.         return message;   
    23.     }   
    24.   
    25.     public String execute() {   
    26.         message = "Hello World! excute";   
    27.         return SUCCESS;   
    28.     }   
    29.   
    30.     public String edit() {   
    31.             message = "Hello World! edit";   
    32.         return RELOAD;   
    33.     }   
    34.            
    35.     public String delete() {   
    36.             message = "Hello World! delete";   
    37.         return CHAINACT;   
    38.     }   
    39. }  
    package com.example.action;
    import com.opensymphony.xwork2.ActionSupport;
    import org.apache.struts2.convention.annotation.Result;
    import org.apache.struts2.convention.annotation.Results;
    import org.apache.struts2.convention.annotation.InterceptorRef;
    import org.apache.struts2.convention.annotation.InterceptorRefs;
    @InterceptorRefs({
    @InterceptorRef("interceptor-1"),
    @InterceptorRef("defaultStack")
    })
    @Results({
    @Result(name="reload",location="hello_world",type="redirectAction",params={key1,value1,key2,value2}),
    @Result(name="chainact",location="hello_world!edit",type="chain")
    })
    public class HelloWorld extends MyBaseAction {
    private String message;
    public String getMessage() {
    return message;
    }
    public String execute() {
    message = "Hello World! excute";
    return SUCCESS;
    }
    public String edit() {
    message = "Hello World! edit";
    return RELOAD;
    }
    public String delete() {
    message = "Hello World! delete";
    return CHAINACT;
    }
    }
    


    4)如果有極其特殊的情況需要為action的每個方法 單獨配置,這時就不能用默認的類掃描了,必須是先配置action,指定名稱,再在action中配置result和interceptor。這就會使配 置增多,違背的零配置的初衷。有時我們?yōu)榱诵阅茉蛳氚褦r截器細化到具體的action上,我想如果真是這樣,我們還不如再寫一個action類。還有 struts2.1.6原有的配置是如果action名稱中有“/”,會認為這是一個命名空間,不會再按照類掃描的默認值。例如:

    Java代碼 復制代碼
    1. package com.example.action;   
    2.   
    3. import com.opensymphony.xwork2.ActionSupport;   
    4. import org.apache.struts2.convention.annotation.Action;   
    5.   
    6. public class HelloWorld extends ActionSupport {   
    7.   
    8.     @Action("/different/url")   
    9.     public String execute() {   
    10.         return SUCCESS;   
    11.     }   
    12.   
    13.     @Action("url")   
    14.     public String doSomething() {   
    15.         return SUCCESS;   
    16.     }   
    17. }  
    package com.example.action;
    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")
    public String doSomething() {
    return SUCCESS;
    }
    }
    


        調(diào)用方法execute的url為 :       /different/url (命名空間已經(jīng)更換)
        調(diào)用方法doSomething的url為 :   /url

    5)比較別扭的地方就是攔截器的配置,必須用名稱,而名稱和實際攔截器類的對應(yīng)關(guān)系是在struts.xml文件中聲明的,如果用 struts2以前的annotation是可以直接配置攔截器類的,但是我沒有和convention插件結(jié)合使用,這個問題我正在研究,看看有沒有好 的辦法。

    6)還有一種默認的chain跳轉(zhuǎn),實際是在struts2.1.6中新增的unknownHandleder中設(shè)定的,沒有什么太大作用,我們可以不使用。而unknownHandleder我們可以自定義為其他,這在后面的文章中會有說明。


    1.Convention插件的主要實現(xiàn)淺析

    1.1  PackageBasedActionConfigBuilder 這個類最重要,是整個程序的入口。
         1.1.1  buildActionConfigs方法進行初始化配置,其中findActions掃描類路徑,我沒有深入研究這個方法具體是怎么找到所有類的。只是 找到全部類后,和我們的配置文件中限定的范圍匹配、過濾,存入一個set中。然后buildConfiguration(set)循環(huán)分析這些類。

         1.1.2  buildConfiguration方法,首先創(chuàng)建一個map類型的packageConfigs。鍵為包(struts2)名,值為PackageConfig.Builder對象,這個對象可以創(chuàng)建PackageConfig對象。
          然后循環(huán)找到的類,分析包名(java),determineActionNamespace方法分析命名空間,得到一個list對象。
          再循環(huán)所有命名空間,determineActionName方法分析類名稱、類的默認方法(這個是寫死在程序中的,就是execute方法)。
          getPackageConfig方法分析得到PackageConfig.Builder對象。
          getActionAnnotations方法分析得到action類方法的annotation配置。
          循環(huán)每個方法的配置,調(diào)用createActionConfig方法分析,把 results,interceptors,exceptionMappings等配置放入ActionConfig.Builder對象,再把 ActionConfig對象(由ActionConfig.Builder生成)放入PackageConfig.Builder中。
          buildIndexActions創(chuàng)建默認索引action。這個好像用處不大。
          最后把PackageConfig對象放入Configuration對象中,這是最頂級的配置。我們在任何時間和地點都可以得到Configuration對象,并對其進行分析。

         1.1.3   determineActionNamespace方法是確定一個action類在web應(yīng)用中的命名空間,先找這個類的Namespace注解,找到后 放入一個存儲命名空間的list。再找Namespaces注解,一個action可以有多個命名空間。如果有注解則按照注解來確定一個action的命 名空間,如果沒有,則分析這個action所在包(java)的路徑,按照struts2.xml中配置的規(guī)則來確定。這個規(guī)則就是截取到定義的 locator,在這個locator之后的包(java)全部作為命名空間,類名作為action名稱。

         1.1.4   determineActionName方法是確定一個action類在web應(yīng)用中的名稱。由ActionNameBuilder(接口)的方法來實 現(xiàn),這個接口的具體實現(xiàn)類,插件默認為SEOActionNameBuilder。被稱為搜索引擎友好的名稱。會把action類的name按單詞分解, 然后用連接符連起來。默認連接符是"-",我們可以設(shè)置為"_"。

         1.1.5   getPackageConfig方法是確定一個action類在web應(yīng)用中的繼承的包(struts2)。先找這個類的ParentPackage注 解,如果有注解則按照注解來確定一個action的父包(struts2),如果沒有,按照struts.xml中配置的規(guī)則來確定。這個規(guī)則就是 defaultParentPackage。得到父包(struts2)后要拼成: actionPackage + "#" + parentPkg.getName() + "#" + actionNamespace 的形式,這是xwork里的規(guī)定。

         1.1.6   getActionAnnotations方法是確定一個action類的方法上的annotation配置。先找方法的Actions注解,一個方法可 以有多個action映射。再找Action注解,放入一個map中,鍵是方法名,值是存儲一組acton映射的list對象。
        
          1.1.7   createActionConfig方法構(gòu)造ActionConfig.Builder對象,逐一判斷 interceptors,results,exceptionMappings,都是從類一級開始判斷是否有此注解,再從方法的action注解中尋 找。InterceptorMapBuilder,ResultMapBuilder是兩個接口,提供通過注解構(gòu)造Interceptor和Result 的方法,插件分別提供了默認的實現(xiàn)DefaultInterceptorMapBuilder和DefaultResultMapBuilder。而 buildExceptionMappings只是本類中的一個方法。

    1.2  DefaultInterceptorMapBuilder
         先找action類是否存在InterceptorRefs注解,再看是否存在InterceptorRef注解,再看action注解中是否定義了InterceptorRefs。
         還用到了StringTools的createParameterMap方法把注解中的params(形式為{key1,value1,key2,value2,......})轉(zhuǎn)化成一個map。
          buildInterceptorList方法利用了xwork中的InterceptorBuilder的一個靜態(tài)方法constructInterceptorReference把攔截器注入到配置中。
          而一個action所繼承的父包中的攔截器,或是默認攔截器,并不在這個類中構(gòu)造。而是由xwork根據(jù)包(struts2)的繼承關(guān)系加載(actionPackage + "#" + parentPkg.getName() + "#" + actionNamespace 這是xwork里規(guī)定的形式,已經(jīng)由PackageBasedActionConfigBuilder 配置)。

    1.3 DefaultResultMapBuilder
        1.3.1  build方法,確定defaultResultPath,構(gòu)造包含ResultConfig的map對象,再通過擴展名獲得一個包含 ResultTypeConfig的map對象。createFromResources方法獲得默認返回結(jié)果頁面,然后查找action注解中的 results配置,再找類級別的Results注解,再找類級別的Result注解,相同的肯定會覆蓋。createFromAnnotations。

        1.3.2  createFromResources方法中使用servletContext.getResourcePaths方法尋找頁面。如果 struts.xml中配置flatLayout為true則直接找到以命名空間為名稱的文件夾,在此文件夾中尋找頁面,如果flatLayout為 false,則會找到以命名空間為名稱的文件夾,再找到此文件夾中的以action名稱命名的子文件夾,在這個文件夾中尋找頁面。

        1.3.3  makeResults方法找默認的返回頁面,如果沒有路徑?jīng)]有包含resultcode(定義的字符串)的頁面,則按默認順序?qū)ふ? success,input,error。比如hello_world.jsp文件(flatLayout為true,連接符為"_"),如果沒有 hello_world_success.jsp,hello_world_input.jsp,hello_world_error.jsp文件,同 時"success","input","error",又沒有顯式的配置,只是作為結(jié)果字符串返回,則程序默認會用hello_world.jsp來匹 配三種結(jié)果。如果結(jié)果字符串resultcode是"edit",同時又沒有顯式的配置,則必會找hello_world_edit.jsp。

        1.3.4  createFromAnnotations這個方法就是把注解轉(zhuǎn)換成ResultConfig配置。

    1.4 ConventionsServiceImpl
        是result配置的輔助類。determineResultPath方法先判斷struts.xml文件中的配置,再判斷action類的注解中是否有ResultPath,如果有將覆蓋struts.xml中配置。
         getResultTypesByExtension方法提供一個map對象,默認的result結(jié)果返回。

          其實通過看這些方法,我們也基本了解了struts2的整個配置過程,非常繁瑣,很多的判斷確實很耗費資源,使用xml配置也一樣。我們也知道所有配置信息都是應(yīng)用啟動時加載,存入map中常駐內(nèi)存。所以我們應(yīng)該盡可能減少配置,多使用動態(tài)方法調(diào)用。

    1.5  ConventionUnknownHandler 是UnknownHandler接口的一個實現(xiàn),用來處理找不到相應(yīng)配置的情況。在struts2.1的dtd中新增了一個<unknown-handler-stack>元素,可以配置一組handler。
           handleUnknownAction方法處理找不到action的情況。這個我感覺用處不大。
           handleUnknownResult方法處理找不到result的情況。這個方法可以有很多擴展。比如我想定義一種返回值形式:redirect->xxx.do?ad=12或chain->xxx.do。用這種形式比寫注解要方便的多。
           handleUnknownActionMethod方法處理找不到action中方法的情況。這個默認沒有實現(xiàn)。

    posted on 2009-06-17 13:49 老文 閱讀(2342) 評論(0)  編輯  收藏 所屬分類: S2(F)SJ(H)JJ

    導航

    常用鏈接

    留言簿(2)

    隨筆分類(29)

    收藏夾(1)

    My Work

    學習文章

    軟件使用

    最新隨筆

    最新評論

    主站蜘蛛池模板: 国产高清视频免费在线观看| 亚洲女人初试黑人巨高清| 四虎影视永久免费观看地址| 最近高清国语中文在线观看免费| 国产一卡2卡3卡4卡无卡免费视频| 18禁男女爽爽爽午夜网站免费| 免费国产黄网站在线观看可以下载| 日韩电影免费在线观看| 国产精品免费看久久久| 久久久久久夜精品精品免费啦| 毛片无码免费无码播放 | 1区1区3区4区产品亚洲| 亚洲国产精品一区二区久久| 久久久无码精品亚洲日韩按摩| 亚洲综合视频在线| 亚洲av成人一区二区三区| 亚洲人片在线观看天堂无码| 国产亚洲一卡2卡3卡4卡新区| 免费国产va视频永久在线观看| 无码毛片一区二区三区视频免费播放| 暖暖免费中文在线日本| 中国性猛交xxxxx免费看| 成全视频高清免费观看电视剧| 日本免费一区二区三区四区五六区| 中文字幕天天躁日日躁狠狠躁免费| 91大神免费观看| 毛片a级三毛片免费播放| 五月天婷亚洲天综合网精品偷| 亚洲综合精品香蕉久久网| 亚洲国产人成在线观看69网站| 亚洲国产综合在线| 色偷偷亚洲第一综合网| 2022免费国产精品福利在线| 久久精品国产大片免费观看| 国产又黄又爽又猛免费app| 免费精品国产自产拍观看| 亚洲小说区图片区另类春色| 亚洲黄色片免费看| 亚洲AV无码专区在线电影成人| 九九九精品视频免费| 99热在线免费观看|