隨筆:93 文章:11 評論:22 引用:0
          首頁 發新隨筆
          發新文章 聯系 聚合管理

          摘自http://blog.csdn.net/dl88250/archive/2007/10/25/1843813.aspx
          Java Logging API是sun公司于2002年5月正式發布的。它是自J2SE 1.4版本開始提供的一個新的應用程序接口。它能夠很方便地控制和輸出日志信息到文件,控制臺或其它用戶定義的地方,如數據庫,電子郵件等。所以它是為最 終用戶,系統管理員,軟件服務工程師和開發人員提供的一種捕捉安全漏洞,檢查配置正確性,跟蹤調查系統運行瓶頸和調查系統運行錯誤的工具。
          Java Logging API的設計目標是要:
          1. 能夠在運行時啟動或關閉日志功能;
          2. 能夠非常精密地控制日志,即能夠啟動或關閉日志的某個個別功能;
          3. 能夠在運行時注冊日志服務,當然也可以注冊新的第三方日志服務;
          4. 能夠提供連接服務,使Java Logging API能與現存的日志系統(如操作系統的日志功能)連接;
          5. 能夠支持顯示高優先度的信息給最終用戶。

          輸出日志
          由于Java Logging API提供了非常方便的接口,你可以在下面的例子里看到它的使用有多方便。
          例1:
          1
          2
          3
          4
          5
          6
          7
          8
          9
          10
          11
          12
          13
          14
          15
          16
          17
          18
          19
          package jdk14logger;
          import java.util.logging.Logger; // <= (1)
          public class HelloLogWorld
          {

          private static String name = HelloLogWorld.class.getName();
          private static Logger log = Logger.getLogger(name);// <= (2)

          public void sub()
          {
          log.info("Hello Logging World");// <= (3)
          }

          public static void main(String[] args)
          {
          HelloLogWorld logWorld = new HelloLogWorld();
          logWorld.sub();
          }
          }

          說明:
          1. Logger是Java Logging API中的一個類。在此之前,你必須確認你所使用的J2SE是1.4或更高版本。
          2. Logger.getLogger方法創建了一個Logger實例。每一個Logger實例都必須有個名稱,通常的做法是使用類名稱定義Logger實例。后面還會講到這樣做的原因。
          3. log.info方法用來輸出日志信息。
          執行例1你可以看到控制臺上輸出了日期時間,類名,方法名和Hello Logging World的信息。

          輸出的種類
          Java Logging API提供了七個級別用來控制輸出。這七個級別分別是:
          SEVERE (最高級別)
          WARNING
          INFO
          CONFIG
          FINE
          FINER
          FINEST (最低級別)
          與之對應,在Logger類中也為你預備好了這七個級別的輸出方法。下面是使用這幾種方法輸出日志信息的例子。
          例2:
          1
          2
          3
          4
          5
          6
          7
          8
          9
          10
          11
          12
          13
          14
          15
          16
          17
          18
          19
          20
          21
          22
          23
          24
          25
          26
          package jdk14logger;
          import java.util.logging.Logger;

          public class LevelTest
          {

          private static String name = HelloLogWorld.class.getName();
          private static Logger log = Logger.getLogger(name);

          public void sub()
          {
          log.severe("severe level");// <= (1)
          log.warning("warning level");// <= (2)
          log.info("info level");// <= (3)
          log.config("config level");// <= (4)
          log.fine("fine level");// <= (5)
          log.finer("finer level");// <= (6)
          log.finest("finest level");// <= (7)
          }

          public static void main(String[] args)
          {
          LevelTest test = new LevelTest();
          test.sub();
          }
          }


          執行例2你可能看到控制臺上只輸出了(1)-(3)的信息,(4)-(7)的信息并沒有如想象的那樣被輸出。這不要緊,繼續看下面的內容你就知道原因了。

          控制輸出
          上面例2中info以下的級別信息沒有被輸出是因為缺省日志輸出級別的設置是info,也就是說只有info或它以上的級別被輸出,它以下的級別不被輸 出。通過變更設置可以使輸出級別改變。變更輸出級別的方法有兩種,一是使用外部配置文件,二是使用程序編碼。通常都是使用第一種方法。缺省的外部配置文件 是JRE中lib/logging.properties文件。你可以打開這個文件,修改以下兩行為:
          .level= ALL
          java.util.logging.ConsoleHandler.level = ALL
          修改完后,再運行一次例2,這次(1)-(7)的內容就都輸出出來了。你可以修改輸出級別為以下任何值,試一試輸出有什么變化。
          OFF
          SEVERE
          WARNING
          INFO
          CONFIG
          FINE
          FINER
          FINEST
          ALL

          自定義的配置文件
          如果你不想使用系統提供的缺省配置文件lib/logging.properties,那么也可以使用自己定義的配置文件。使用自定義配置文件的方法有很 多種,比較方便的方法是通過定義系統屬性值java.util.logging.config.file來設置自定義配置文件。例如在執行例2時,使用下 面的命令:
          java -Djava.util.logging.config.file=mylogging.properties LevelTest
          其中mylogging.properties是你自定義的配置文件。如果需要,你還可以加上文件的路徑名。

          更多的輸出控制
          除了前面講到的七個輸出級別外,Logger類中還提供了以下三個便于程序員調試時使用的輸出信息方法:
          entering
          exiting
          throwing
          它們是與FINER相同級別的輸出,分別用于程序入口,出口和例外時的輸出。除此之外Logger類中還準備了一些輸出信息的方法,這些留待以后詳細介紹。

          輸出內容的本地化
          Java Logging API已經考慮到了國際化對應問題。在輸出信息上你可以使用ResourceBundle提供本地化的輸出信息。下面舉個例子說明。
          例3:
          1
          2
          3
          4
          5
          6
          7
          8
          9
          10
          11
          12
          13
          14
          15
          16
          17
          18
          19
          package jdk14logger;
          import java.util.logging.Logger;
          public class LocalTest {
          private static String name = HelloLogWorld.class.getName();
          private static Logger log = Logger.getLogger (name, "jdk14logger/LocalTest");<= (1)
          public void sub() {
          log.severe("level.severe");<= (2)
          log.warning("level.warning");<= (3)
          log.info("level.info");<= (4)
          log.config("level.config");<= (5)
          log.fine("level.fine");<= (6)
          log.finer("level.finer");<= (7)
          log.finest("level.finest");<= (8)
          }
          public static void main(String[] args) {
          LocalTest test = new LocalTest();
          test.sub();
          }
          }

          你可以比較一下例2和例3。可以看到例3的Logger.getLogger 方法調用中增加了一個傳參,并且(2)-(8)中的輸出內容也改變了。(1)中增加的字符串傳參就是使用ResourceBundle配置時的屬性文件 名。下面就需要建立這個屬性文件jdk14logger/LocalTest.properties,內容如下:
          level.severe=severe level
          level.warning=warning level
          level.info=info level
          level.config=config level
          level.fine=fine level
          level.finer=finer level
          level.finest=finest level
          現在運行例3可以看到輸出結果并不是(2)-(8)中定義的內容。或許你已經想到了,(2)-(8)中定義的實際上是local.properties文 件中的屬性鍵名,而輸出是這些屬性鍵名所對應的鍵值。那么或許你要問如果屬性鍵名在屬性文件中不存在怎么辦,答案很簡單,如果它不是屬性鍵名就一定是要輸 出的內容,所以就照原樣輸出了事。 
          posted @ 2009-02-19 23:00 redcoatjk 閱讀(1829) | 評論 (0)編輯 收藏
           
          載自http://kuangbaoxu.javaeye.com/blog/192804
          1. 代理模式主要有兩種:靜態代理和動態代理

          2. 靜態代理:

          比如要在輸出“HelloWorld”前打印一個字符串“Welcome”

          A:先定義一個接口類
          1package ttitfly.proxy;    
          2   
          3public interface HelloWorld {    
          4    public void print();    
          5//  public void say();    
          6}
           
          B: 定義一個該接口的實現類

          java 代碼
           1package ttitfly.proxy;    
           2   
           3public class HelloWorldImpl implements HelloWorld{    
           4   
           5    public void print(){    
           6        System.out.println("HelloWorld");    
           7    }
              
           8//  public void say(){    
           9//      System.out.println("Say Hello!");    
          10//  }    
          11}
              
          C:定義一個靜態代理類
           1package ttitfly.proxy;    
           2   
           3public class StaticProxy implements HelloWorld{    
           4   
           5    public HelloWorld helloWorld ;    
           6    public StaticProxy(HelloWorld helloWorld){    
           7        this.helloWorld = helloWorld;    
           8    }
              
           9        
          10    public void print(){    
          11        System.out.println("Welcome");    
          12        //相當于回調    
          13        helloWorld.print();    
          14    }
              
          15        
          16//  public void say(){    
          17//      //相當于回調    
          18//      helloWorld.say();    
          19//  }    
          20}
              
          D: 一個測試類:
           1package ttitfly.proxy;    
           2   
           3public class TestStaticProxy {    
           4   
           5    public static void main(String[] args){    
           6        HelloWorld helloWorld = new HelloWorldImpl();    
           7        StaticProxy staticProxy = new StaticProxy(helloWorld);    
           8        staticProxy.print();    
           9            
          10//      staticProxy.say();    
          11    }
              
          12}
              
          可以看出靜態代理類有一個很不爽的缺點:當如果接口加一個方法(把上面所有的代碼的注釋給去掉),所有的實現類和代理類里都需要做個實現。這就增加了代碼的復雜度。動態代理就可以避免這個缺點。 
          3 。動態代理

          動態代理與普通的代理相比較,最大的好處是接口中聲明的所有方法都被轉移到一個集中的方法中處理(invoke),這樣,在接口方法數量比較多的時候,我們可以進行靈活處理,而不需要像靜態代理那樣每一個方法進行中轉。

          動態代理類只能代理接口,代理類都需要實現InvocationHandler類,實現invoke方法。該invoke方法就是調用被代理接口的所有方法時需要調用的,該invoke方法返回的值是被代理接口的一個實現類

          代理類: 
           1package ttitfly.proxy;        
           2       
           3import java.lang.reflect.InvocationHandler;        
           4import java.lang.reflect.Method;        
           5import java.lang.reflect.Proxy;        
           6//動態代理類只能代理接口,代理類都需要實現InvocationHandler類,實現invoke方法。該invoke方法就是調用被代理接口的所有方法時需要調用的,該invoke方法返回的值是被代理接口的一個實現類        
           7public class DynamicProxy implements InvocationHandler{        
           8            
           9    private Object object;         
          10    //綁定關系,也就是關聯到哪個接口(與具體的實現類綁定)的哪些方法將被調用時,執行invoke方法。    
          11    //Proxy.newProxyInstance的第三個參數是表明這些被攔截的方法執行時需要執行哪個InvocationHandler的invoke方法    
          12    public Object bindRelation(Object object){         
          13        this.object = object;        
          14        return Proxy.newProxyInstance(object.getClass().getClassLoader(), object.getClass().getInterfaces(),this);         
          15    }
                   
          16    //攔截關聯的這個實現類的方法被調用時將被執行        
          17    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {         
          18        System.out.println("Welcome");        
          19        Object result = method.invoke(object, args);         
          20        return result;        
          21    }
                  
          22       
          23}
                  

          測試類:
           1package ttitfly.proxy;        
           2       
           3public class TestDynamicProxy {        
           4    public static void main(String[] args){        
           5        HelloWorld helloWorld = new HelloWorldImpl();        
           6        DynamicProxy dp = new DynamicProxy();        
           7        //在這里綁定的是HelloWorld,也就是HelloWorld是被代理接口。所以綁定關系時,需要傳遞一個HelloWorld的實現類的實例化對象。        
           8        HelloWorld helloWorld1 = (HelloWorld)dp.bindRelation(helloWorld);         
           9        helloWorld1.print();         
          10        helloWorld1.say();        
          11            
          12        //helloWorld2將不被攔截    
          13        HelloWorld helloWorld2 = new HelloWorldImpl();    
          14        helloWorld2.print();         
          15        helloWorld2.say();    
          16            
          17    }
                  
          18}
                  
          在測試類里調用實現類的print和say方法,因為代理類里代理了HelloWorld的所有方法。所以就不需要像靜態代理類那樣一一實現了。
          [本來想自己寫個類似的東西,不過發現javaeye的這篇寫的已經很好了.轉載過來學習一下.
           javaeye的代碼copy功能真好用!.]





          posted @ 2009-02-17 18:40 redcoatjk 閱讀(374) | 評論 (1)編輯 收藏
           
          載自http://blog.csdn.net/icecityman/archive/2008/11/08/3256281.aspx

          Java程序在定義類時,除了使用class關鍵字標識之外,還可以在class之前增加若干類的修飾符來修飾限定所定義的類的特性。類的修飾符分為訪問控制符和非訪問控制符兩大類。修飾符之間的先后排列次序對類的性質沒有任何影響。

          一. 非訪問修飾符。
           1. 抽象類:
              凡是用abstract修飾符修飾的類被稱為抽象類。抽象類就是沒有具體對象的概念類。
              抽象類是一種經過優化的概念組織方式:把共同特點抽象出來;其后在描述和處理某一種具體對象時,就只需描述不同的特殊之處。這種組織方式使得所有的概念層次分明,簡潔洗練,非常符合人們日常的思維習慣。
              由于抽象類是它的所有子類的公共屬性的集合,所以使用抽象類的一個優點就是可以充分利用這些公共屬性來提高開發和維護程序的效率。
              值得一提的是,面向對象技術是要用更接近于人類思維方式的方法來處理實際問題,抽象類的設立就是這種思想的具體體現之一,它是模仿人類的思維模式的產物。

           2. 最終類:
              如果一個類被final修飾符所修飾和限定,說明這個類不可能有子類。
              被定義為final的類通常是一些有固定作用、用來完成某種標準功能的類。如Java系統定義好的用來實現網絡功能的InterAddress、Socket等類都是final類。
                 abstract和final修飾符不能同時修飾一個類,因為abstract類自身沒有具體對象,需要派生出子類后在創建子類的對象;而final類不可能有子類。這樣放在一起修飾就沒有意義了。

           3. 有些類的修飾符也可以用來修飾類中的成員變量或方法:
           (1)成員變量:是類和對象的靜態屬性,定義成員變量的操作就是說明變量或創建對象的操作。
             <1> 靜態成員變量:用static修飾符修飾的成員變量是僅屬于類的靜態成員變量。靜態成員變量是類中每個對象共享的成員變量。他們是類的成員變量,不屬于任何一個類的具體對象。是一個公共的存儲單元,任何一個類的對象訪問它時,取到的都是相同的數值。
             <2> 靜態初始化器:靜態初始化器是由關鍵字static引導的一對大括號括起的語句組。作用是:在加載時,初始化類的靜態成員變量。
                與構造函數相同,他們都是用來完成初始化的工作,但是靜態初始化器與構造函數有三點不同:
                 ①構造函數是對每個新創建的對象初始化,而靜態初始化器是對類自身進行初始化。
                 ②構造函數是在用new運算符產生新對象時由系統自動執行,而靜態初始化器則是在它所屬的類加載到內存時由系統調用執行。
                 ③不同于構造函數,靜態初始化器不是方法,沒有方法名、返回值和參數列表。
             <3> 最終成員變量:用final修飾的成員變量,實際上就是Java中的常量。
                用final修飾符說明常量時,需要注意以下幾點:
                ①需要說明常量的數據類型。
                ②需要同時指出常量的具體取值。
                ③因為所有類對象的常量成員,其數值都固定一致,為了節省空間,常量通常聲明為static。
             <4> 易失成員變量:如果一個成員變量被volatile修飾符所修飾,說明這個成員變量可能同時被幾個線程所控制和修改,即這個成員變量不僅僅被當前程序所掌握,在運行過程中可能在其他未知的程序操作影響和改變該成員變量的取值。在使用當中應該特別注意。
              通常,volatile用來修飾接受外部輸入的成員變量。如表示當前時間的變量將系統的后臺線程隨時修改,以保證程序中取到的總是最新的當前系統時間,所以可以把它定義為易失成員變量。

           (2)方法:是類的動態屬性,標志了類所具有的功能和操作。小括號是方法的標志。
             <1> 抽象方法:修飾符abstract修飾的抽象方法是一種僅有方法頭,而沒有具體的方法體和操作實現的方法。使用抽象方法的目的是使所有的子類,對外都呈現一個相同名字的方法,是一個統一的接口。所有的抽象方法,都必須存在于抽象類之中。
             <2> 靜態方法:用static修飾符修飾的方法,是屬于整個類的類方法,不用的是對象或實例的方法。調用這種方法時,應該使用類名作前綴;這種方法在內存中的代碼段將隨著類的定義而分配和裝載,不被任何一個對象專有;只能處理屬于整個類的成員變量。
             <3> 最終方法:用final修飾符修飾的類方法。功能和內部語句不能再更改的方法,不能再被繼承。
              注意:所有已被private修飾符限定為私有的方法,以及所有包含在final類中的方法,都被缺省地認為是final的。
             <4> 本地方法:用native修飾符聲明其他語言書寫方法體并具體實現方法功能的特殊的方法。這里的其他語言包括C/C++/FROTRAN/匯編等。由于native的方法的方法體使用其他語言在程序外部寫成,所以所有的native方法都沒有方法體,而用一個分號代替。
             <5> 同步方法:如果synchronized修飾的方法是一個類的方法(即static的方法),那么在被調用執行前,將把系統類Class中對應當前類的對象加鎖。如果synchronized修飾的是一個對象的方法(未用static修飾的方法),則這個方法在被調用執行前,將把當前對象加鎖。Synchronized修飾符主要用于多線程共存的程序中的協調和同步。


          二. 訪問控制符。
              訪問控制符是一組限定類、成員變量或方法是否可以被程序里的其他部分訪問和調用的修飾符。類的訪問控制符只有一個public,成員變量和方法的訪問控制符有四個,分別是public、private、protected、private protected,另外還有一種沒有定義專門的訪問控制符的缺省情況。
           1. 公有訪問控制符public:
                Java的類是通過包的概念來組織的,包氏類的一個松散的集合。處于同一個包中的類可以不需要任何說明而方便的互相訪問和引用,而對于不同包中的類,則不行。但當一個類被聲明為public時,他就具有了被其他包中的類訪問的可能性,只要這些其他包中的類在程序中使用import語句引入public類,就可以訪問和引用這個類。
              類中被設定為public的方法是這個類對外的接口部分,避免了程序的其他部分直接去操作類內的數據,這實際就是數據封裝思想的體現。
              每個Java程序的主類都必須是public類,也是基于相同的原因。
              用public修飾的類的成員變量稱為公共成員變量。如果公共成員變量屬于公共類,則它能被所有的其他類所引用。public修飾符會造成安全性的數據封裝性下降,所以一般應減少public成員變量的使用。

           2. 缺省訪問控制符:
              缺省訪問控制權規定,該類只能被同一個包中的類訪問和引用,而不可以被其他包中的類使用,這種訪問特性又稱為包訪問性。
              同樣道理,類內的成員變量或方法如果美育訪問控制符來限定,也就具有包訪問性。
              簡單說,定義在同一個程序中的所有類屬于一個包。

           3. 私有訪問控制符private:
              用private修飾得成員變量或方法只能被該類自身所訪問和修改,而且不能被任何其他類(包括該類的子類)來獲取和引用。private修飾符用來聲明那些類的私有成員,它提供了最高的保護級別。

           4. 保護訪問控制符protected:
              用protected修飾的成員變量可以被三種類所引用:該類自身、與它在同一個包中的其它類、在其他包中的該類的子類。使用protected修飾符的主要作用是允許其他包中該類的子類來訪問父類的特定屬性。

           5. 私有保護訪問控制符 private protected :
              用private protected修飾的成員變量可以被兩種類訪問和引用,一種是該類本身,一種是該類的所有子類。把同一個包內的非子類排除在可訪問的范圍之外,使得成員變量更專于具有明確繼承關系的類,而不是松散地組合在一起的包。

          posted @ 2009-02-10 12:50 redcoatjk 閱讀(521) | 評論 (0)編輯 收藏
           

          一、攔截器的實現

               實現一個攔截器非常簡單。實際上,一個攔截器就是一個普通的類,只是這個類必須實現com.opensymphony.xwork2.interceptor.Interceptor接口。Interceptor接口有如下三個方法:


          public interface Interceptor extends Serializable 
          {
              
          void destroy();
              
          void init();
              String intercept(ActionInvocation invocation
          throws Exception;
          }


           

          其中initdestroy方法只在攔截器加載和釋放(都由Struts2自身處理)時執行一次。而intercept方法在每次訪問動作時都會被調用。Struts2在調用攔截器時,每個攔截器類只有一個對象實例,而所有引用這個攔截器的動作都共享這一個攔截器類的對象實例,因此,在實現Interceptor接口的類中如果使用類變量,要注意同步問題。

          下面我們來實現一個簡單的攔截器,這個攔截器通過請求參數action指定一個攔截器類中的方法,并調用這個方法(我們可以使用這個攔截器對某一特定的動作進行預處理)。如果方法不存在,或是action參數不存在,則繼續執行下面的代碼。如下面的URL

          http://localhost:8080/struts2/test/interceptor.action?action=test

          訪問上面的url后,攔截器會就會調用攔截器中的test方法,如果這個方法不存在,則調用invocation.invoke方法,invoke方法和Servlet過濾器中調用FilterChain.doFilter方法類似,如果在當前攔截器后面還有其他的攔截器,則invoke方法就是調用后面攔截器的intercept方法,否則,invoke會調用Action類的execute方法(或其他的執行方法)。

          下面我們先來實現一個攔截器的父類ActionInterceptor。這個類主要實現了根據action參數值來調用方法的功能,代碼如下:


           

          package interceptor;

          import com.opensymphony.xwork2.ActionInvocation;
          import com.opensymphony.xwork2.interceptor.Interceptor;
          import javax.servlet.http.*;
          import org.apache.struts2.*;

          public class ActionInterceptor implements Interceptor
          {
              
          protected final String INVOKE = "##invoke";
             
              
          public void destroy()
              {
                  System.out.println(
          "destroy");
              }

              
          public void init()
              {
                  System.out.println(
          "init");
              }

              
          public String intercept(ActionInvocation invocationthrows Exception
              {    
                  HttpServletRequest request 
          = ServletActionContext.getRequest();
                  String action 
          = request.getParameter("action");
                  System.out.println(
          this.hashCode());
                  
          if (action != null)
                  {
                      
          try
                      {
                          java.lang.reflect.Method method 
          = this.getClass().getMethod(action);
                          String result 
          = (String)method.invoke(this);
                          
          if(result != null)
                          {
                              
          if(!result.equals(INVOKE))
                                  
          return result;
                          }
                          
          else
                              
          return null;
                      }
                      
          catch (Exception e)
                      {
                      }
                  }
                  
          return invocation.invoke();
              }
          }


           

          從上面代碼中的intercept方法可以看出,在調用action所指定的方法后,來判斷返回值。可能發生的情況有三種:

          1.        返回值為null,執行return null

          2.        返回值為INVOKE,執行return invockation.invoke()

          3.        其他情況,執行return result result表示指定方法的返回值,如上面代碼所示。

              在實現完上面的攔截器父類后,任何繼承于ActionInterceptor類的攔截器都可以自動根據action的參數值調用自身的相應方法。下面我們來實現一個擁有兩個動作方法testprint的攔截器類。代碼如下:


          package interceptor;

          import javax.servlet.http.HttpServletResponse;
          import org.apache.struts2.ServletActionContext;

          public class MultiMethodInterceptor extends ActionInterceptor
          {
              
          public String test() throws Exception
              {
                  HttpServletResponse response 
          = ServletActionContext.getResponse();
                  response.getWriter().println(
          "invoke test");
                  
          return this.INVOKE;
              }

              
          public String print() throws Exception
              {
                  HttpServletResponse response 
          = ServletActionContext.getResponse();
                  response.getWriter().println(
          "invoke print");

                  
          return null;
              }
          }


           

          test方法返回了INVOKE,因此,在執行完這個方法后,Struts2會接著調用其他攔截器的intercept方法或Action類的execute方法。而print方法在執行完后,只是返回了null,而不再調用其他的方法了,也就是訪問如下的url時,動作的execute方法將不會執行:

              http://localhost:8080/struts2/test/ddd.action?action=print

              下面我們來實現一個Action類,代碼如下:

          package action;

          import org.apache.struts2.*;
          import com.opensymphony.xwork2.ActionSupport;

          public class InterceptorAction extends ActionSupport
          {
              
          public String abcd() throws Exception
              {
                  ServletActionContext.getResponse().getWriter()
                          .println(
          "invoke abcd");
                  
          return null;
              }
          }


           

          在這個Action類中,只有一個abcd方法,實際上,這個方法相當于execute方法,在下面會設置動作的method屬性為abcd。下面我們來在struts.xml中定義攔截器類和動作,代碼如下:


           

          <?xml version="1.0" encoding="UTF-8" ?>
          <!DOCTYPE struts PUBLIC
              "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
              "http://struts.apache.org/dtds/struts-2.0.dtd"
          >
          <struts>
              
          <package name="demo" extends="struts-default" namespace="/test">
                  
          <interceptors>
                      
          <interceptor name="method" class="interceptor.MultiMethodInterceptor" />
                          
          <interceptor-stack name="methodStack">
                              
          <interceptor-ref name="method" />
                              
          <interceptor-ref name="defaultStack" />
                          
          </interceptor-stack>
                  
          </interceptors>

                  
          <action name="interceptor" class="action.InterceptorAction" method="abcd">
                      
          <interceptor-ref name="methodStack" />
                  
          </action>
              
          </package>
          </struts>


           

          在配置上面的methodStack攔截器時要注意,最好在后面引用defaultStack,否則很多通過攔截器提供的功能將失去。

          OK,現在訪問如下的URL

              http://localhost:8080/struts2/test/ddd.action?action=test

          在瀏覽器中將會出現如下的字符串:

              invoke test

          invoke abcd

          而如果訪問http://localhost:8080/struts2/test/ddd.action?action=print,將會只出現如下的字符串:

              invoke print

          大家可以看出,訪問這個url時并沒有調用abcd方法。如果隨便指定的action值的話,則只調用abcd方法,如訪問http://localhost:8080/struts2/test/ddd.action?action=aaa,就只會輸出invoke abcd


          二、攔截器的參數

             
          我們在使用很多Struts2內置的攔截器時會發現有很多攔截器都帶參數,當然。我們自己做的攔截器也可以加上同樣的參數。有兩個參數比較常用,這兩個參數是includeMethodsexcludeMethods,其中includeMethods指定了攔截器要調用的Action類的執行方法(默認是execute),也就是說,只有在includeMethods中指定的方法才會被Struts2調用,而excludeMethods恰恰相反,在這個參數中指定的執行方法不會被Struts2調用。如果有多個方法,中間用逗號(,)分隔。在Struts2中提供了一個抽象類來處理這兩個參數。這個類如下:

          com.opensymphony.xwork2.interceptor.MethodFilterInterceptor

             
          如有繼承于這個類的攔截器類都會自動處理includeMethodsexcludeMethods參數,如下面的攔截器類所示:

          package interceptor;

          import com.opensymphony.xwork2.ActionInvocation;
          import com.opensymphony.xwork2.interceptor.*;

          public class MyFilterInterceptor extends MethodFilterInterceptor
          {
              
          private String name;
              
          public String getName()
              {
                  
          return name;
              }
              
          public void setName(String name)
              {
                  
          this.name = name;
              }
              @Override
              
          protected String doIntercept(ActionInvocation invocationthrows Exception
              {
                  System.out.println(
          "doIntercept");
                  System.out.println(name);
                  
          return invocation.invoke();
              }
          }


              MethodFilterInterceptor的子類需要實現doIntercept方法(相當于Interceptorintercept方法),如上面代碼所示。在上面的代碼中還有一個name屬性,是為了讀取攔截器的name屬性而設置的,如下面的配置代碼所示:


          <?xml version="1.0" encoding="UTF-8" ?>
          <!DOCTYPE struts PUBLIC
              "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
              "http://struts.apache.org/dtds/struts-2.0.dtd"
          >
          <struts>
              
          <package name="demo" extends="struts-default" namespace="/test">
                  
          <interceptors>
                      
          <interceptor name="method" class="interceptor.MultiMethodInterceptor" />
                          
          <interceptor name="filter"
                              class
          ="interceptor.MyFilterInterceptor">
                              
          <param name="includeMethods">abcd</param>
                              
          <param name="name">中國</param>
                          
          </interceptor>
                          
          <interceptor-stack name="methodStack">
                              
          <interceptor-ref name="method" />
                              
          <interceptor-ref name="filter" />
                              
          <interceptor-ref name="defaultStack" />
                          
          </interceptor-stack>
                  
          </interceptors>

                  
          <action name="interceptor" class="action.InterceptorAction" method="abcd">
                      
          <interceptor-ref name="methodStack" />
                  
          </action>
              
          </package>
          </struts>


              再次訪問http://localhost:8080/struts2/test/ddd.action?action=test, Struts2就會調用MyFilterInterceptordoIntercept方法來輸出name屬性值。如果將上面的includeMethods參數值中的abcd去掉,則Action類的abcd方法不會被執行。

          posted @ 2008-12-28 22:37 redcoatjk 閱讀(353) | 評論 (0)編輯 收藏
           
           WebWork截獲Action請求,在Action執行之前或之后調用攔截器方法。這樣,可以用插拔的方式將功能注入Action中。WebWork框架的很多功能都是以攔截器的形式提供出來。例如:參數組裝,驗證,國際化,文件上傳等等。

          1. 一個攔截器就是在xwork.xml文件中定義的一個無狀態Java類,它至少要實現XWork的com.opensymphony.xwork.interceptor.Interceptor接口。代碼如下:

          public interface Interceptor extends Serializable {

          void destroy();

          void init();

          String intercept(ActionInvocation invocation) throws Exception;

          }

          2. 實現Interceptor接口的攔截器,代碼部分在intercept方法中實現。在intercept方法中,可以直接返回一個Result字符串,這樣整個執行直接“短路”,這時Action的execute方法也不會執行(一般很少會這么用)。所以,一般都會在這個方法里調用參數對象invocation的invoke方法,并返回這個方法執行的結果。這樣會持續執行后面的攔截器方法以及Action的execute方法等。

          3. 大部分的時候,攔截器直接繼承WebWork的抽象類 com.opensymphony.xwork.interceptor.AroundInterceptor就可以了。這時,需要實現它的before 和after方法。Before方法會在Action執行之前調用,after方法在Action執行之后調用。

          4. 攔截器的執行順序。我們可將多個攔截器放一起組裝成一個攔截器棧。這樣攔截器會按照棧的順序由上而下執行before方法,所有before方法執行結束,再執行Action的方法,執行Result的方法,再返回執行結果,最后再從下而上執行攔截器的after方法


          5. 攔截器的過濾功能。我們通常會在應用中使用一個通用的定義多個攔截器的攔截器棧。但有些Action方法在調用的時候,不需要要其中的部分攔截器。這時,我們就可以使用攔截器過濾功能。如果攔截器要擁有過濾功能,必須實現抽象類 com.opensymphony.xwork.interceptor.MethodFilterInterceptor。這樣,攔截器在定義的時候或者在Action引用攔截器棧的時候,我們就可以指定哪些Action方法是需要過濾的,哪些Action是不需要過濾的。
            攔截器可以將任意代碼包含在調用棧中活動執行前或之后, 它可以極大的簡化代碼同時提供增強代碼復用能力. XWork和WebWork的許多特性多作為攔截器實現, 可以和你自己的攔截器一起通過外部配置任意指定順序并配置在任意活動上.
            換言之, 當你訪問一個*.action的地址, WebWork的 class="monospaced">ServletDispatcher執行一個活動調用. 在活動執行前, 這一調用可以被另一個對象截取, 這個對象就稱為攔截器. 要想在一個活動執行之前(或之后)設置一個攔截器, 只需正確配置xwork.xml, 如下例所示:

          攔截器配置:
          <action name="formProcessing" class="lesson04_01_01.FormProcessingAction">
          <result name="input" type="dispatcher">ex01-index.jsp</result>
          <result name="success" type="dispatcher">ex01-success.jsp</result>
          <interceptor-ref name="validationWorkflowStack" />
          </action>
            名為formProcessing的Action使用了validationWorkflowStack. 它是一個截取器棧, 棧中按照截取器的執行順序進行組織. 這個截取器棧定義在webwork-default.xml, 這樣我們需要做的就是在活動配置的<interceptor-ref />或包配置中的<default-interceptor-ref />中聲明, 就像:

          攔截器配置:
          <!DOCTYPE xwork PUBLIC "-//OpenSymphony Group//XWork 1.0//EN"
          "http://www.opensymphony.com/xwork/xwork-1.0.dtd">


          <xwork>
          <!-- Include webwork defaults (from WebWork JAR). -->
          <include file="webwork-default.xml" />

          <!-- Configuration for the default package. -->
          <package name="default" extends="webwork-default">
          <!-- Default interceptor stack. -->
          <default-interceptor-ref name="defaultStack" />

          <!-- Action: HelloWebWorldAction. -->
          <action name="helloWebWorld" class="lesson03.HelloWebWorldAction">
          <result name="success" type="dispatcher">ex01-success.jsp</result>
          </action>
          </package>
          </xwork>

          -------------------------------------------------------
          寫個示例,實現在interceptor中判斷當前時間,返回問候語句,比如“Good afternoon”
          1.xwork_interceptor.xml
          <!DOCTYPE xwork PUBLIC "-//OpenSymphony Group//XWork 1.1.1//EN" "http://www.opensymphony.com/xwork/xwork-1.1.1.dtd">

          <xwork>

          <package name="hello1" extends="webwork-default">
          <!-- 在action和result code之間建立了聯系-->
          <interceptors>
          <interceptor name="greetingInterceptor" class="com.vstsoft.action.GreetingInterceptor" />
          </interceptors>
          <action name="greeting" class="com.vstsoft.action.GreetingAction">
          <interceptor-ref name="greetingInterceptor" />
          <result name="success">/success.jsp</result>
          <result name="input">/error.jsp</result>
          </action>
          </package>
          </xwork>
          2.GreetingAction
          package com.vstsoft.action;

          import com.opensymphony.xwork.Action;

          public class GreetingAction implements Action {

          public String execute(){
          // TODO Auto-generated method stub
          for(int i=0;i<10;i++){
          System.out.println(i);
          }
          return SUCCESS;//INPUT對應于xwork.xml中的resultcode='success'
          }

          }
          3.GreetingInterceptor
          package com.vstsoft.action;

          import java.util.Calendar;
          import com.opensymphony.xwork.interceptor.Interceptor;
          import com.opensymphony.xwork.ActionInvocation;

          public class GreetingInterceptor implements Interceptor {
          public void init() { }
          public void destroy() { }
          public String intercept(ActionInvocation invocation) throws Exception {
          Calendar calendar = Calendar.getInstance();
          int hour = calendar.get(Calendar.HOUR_OF_DAY);
          String greeting = (hour < 6) ? "Good evening" :
          ((hour < 12) ? "Good morning":
          ((hour < 18) ? "Good afternoon": "Good evening"));

          invocation.getInvocationContext().getSession().put("greeting", greeting);

          String result = invocation.invoke();

          return result;
          }
          }
          4.success.jsp
          <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
          <%@ taglib prefix="ww" uri="/webwork"%>
          <%String path = request.getContextPath();
          String basePath = request.getScheme() + "://"
          + request.getServerName() + ":" + request.getServerPort()
          + path + "/";
          %>


          <html>
          <head>
          <title>Say Hello</title>
          </head>
          <body>
          <font color="red"><%=session.getAttribute("greeting")%></red>
          </body>
          </html>
          posted @ 2008-12-28 22:16 redcoatjk 閱讀(715) | 評論 (0)編輯 收藏
           

          摘自http://dev.rdxx.com/NET/NETOther/2005-7/27/120335366.shtml
          WML教程1:從第一個實際應用全面了解WML

          學習自然語言的最好方法就是溶入相應的語言環境在交流中學習,學習一種編程語言的最好方法就是看例程。為了幫助大家建立WML應用的第一印象,所以請大家先看第一個例子:

          <?xml version="1.0"?>
          <!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN"
          "http://www.wapforum.org/DTD/wml_1.1.xml">
          <wml>
           <template>
             <do type="prev" label="back">
               <prev/>
               <!--provide a button you can clink to back a step-->
             </do>
           </template>
          <card id="friends" title="Hot link">
           <p>
             <a href="Sina'>http://wap.sian.com.cn/">Sina WAP</a><br/>
             <a href="#nextcard">Next Card</a>
           </p>
          </card>
          <card id="nextcard">
           <p>
            this is the second card.
           </p>
          </card>
          </wml>

          通過以上示例大家應該了解到以下內容:

          1、語法:WML的語法與HTML相似,仍然是一種標記語言,而且延續了xML語法規則

          2、元素:在XML和WML 語言中,語言的基本元素稱之為"標簽"
            標簽必須被 < 和 > 括起來。
            大多數標簽都包括"起""止"兩部分,例如:<p>…</p>
            某些特殊標簽可以只有一個標簽,但是必須有結束標記,例如:<prev/>

          3、屬性:XML語言的標簽可以包含很多屬性,給標簽提供必要的附加信息
            屬性內容通常在起始標簽內使用
            屬性只作為參數為標簽提供必要的信息,不會被瀏覽器顯示
            屬性的值需要被引號括起來,可以是單引號或者雙引號,引號可以成對嵌套使用
            例如:<card id="friends" title="Hot link">

          4、注釋
            注釋內容是方便制作者閱讀源代碼,不會被瀏覽器顯示
            WML不支持注釋嵌套
            例如:<!-- This is a comment. -->

          5、文檔結構
            WML文檔是由Card和Deck構成的,一個Deck是一個或多個Card的集合。在得到客戶終端的請求之后,WML從網絡上把Deck發送到客戶的瀏覽器,訪問者可以瀏覽Deck內包含的所有Card,而不必從網上單獨下載每一個Card。

          其他一些示例中沒有涉及到的基本內容:

          6、大小寫敏感
            無論是標簽元素還是屬性內容都是大小寫敏感的,這一點繼承了XML的嚴格特性,任何大小寫錯誤都可能導致訪問錯誤,這是WML制作者必須注意的問題。


          7、躲避語法檢查的方法-CDATA
            CDATA內的數據內容都會被當作文本來處理,從而避開語法檢查,直接作為文本顯示。
            示例:
            < ! [ CDATA [ this ia <b> a test ] ] >
            顯示結果為
            this ia <b> a test

          8、定義變量
            WML可以使用變量供瀏覽器和Script使用,通過在Deck中的一個Card上設置變量,其他Card不必重新設置就可以直接調用。

            變量的語法如下:
            $identifier
            $(identifier)
            $(identifier:conversion)

            如果變量內容包含空格就需要用圓括號括起來。由于變量在語法中有最高的優先級,包含變量聲明字符的字符串會被當作變量對待,所以如果要顯示$,就一定要連續使用兩個$。

            示例:
            <p> Your account has $$15.00 in it.</p>
            顯示結果為:Your account has $15.00 in it

            XML是一種語法非常嚴格的語言,WML也繼承了這種規則,任何地不規范語法都會導致錯誤。

          posted @ 2008-12-16 17:29 redcoatjk 閱讀(244) | 評論 (0)編輯 收藏
           
              這個筆記做的不錯.摘自javaeye:  http://chineseoa.javaeye.com/blog/127282 作者chineseoa
          ---------------------------------------------------------------
          第4章: 實現WebWork action

          action是WebWork編程的核心部分,負責:
          . 封裝和傳遞數據;
          . 邏輯處理

          一.  Action接口

               要求action實現com.opensymphony.xwork.Action接口,該接口有一唯一方法需要實現:

               String execute() throws Exception;

               該接口內置很多靜態屬性,可作為execute()方法的返回值;

          二.  ActionSupport基類

               該類包含了action能夠提供的許多可選服務的默認實現(實現了很多可選的接口),讓你更容易地開發自己的action類:

               1. action驗證:(com.opensymphony.xwork.Validateable接口)

                  該接口有一個唯一的方法,在該方法中可放入驗證代碼:

                  void validate()

                  該方法會被合適的intereceptor調用。調用過程如下:
                  . 執行validate()方法;
            . 如校驗action出錯(有錯誤消息增加至action),返回INPUT,否則執行這個action;

                  示例:

              @Override
              public void validate() {
                  if(name==null||name.trim().length()<1) {
                      addFieldError("name","Invalid name, please input again!");
                  }
                  if(password==null||password.trim().length()<1) {
                      addFieldError("password","Invalid password, please input again!");
                  }       
              }

               2. 顯示錯誤信息:(com.opensymphony.xwork.ValidationAware接口)

                  收集錯誤信息并將這些信息顯示給用戶。錯誤信息能夠依據class(action->actionErrors屬性)級別
                  (放入一個Collection->fieldErrors屬性)和字段級別(放入一個Map)進行收集。

                  一些常見方法:

                  void     addActionError(String anErrorMessage)
                          Add an Action-level error message to this Action.
                  void     addActionMessage(String aMessage)
                          Add an Action-level message to this Action.
                  void     addFieldError(String fieldName, String errorMessage)        

               3. 獲取用戶的locale: (public interface LocaleProvider接口)

                  該接口中擁有唯一的一個方法:

          Locale getLocale();

                  通過該方法獲得客戶端的語言和地區;

               4. 顯示本地化文本:(com.opensymphony.xwork.TextProvider接口)

                  該接口基本上由多個不同參數的getText()方法組成,getText()方法用于查找本地化信息文本。
                  默認情況下, 本地化信息存于和action同一個包下,同名的.properties結尾的文本。

                  示例:

                  cho4.LoginAction.java
                  ---------------------------------------------------------------------------
              @Override
              public void validate() {
                  if(name==null||name.trim().length()<1) {
                      addFieldError("name",getText("invalid.name"));     //通過getText獲取本地化信息
                  }
                  if(password==null||password.trim().length()<1) {
                      addFieldError("password",getText("invalid.password"));
                  }       
              }

                  ch04/LoginAction.properties
                  ---------------------------------------------------------------------------
                  invalid.name=Invalid name, please input again\!
                  invalid.password=Invalid password, please input again\!

          三.  使用ModelDriven action

               1. ???????????????????????/

           
          四.  通過ActionContext訪問數據

               1. 獲得HttpSession;

                  方法一:
                  Map session = ActionContext.getContext().getSession();
                  session.put("user",user);



                  方法二:(推薦使用)
                  public class Login extends ActionSupport implements SessionAware {
                         Map session;
              
                         public void setSession(Map session) {
                                this.session = session;
                         }
                         ...
                  }

                  實現SessionAware接口,該接口告知WebWork在action執行之前需要設置session Map。

               2. 訪問request和response

                  方法一:
                  ActionContext ctx = ActionContext.getContext();
                  HttpServletRequest req = ctx.get(ServletActionContext.HTTP_REQUEST);
                  HttpSession sessio = req.getSession();

                  方法二:
                  HttpServletRequest req = ServletActionContext.getRequest(); 
                  HttpSession sessio = req.getSession();

                  方法三:(推薦使用)
                  public class Login extends ActionSupport implements ServletRequestAware {
                         HttpServletRequest req;
              
                         public void setServletRequest(HttpServletRequest req) {
                                this.req = req;
                         }
                         ...
                  }     

          五.  處理文件上傳

               1. 使用request封裝類訪問上傳文件

                  使用MultiPartRequestWrapper對象,該對象會從request的余下部分中把文件正確地解析出來。

                  a. JSP頁面

                
                 
                   
                

                  b. action

                  public class FileUpload extends ActionSupport implements ServletRequestAware {
                      private HttpServletRequest req;
                     
                      @Override
                      public String execute() {
                          MultiPartRequestWrapper wrapper = (MultiPartRequestWrapper)req;
                          File doc = null;
                          try {
                                                  //獲得File對象
                              doc = wrapper.getFiles("doc")[0];
          //獲得內容類型
                              System.out.println("content type: "+ wrapper.getContentTypes("doc")[0]);
                                                  //獲得初始文件名
                              System.out.println("name: "+wrapper.getFileSystemNames("doc")[0]);
                          }catch(Exception e) {
                              e.printStackTrace();
                          }finally {
                              doc.delete();
                          }
                          return SUCCESS;
                      }

                      public HttpServletRequest getReq() {
                          return req;
                      }

                      public void setServletRequest(HttpServletRequest req) {
                          this.req = req;
                      }   
                     
                  }

               2. 自動文件上傳

                  WebWork提供了一個interceptor: FileUploadInterceptor, 它封裝了上傳文件的獲取和清理工作:
                  . 自動獲得request對象;
                  . 自動獲得request封裝對象;
                  . 自動清除File對象;

                  FileUploadInterceptor在webwork-default.xml中自動設好。通過使用FileUploadInterceptor, 可以把
                  上傳的文件(以及內容類型和文件名)看做是一般的表單參數。

                  html表單的input元素命名為doc, File字段也必須命名為doc,如多個文件則類型是 File[];
                  內容類型命名為[element]ContentType, 如多個文件則類型是 String[];
                  文件名命名為[element]FileName, 如多個文件則類型是 String[];

              import java.io.File;
              import com.opensymphony.xwork.ActionSupport;

              public class FileUpload extends ActionSupport {
                  private File doc;
                  private String docContentType;
                  private String docFileName;
                 
                  @Override
                  public String execute() {
                      System.out.println("doc: "+doc.getName());
                      System.out.println("docContentType: "+docContentType);
                      System.out.println("docFileName: "+docFileName);
                      return SUCCESS;
                  }

                  public void setDoc(File doc) {
                      this.doc = doc;
                  }

                  public void setDocContentType(String docContentType) {
                      this.docContentType = docContentType;
                  }

                  public void setDocFileName(String docFileName) {
                      this.docFileName = docFileName;
                  }   
              }     


               3. 配置設定

                  webwork.properties中有三個屬性可以對上傳文件的選項進行設定:

                  . webwork.multipart.parser: 定義底層的多部分 request 的解析器,可選值為 pell, cos和jakarta.
                                              默認值為pell, 建議選用jakarta。
                  . webwork.multipart.saveDir: 上傳文件WebWork臨時保存目錄。如沒設定,則存于javax.servlet.context.tempdir
                                              系統屬性指定的目錄中;
                  . webwork.multipart.maxSize: 上傳文件的大小上限,以字節為單位。默認值為2097152.
          posted @ 2008-12-16 11:39 redcoatjk 閱讀(253) | 評論 (0)編輯 收藏
           
          OGNL使用小結(一)
          最近一直使用struts2,表現層采用JSP,用的struts2標簽,支持OGNLOGNL中的# $ %使用場景:
          1、“#”主要有三種用途:
          • 訪問OGNL上下文和Action上下文,#相當于ActionContext.getContext();下表有幾個ActionContext中有用的屬性:
            名稱 作用 例子
            parameters 包含當前HTTP請求參數的Map #parameters.id[0]作用相當于request.getParameter("id")
            request 包含當前HttpServletRequest的屬性(attribute)的Map #request.userName相當于request.getAttribute("userName")
            session 包含當前HttpSession的屬性(attribute)的Map #session.userName相當于session.getAttribute("userName")
            application 包含當前應用的ServletContext的屬性(attribute)的Map #application.userName相當于application.getAttribute("userName")
            attr 用于按request > session > application順序訪問其屬性(attribute) #attr.userName相當于按順序在以上三個范圍(scope)內讀取userName屬性,直到找到為止
          • 用于過濾和投影(projecting)集合,如books.{?#this.price<100};
          • 構造Map,如#{'foo1':'bar1', 'foo2':'bar2'}。
          2、“%”符號的用途
          在標志的屬性為字符串類型時,計算OGNL表達式的值。例如在Ognl.jsp中加入以下代碼:
          [size=13px]<hr />
          <h3>%的用途</h3>
          <p><s:url value="#foobar['foo1']"
          /></p>
          <p><s:url value="%{#foobar['foo1']}"
          /></p>
          清單6 演示%用途的代碼片段
          3、“$”有兩個主要的用途
          • 用于在國際化資源文件中,引用OGNL表達式,例子請參考《在Struts 2.0中國際化(i18n)您的應用程序
          • 在Struts 2配置文件中,引用OGNL表達式,如 <action name="AddPhoto" class="addPhoto">
                        <interceptor-ref name="fileUploadStack" />
                        <result type="redirect">ListPhotos.action?albumId=${albumId}</result>
             </action>

          OGNL使用小結(二)

          1、OGNL除了支持所有的Java操作符外,還支持以下幾種:
             1、逗號,
               與C語言中的逗號操作符類似。
             2、花括號{}
               用于創建列表,元素之間用逗號分隔。
             3、in和not in
               用于判斷一個值是否在集合中。
          2、訪問靜態方法和靜態字段
            @class@method(args)     //調用靜態方法
            @class@field         //調用靜態字段
            其中class必須給出完整的類名(包括包名),如果省略class,那么默認使用的類是java.util.Math,如:
            @@min(5,3)
            @@max(5,3)
            @@PI
          3、索引訪問
            OGNL支持多種索引方式的訪問。
             1、數組和列表索引
               在OGNL中,數組和列表可以大致看成是一樣的。
               如:array[0]、list[0]。表達式:{’zhangsan’,'lisi’,'wangwu’}[1]等。
             2、JavaBean的索引屬性
               要使用索引屬性,需要提供兩對setter和getter方法,一對用于數組,一對用于數組中的元素。
               如:有一個索引屬性interest,它的getter和setter如下
               public String[] interest;
               public String[] getInterest(){ return interest;}
               public void setInterest(String[] interest){ this.interest=interest;}
               public String getInterest(int i){ return interest[i]}
               public void setInterest(int i, String newInterest){ interest[i]=newInterest;}
               對于表達式interest[2],OGNL可以正確解釋這個表達式,調用getInterest(2)方法。如果是設置的情況下,會調用setInterest(2,value)方法。
             3、OGNL對象的索引屬性
               JavaBean的索引屬性只能使用整型作為索引,OGNL擴展了索引屬性的概念,可以使用任意的對象來作為索引。
          4、對集合進行操作
            1、創建集合:
               創建列表
                 使用花括號將元素包含起來,元素之間使用逗號分隔。如{’zhangsan’,'lisi’,'wangwu’}
               創建數組
                 OGNL中創建數組與Java語言中創建數組類似。
               創建Map
                 Map使用特殊的語法來創建 #{”key”:value, ……}
                 如果想指定創建的Map類型,可以在左花括號前指定Map實現類的類名。如:
                 #@java.util.LinkedHashMap@{”key”:”value”,….}
                 Map通過key來訪問,如map["key"]或map.key。
            2、投影
               OGNL提供了一種簡單的方式在一個集合中對每一個元素聞調用相同的方法,或者抽取相同的屬性,并將結果保存為一個新的集合,稱之為投影。
               假如employees是一個包含了employee對象的列表,那么
                 #employees.{name}將返回所有雇員的名字的列表。
               在投影期間,使用#this變量來引用迭代中的當前元素。
                 如:objects.{#this instanceof String? #this: #this.toString()}
            3、選擇
               OGNL提供了一種簡單的方式來使用表達式從集合中選擇某些元素,并將結果保存到新的集合中,稱為選擇。
                如#employees.{?#this.salary>3000}
                將返回薪水大于3000的所有雇員的列表。
                 #employees.{^#this.salary>3000}
                將返回第一個薪水大于3000的雇員的列表。
                 #employees.{$#this.salary>3000}
                將返回最后一個薪水大于3000的雇員的列表。
          5、lambda表達式
            lambda表達式的語法是:   :[...]。OGNL中的lambda表達式只能使用一個參數,這個參數通過#this引用。
            如:
             #fact= :[ #this<=1 ? 1 : #this* #fact ( #this-1) ], #fact(30)
             #fib= :[#this==0 ? 0 : #this==1 ? 1 : #fib(#this-2)+#fib(#this-1)], #fib(11)
          posted @ 2008-12-15 16:39 redcoatjk 閱讀(3523) | 評論 (0)編輯 收藏
           

          摘自http://blog.csdn.net/liuyf8688/archive/2008/02/17/2100759.aspx
          1、Act.java 

          //接口類
          public interface Act {
              
          public void go();
          }

           2、Chinese.java

          //實體類
          public class Chinese {

              
          public void getAge() {
                  System.out.println(
          "entity class.");
              }


          }

          3、Person.java

          //抽象類可以實現接口,并且可以繼承實體類。
          public abstract class Person extends Chinese implements Act {

              
          public void run() {
                  System.out.println(
          "run");
              }


              
          public abstract void jump();

          }


          4、Test.java
          public class Test extends Person {

              
          // Act中的方法
              public void go() {
                  System.out.println(
          "go");
              }


              
          // Person中的方法
              public void jump() {
                  System.out.println(
          "jump");
              }


              
          public static void main(String[] args) {
                  Test t 
          = new Test();
                  t.go();
                  t.run();
                  t.jump();
                  t.getAge(); 
          // Chinese中的方法
              }

          }
          posted @ 2008-12-15 15:52 redcoatjk 閱讀(432) | 評論 (0)編輯 收藏
           
          JSTL中的EL語言是個災難,很難想象一個EL表達式不能去取復雜的屬性還不支持顯示的方法調用,類似list.get(20).getName(locale)。而且這個災難還非常流行,唉。

          幸好OGNL很好的解決了這個問題,而且在Tapestry,Webwork等框架下均已經內嵌了支持。

          表達式分類:
          1. 訪問屬性:如,user.name
          2. 訪問接口/方法:如,user.verify()
          3. 數組游標,如:users[2]

          常量:
          字符串、字符:一般使用單引號,也可以使用雙引號,支持所有的轉義字符
          數值:可以使用B表示BigDecimal,H表示BigInteger(不是十六進制)
          布爾:true或者false關鍵字
          空指針:null關鍵字

          訪問屬性:
          user.name

          索引位置:
          OGNL提供了一個很有趣的例子:array["length"],其中array作為根對象,調用其length方法是采用字符串的形式來進行的,等同于array["len" + "gth"],當然等價array.length。

          帶索引的屬性:
          someProperty[2] 可以用來getSomeProperty(2) or setSomeProperty(2, value),查找順序先找關聯數組的方法,再找帶索引參數的方法如下:
          public PropertyType[] getPropertyName()
          public void setPropertyName(PropertyType[] anArray)
          public PropertyType getPropertyName(int index)
          public void setPropertyName(int index, PropertyType value)

          OGNl擴展的帶索引的屬性:
          public PropertyType getPropertyName(IndexType index)
          public void setPropertyName(IndexType index, PropertyType value)
          比如:session.attribute("bar")

          調用方法:
          method( ensureLoaded(), name ),用逗號分隔參數,由于逗號在OGNL語言中有別的用處,所以在語法上需要小心。

          變量引用:
          使用#標注:#var = 99
          this是OGNL語言中內置的對象,用來表示當前表達式的變量。listeners.size().(#this > 100? 2*#this : 20+#this)

          括號:
          method( (ensureLoaded(), name) )這個表達式是調用一個參數的method方法。

          鏈接表達式:
          再看一次method( (ensureLoaded(), name) )
          其中ensureLoaded(), name的意思是:調用ensureLoaded方法,再調用#this.name,method方法的參數是name。

          集合構建
          { null,"Untitled" }——說明:最好看成數組,因為集合一般不會支持空元素。

          集合投射
          listeners.{delegate}返回所有listener對象的delegate對象。
          objects.{ #this instanceof String ? #this : #this.toString()}轉變為字符串對象

          集合選擇:
          listeners.{? #this instanceof ActionListener}——注意?的位置
          返回單個對象,首個:objects.{^ #this instanceof String },最后一個:objects.{$ #this instanceof String }

          創建對象:
          需要顯式的指定java package,如:new java.util.ArrayList()

          靜態方法、成員:
          @class@method(args),@class@field,同樣要指定class的全路徑

          表達式賦值:
          如果是AST,OGNL直接解析,如果是其他對象,則將其轉化對字符串交給AST解析。

          簡單的功能表達式:
          如遞歸表達式:#fact = :[#this<=1? 1 : #this*#fact(#this-1)], #fact(30H)

          集合的特殊屬性
          Collection:size, isEmpty
          List:iterator
          Map:keys, values
          注意:someMap["size"]可能得到someMap中對應key為"size"的對象, 而someMap.size得到someMap的大小.
          Set:iterator
          Iterator:next,hasNext
          Enumeration:next,hasNext,nextElement,hasMoreElements

          與JAVA的不同之處
          逗號:類似C的語法,逗號用于分割兩個不同的表達式
          花括號:用于創建list,元素可以為空
          in和not in:用于集合的contains測試
          posted @ 2008-12-15 15:10 redcoatjk 閱讀(331) | 評論 (0)編輯 收藏
          僅列出標題
          共8頁: 上一頁 1 2 3 4 5 6 7 8 下一頁 
          CALENDER
          <2025年6月>
          25262728293031
          1234567
          891011121314
          15161718192021
          22232425262728
          293012345

          常用鏈接

          留言簿(3)

          隨筆分類(22)

          隨筆檔案(76)

          文章分類(12)

          文章檔案(17)

          搜索

          •  

          積分與排名

          • 積分 - 250888
          • 排名 - 227

          最新評論

          評論排行榜


          Powered By: 博客園
          模板提供滬江博客

          主站蜘蛛池模板: 沧源| 澄迈县| 乐亭县| 南乐县| 贡嘎县| 胶南市| 武强县| 郓城县| 昌宁县| 浙江省| 蓝山县| 合江县| 色达县| 雷山县| 马龙县| 冷水江市| 南丰县| 安福县| 通河县| 抚顺县| 天气| 施甸县| 烟台市| 青海省| 莎车县| 叶城县| 永新县| 黔西县| 军事| 揭阳市| 静乐县| 江北区| 卢龙县| 宁德市| 株洲县| 共和县| 寿阳县| 岱山县| 金湖县| 新建县| 吴江市|