隨筆 - 312, 文章 - 14, 評論 - 1393, 引用 - 0

          導(dǎo)航

          <2009年2月>
          25262728293031
          1234567
          891011121314
          15161718192021
          22232425262728
          1234567

          公告

          關(guān)注我的新浪微博

          我的著作









          常用鏈接

          留言簿(126)

          我參與的團(tuán)隊

          隨筆分類(818)

          隨筆檔案(310)

          文章分類(1)

          文章檔案(8)

          相冊

          ADSL、3G查詢

          CSDN

          eclipse

          ibm

          Java EE

          Linux

          Web

          云服務(wù)

          代理網(wǎng)站

          關(guān)注的網(wǎng)站

          協(xié)議

          喜歡的Blog

          國內(nèi)廣告平臺

          圖書出版

          在線培訓(xùn)

          開發(fā)工具

          微博客戶端

          手機(jī)鈴聲

          操作系統(tǒng)

          • ReactOS
          • 一個與windowXP/2003兼容的操作系統(tǒng)

          數(shù)學(xué)

          文件格式

          源碼資源

          移動(Mobile)

          編程語言

          英語學(xué)習(xí)

          最新隨筆

          搜索

          •  

          積分與排名

          • 積分 - 1972671
          • 排名 - 6

          最新評論

          閱讀排行榜

          評論排行榜

          Struts 2雜談(1):ValueStack對象的傳送帶機(jī)制

          本文為原創(chuàng),如需轉(zhuǎn)載,請注明作者和出處,謝謝!

          源碼與jar包下載(將rar改成jar,直接放在WEB_INF\lib目錄中即可)

              眾所周知,Strut 2的Action類通過屬性可以獲得所有相關(guān)的值,如請求參數(shù)、Action配置參數(shù)、向其他Action傳遞屬性值(通過chain結(jié)果)等等。要獲得這些參數(shù)值,我們要做的唯一一件事就是在Action類中聲明與參數(shù)同名的屬性,在Struts 2調(diào)用Action類的Action方法(默認(rèn)是execute方法)之前,就會為相應(yīng)的Action屬性賦值。
              要完成這個功能,有很大程度上,Struts 2要依賴于ValueStack對象。這個對象貫穿整個Action的生命周期(每個Action類的對象實(shí)例會擁有一個ValueStack對象)。當(dāng)Struts 2接收到一個.action的請求后,會先建立Action類的對象實(shí)例,并且將Action類的對象實(shí)例壓入ValueStack對象中(實(shí)際上,ValueStack對于相當(dāng)一個棧),而ValueStack類的setValue和findValue方法可以設(shè)置和獲得Action對象的屬性值。Struts 2中的某些攔截器正是通過ValueStack類的setValue方法來修改Action類的屬性值的。如params攔截器用于將請求參數(shù)值映射到相應(yīng)成Action類的屬性值。在params攔截器中在獲得請求參數(shù)值后,會使用setValue方法設(shè)置相應(yīng)的Action類的屬性。
              從這一點(diǎn)可以看出,ValueStack對象就象一個傳送帶,當(dāng)客戶端請求.action時,Struts 2在創(chuàng)建相應(yīng)用Action對象后就將Action對象放到了ValueStack傳送帶上,然后ValueStack傳送帶會帶著Action對象經(jīng)過若干攔截器,在每一攔截器中都可以通過ValueStack對象設(shè)置和獲得Action對象中的屬性值。實(shí)際上,這些攔截器就相當(dāng)于流水線作業(yè)。如果要對Action對象進(jìn)行某項加工,再加一個攔截器即可,當(dāng)不需要進(jìn)行這項工作時,直接將該攔截器去掉即可。
              下面我們使用一個例子來演示這個過程。在這個例子中實(shí)現(xiàn)了一個攔截器,該攔截器的功能是將一個屬性文件中的key-value對映射成相應(yīng)的屬性的值。如下面是一個屬性文件的內(nèi)容:

              name = 超人
              price = 10000

              我們可以在Action類中定義name和price屬性,在Action中引用這個攔截器后,就會自動為屬性賦值。
              在使用該攔截器有如下規(guī)則:
              1.  攔截器讀取的屬性文件路徑由path參數(shù)指定。
              2.  屬性文件的編碼格式由encoding參數(shù)指定,默認(rèn)值是UTF-8。
              3.  如果某個key中包含有“.”(該符號不能出現(xiàn)在標(biāo)識符中),則有如下處理方法:
              (1)將Action類的屬性名定義為去掉“.”的key。例如,key為person.name,而屬性名可定義為personname。
              (2)將Action類的屬性名定義為將“.”替換成其他字符的表示符號。例如,key為person.name,而屬性名可定義為person_name,其中“_”由separator參數(shù)指定。
              4.  如果key太長,也可以直接使用Action參數(shù)進(jìn)行映射,例如,key為country.person.name,可做如下映射:
                <param name="countrypersonname">name</param>
                要注意的是,name屬性值不能包含“.”,因此,應(yīng)將key值中的“.”去掉。現(xiàn)在就可以直接在Action類中定義名為name的屬性的,name屬性的值會與key值相同。
              5.  上面所有的規(guī)則可以同時使用。

          攔截器的源代碼:

          package interceptors;

          import java.util.Enumeration;
          import java.util.Map;
          import java.util.Properties;
          import java.io.InputStream;
          import java.io.FileInputStream;
          import com.opensymphony.xwork2.ActionContext;
          import com.opensymphony.xwork2.ActionInvocation;
          import com.opensymphony.xwork2.config.entities.ActionConfig;
          import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
          import com.opensymphony.xwork2.util.ValueStack;

          public class PropertyInterceptor extends AbstractInterceptor
          {
              
          private static final String DEFAULT_PATH_KEY = "path";
              
          private static final String DEFAULT_ENCODING_KEY = "encoding";
              
          private static final String DEFAULT_SEPARATOR_KEY = "separator";

              
          protected String pathKey = DEFAULT_PATH_KEY;
              
          protected String encodingKey = DEFAULT_ENCODING_KEY;
              
          protected String separatorKey = DEFAULT_SEPARATOR_KEY;

              
          public void setPathKey(String pathKey) 
              {
                  
          this.pathKey = pathKey;
              }

              
          public void setEncodingKey(String encodingKey)
              {
                  
          this.encodingKey = encodingKey;
              }

              
          public void setSeparatorKey(String separatorKey)
              {
                  
          this.separatorKey = separatorKey;
              }

              @Override
              
          public String intercept(ActionInvocation invocation) throws Exception
              {
                  ActionConfig config 
          = invocation.getProxy().getConfig();

                  Map
          <String, String> parameters = config.getParams();
                  
          if (parameters.containsKey(pathKey))
                  {
                      String path 
          = parameters.get(pathKey);
                      String encoding 
          = parameters.get(encodingKey);
                      String separator 
          = parameters.get(separatorKey);
                      
          if (encoding == null)
                          encoding 
          = "UTF-8";
                      
          if (separator == null)
                          separator 
          = "";
                      path 
          = invocation.getAction().getClass().getResource(path)
                              .getPath();
                      Properties properties 
          = new Properties();
                      InputStream is 
          = new FileInputStream(path);
                      java.io.Reader reader 
          = new java.io.InputStreamReader(is, encoding);
                      
                      properties.load(reader);
                      ActionContext ac 
          = invocation.getInvocationContext();
                      ValueStack stack 
          = ac.getValueStack();
                      System.out.println(stack.hashCode());
                      Enumeration names 
          = properties.propertyNames();
                      
          while (names.hasMoreElements())
                      {
                          
          //  下面會使用setValue方法修改ValueStack對象中的相應(yīng)屬性值
                          String name = names.nextElement().toString();
                          
          if (!name.contains("."))
                              stack.setValue(name, properties.get(name)); 

                          String newName 
          = null;
                          newName 
          = parameters.get(name.replaceAll("\\."""));
                          
          if (newName != null)
                              stack.setValue(newName, properties.get(name));

                          
          if (!separator.equals(""))
                          {
                              newName 
          = name.replaceAll("\\.""");
                              stack.setValue(newName, properties.get(name));
                          }               
                          newName 
          = name.replaceAll("\\.", separator);
                          stack.setValue(newName, properties.get(name));
                      } 
                  }
                  
          return invocation.invoke();
              }
          }

          用于測試的Action類的源代碼:

          package actions;

          public class MyAction
          {
              
          private String name;
              
          private Integer price;
              
          private String log4jappenderstdout;
              
          private String log4j_rootLogger;
              
          private String conversionPattern;

              
          public String getName()
              {
                  
          return name;
              }

              
          public void setName(String name)
              {
                  
          this.name = name;
              }

              
          public Integer getPrice()
              {
                  
          return price;
              }

              
          public void setPrice(Integer price)
              {
                  
          this.price = price;
              }

              
          public String getLog4jappenderstdout()
              {
                  
          return log4jappenderstdout;
              }

              
          public void setLog4jappenderstdout(String log4jappenderstdout)
              {
                  
          this.log4jappenderstdout = log4jappenderstdout;
              }

              
          public String getLog4j_rootLogger()
              {
                  
          return log4j_rootLogger;
              }

              
          public void setLog4j_rootLogger(String log4j_rootLogger)
              {
                  
          this.log4j_rootLogger = log4j_rootLogger;
              }

              
          public String getConversionPattern()
              {
                  
          return conversionPattern;
              }

              
          public void setConversionPattern(String conversionPattern)
              {
                  
          this.conversionPattern = conversionPattern;
              }

              
          public String execute()
              {
                  System.out.println(
          "name:" + name);
                  System.out.println(
          "price:" + price);
                  System.out.println(
          "log4jappenderstdout:" + log4jappenderstdout);
                  System.out.println(
          "log4j_rootLogger:" + log4j_rootLogger);
                  System.out.println(
          "conversionPattern:" + conversionPattern);
                  
          return null;
              }
          }

          Action類的配置代碼如:

          <?xml version="1.0" encoding="UTF-8" ?>
          <!DOCTYPE struts PUBLIC
              "-//Apache Software Foundation//DTD Struts Configuration 2.1//EN"
              "http://struts.apache.org/dtds/struts-2.1.dtd"
          >
          <struts>
              
          <package name="struts" extends="struts-default">

                  
          <interceptors>
                      
          <interceptor name="property"
                          class
          ="interceptors.PropertyInterceptor" />
                      
          <interceptor-stack name="myStack">
                          
          <interceptor-ref name="defaultStack" />
                          
          <interceptor-ref name="property" />
                      
          </interceptor-stack>
                  
          </interceptors>
                  
          <action name="test" class="actions.MyAction">
                      
          <interceptor-ref name="myStack" />
                      
          <param name="path">/log4j.properties</param>
                      
          <param name="encoding">UTF-8</param>
                      
          <param name="separator">_</param>
                      
          <param name="log4jappenderstdoutlayoutConversionPattern">
                          conversionPattern
                      
          </param>

                  
          </action>
              
          </package>
          </struts>

            請將log4j.properties文件復(fù)制到WEB-INF\classes目錄,并在該文件中加入name和price屬性。

          測試結(jié)果:

          name:中國
          price:
          34
          log4jappenderstdout:org.apache.log4j.ConsoleAppender
          log4j_rootLogger:error
          , stdout
          conversionPattern:%d{ABSOLUTE} %5p %c{
          1}:%L - %m%n

              由于property攔截器在defaultStack后引用,因此,在該攔截器中設(shè)置的屬性值是最終結(jié)果,如果將property攔截器放在defaultStack前面(將兩個<interceptor-ref>元素掉換一下),就可以通過同名勝Action配置參數(shù)或請求參數(shù)來干預(yù)最終究輸出結(jié)果了。

          下一篇:Struts 2雜談(2):如何向標(biāo)簽文件中的Struts 2標(biāo)簽傳遞參數(shù)值



          Android開發(fā)完全講義(第2版)(本書版權(quán)已輸出到臺灣)

          http://product.dangdang.com/product.aspx?product_id=22741502



          Android高薪之路:Android程序員面試寶典 http://book.360buy.com/10970314.html


          新浪微博:http://t.sina.com.cn/androidguy   昵稱:李寧_Lining

          posted on 2009-02-11 22:22 銀河使者 閱讀(5733) 評論(4)  編輯  收藏 所屬分類: Struts2javaweb 原創(chuàng)

          評論

          # re: Struts 2雜談(1):ValueStack對象的傳送帶機(jī)制  回復(fù)  更多評論   

          Very good ,我也可以用invocation.getAction();取得Action對象來干預(yù)里面屬性的值。
          2009-02-12 15:45 | wjywilliam

          # re: Struts 2雜談(1):ValueStack對象的傳送帶機(jī)制  回復(fù)  更多評論   

          @wjywilliam
          沒錯,可以通過invocation.getAction()獲得Action對象的屬性,但并不建議這么做,使用ValueStack接口的setValue和findValue方法更容易實(shí)現(xiàn)設(shè)置和獲得Action對象的屬性值的工作。
          2009-02-12 16:08 | 銀河使者

          # re: Struts 2雜談(1):ValueStack對象的傳送帶機(jī)制  回復(fù)  更多評論   

          寫得相當(dāng)不錯,很平易近人,比網(wǎng)上有些故做高深的文章好得多。
          2009-06-15 13:40 | whoiam8485

          # re: Struts 2雜談(1):ValueStack對象的傳送帶機(jī)制  回復(fù)  更多評論   

          中國和34是怎么來的?
          2013-08-07 17:45 | 飛過天涯海角
          主站蜘蛛池模板: 郧西县| 揭西县| 内江市| 鄂托克旗| 新巴尔虎左旗| 修文县| 广汉市| 梓潼县| 衡水市| 盐城市| 九龙坡区| 金秀| 南召县| 宜城市| 湖北省| 永城市| 沈丘县| 乐陵市| 樟树市| 资兴市| 东平县| 左权县| 长治市| 双柏县| 无棣县| 怀柔区| 图片| 邛崃市| 准格尔旗| 布拖县| 大悟县| 商都县| 海南省| 衡水市| 大渡口区| 晋城| 封丘县| 大冶市| 云龙县| 大关县| 闽清县|