隨筆 - 71  文章 - 15  trackbacks - 0
          <2025年6月>
          25262728293031
          1234567
          891011121314
          15161718192021
          22232425262728
          293012345

          因為口渴,上帝創造了水;
          因為黑暗,上帝創造了火;
          因為我需要朋友,所以上帝讓你來到我身邊
          Click for Shaanxi xi'an, Shaanxi Forecast
          ╱◥█◣
            |田|田|
          ╬╬╬╬╬╬╬╬╬╬╬
          If only I have such a house!
          〖總在爬山 所以艱辛〗
          Email:myesjoy@yahoo.com.cn
          NickName:yesjoy
          MSN:myesjoy@hotmail.com
          QQ:150230516

          〖總在尋夢 所以苦痛〗

          常用鏈接

          留言簿(3)

          隨筆分類

          隨筆檔案

          文章分類

          文章檔案

          Hibernate在線

          Java友情

          Java認證

          linux經典

          OA系統

          Spring在線

          Structs在線

          專家專欄

          企業信息化

          大型設備共享系統

          工作流

          工作流產品

          網上購書

          搜索

          •  

          最新評論

          閱讀排行榜

          評論排行榜

          時間:2005-07-19
          作者:Harshad Oak
          瀏覽次數: 3473
          本文關鍵字:java,? 基礎,? Jakarta Commons?
          轉自:http://dev2dev.bea.com.cn/techdoc/2005071902.html
          作為企業Java開發人員,我們總是需要實現各種功能,如解析XML、使用HTTP、驗證輸入以及處理日期等。使用Jakarta Commons項目的目的在于創建負責處理所有此類常用任務的組件,從而節約時間,讓您集中精力處理核心業務解決方案。在本文中,我們將對Jakarta Commons 項目作簡單介紹,然后演示如何使用Jakarta Commons內的Lang組件來處理和簡化日常Java任務,比如字符串操作、使用日期和日歷、比較數據對象以及對象排序等。對于本文中的所有例子,我們都將使用最新的Lang版本(即2.1版本)。
            編者按:本文中的代碼是根據Commons Lang的 RC1版本 編寫的。其最終版不久將發行。

          Commons和Lang組件簡介
            Jakarta Commons 項目旨在實現可重用的 Java 組件。此項目包含數十個組件,用以簡化 Java 的開發,每個組件負責滿足一個特定需求。有大量的組件可用,且不僅限于在特定類型的Java應用程序中使用。

          項目分類在兩個部件中:

          1. Commons Proper:Commons Proper中的項目已可以投入實際使用。
          2. Commons Sandbox:sandbox內的項目仍然處于實驗階段。

            目前Commons Proper中有33個項目,Commons Sandbox中有22個項目,故而,任何一類Java項目都有其存在的意義。
            Lang組件是Jakarta Commons中較為流行的組件之一。Lang是要呈現在J2SE本身中的一組類。
            在本文中,我們將了解Lang最有用的一些功能。要注意的是,也可以只使用基本Java類來完成Lang的每個功能,但相對于自己學習、理解并編寫代碼而言,使用Lang要簡單得多。即使您能夠寫出最好的代碼,使用經過實驗和測試的Lang的功能會更快一些,能節省大量的檢查與測試時間。隨著Lang一起提供了特有的JUnit測試用例,Lang的使用極其廣泛,已經歷了其創建者和現實世界的種種考驗。
            Lang的一個重要特征是其簡單性。通常來說,新的Java組件十分復雜,要了解若干種技術才能使用這些組件。要理解組件的用途通常都很難,更別說實際使用該組件了。但對于大多數Commons組件而言,這就不是問題了。Lang一類組件使用方便,無論對Java初學者還是高級Java用戶都非常有用。
            如果在采用技術前需要有十足的保證,則請在保存您的Java軟件的目錄中搜索commons-lang*.jar。結果會讓您感到很意外。 TomcatStrutsHibernateSpringWebWork 等常見Java項目都使用Lang。
            首先讓我們看一看使用Lang進行大多數開發人員幾乎每天必須進行的操作——字符串操作。

          處理字符串
            無論應用程序是基于Swing、J2EE或J2ME的,它都必須使用字符串。所以,盡管在Java中使用字符串相當簡單,但是如果希望按照一定的條件修改和處理字符串,事情就不那么簡單了。您不得不在各種與字符串相關的類中尋找各種不常用的方法,然后想辦法使其協同工作,以獲得所需的結果。雖然有些Lang方法與J2SE中的某些方法重疊,但在大多數情況下,一個Lang方法就可提供各種類中的多個J2SE方法的功能,從而幫助您獲得所需的輸出。
            Lang組件有許多專門用于字符串操作的類。現在我們將使用一個簡單的Java應用程序來演示一些較為有用的類和方法。
            當應用程序接受用戶輸入時,由于用戶可能會存在輸入錯誤的情況,或用戶可能以各種格式輸入數據,而您希望只采用一種格式進行處理和存儲,則通常會涉及到對字符串進行操作。
            例如,您有一個帶輸入框的窗體,用戶在此輸入框內輸入許可證密鑰。您希望允許輸入1111-JAVA格式的密鑰。您必須進行以下操作:

          1. 檢查是否為空字符串。
          2. 忽略空格。
          3. 密鑰區分大小寫。
          4. 用“-”標記分隔密鑰字符串,然后檢查第一部分是否全部是數字,第二部分包含的字符是否只來自有效字符集“J”、“A”、“V”、“A”。
          5. 兩個部分均應有四個字符。
          6. 第一部分的第四個數字應該是“0”。

            只有當密鑰滿足所有這些條件時,應用程序才會查詢數據庫,檢查該密鑰是否合法。
            如果不花大量的時間瀏覽String、StringTokenizer和其他類的API文檔,您能完成以上的任務么?我不能,所以現在我將試著用Lang組件來管理驗證。
          清單1. checkLicenseKey()方法

          /**
           * Check if the key is valid
           * @param key license key value
           * @return true if key is valid, false otherwise.
           */
          public static boolean checkLicenseKey(String key){
              //checks if empty or null
              if(StringUtils.isBlank(key)){
                  return false;
              }
          
              //delete all white space
              key= StringUtils.deleteWhitespace(key);
          
              //Split String using the - separator
              String[] keySplit = StringUtils.split(key, "-");
          
              //check lengths of whole and parts
              if(keySplit.length != 2
                  || keySplit[0].length() != 4
                  || keySplit[1].length() != 4) {
                  return false;
              }
          
              //Check if first part is numeric
              if(!StringUtils.isNumeric(keySplit[0])){
                  return false;
              }
          
              //Check if second part contains only
              //the four characters 'J', 'A', 'V' and 'A'
              if(! StringUtils.containsOnly(keySplit[1]
                      ,new char[]{'J', 'A', 'V', 'A'})){
                  return false;
              }
          
              //Check if the fourth character
          	  //in the first part is a '0'
              if(StringUtils.indexOf(keySplit[0], '0') != 3){
                  return false;
              }
          
              //If all conditions are fulfilled, key is valid.
              return true;
          }
            在清單1中,我們使用了org.apache.commons.lang.StringUtils類中提供的各種方法,根據我們先前定義的所有規則對字符串進行驗證。isBlank()方法檢查字符串是否為空。deleteWhitespace()方法確保字符串不包含空格。然后我們使用split()方法對字符串進行分隔,并使用isNumeric()、containsOnly()和indexOf()方法對密鑰的兩部分進行驗證。
            請注意,盡管在J2SE中已經有了indexOf()方法,最好使用StringUtils中的indexOf()。與J2SE indexOf()方法不同,使用StringUtils indexOf()時無需擔心空指針的問題。觸發NullPointerException被認為是Java程序員最常犯的錯誤。Lang可以確保您不會犯同樣的錯誤。即使向indexOf()或其他此類方法傳遞一個null,都不會引發NullPointerException。indexOf()將直接返回-1。
            這樣,只需幾行簡單代碼,就可以實現相應的功能,而采用其他方法需要編寫很多行代碼,而且十分麻煩。如果使用清單2中所示的主方法執行checkLicenseKey()方法,所得到的結果如清單3所示。

          清單2. main()方法
          public static void main(String[] args) {
              String []key= {"1210-JVAJ","1211-JVAJ", "210-JVAJ", "1210-ZVAJ"};
              for (int i=0; i < key.length; i++){
                  if(checkLicenseKey(key[i])){
                      System.out.println(key[i]+ " >> Is Valid");
                  }
                  else{
                      System.out.println(key[i]+ " >> Is InValid");
                  }
              }
          }
          
          清單3. 輸出
          1210-JVAJ >> Is Valid
          1211-JVAJ >> Is InValid
          210-JVAJ >> Is InValid
          1210-ZVAJ >> Is InValid
          
            大部分用于進行字符串操作的方法都隸屬于org.apache.commons.lang.StringUtils,但也有其他的類可以使用。CharUtils和CharSetUtils分別提供使用字符和字符集的實用方法。WordUtils是在2.0版中首次出現的類,用于承載專門用于處理字的實用方法。不過,由于字符串和字的處理上有大量的重疊操作,使得此類似乎有點沒有存在的必要了。RandomStringUtils類可以根據各種規則生成隨機字符串。
            現在,讓我們了解一下Lang的另一個有用的方面:處理日期和時間的能力。

          時間技術
            在Java中處理日期和時間是一件相當棘手的事。如果要使用java.text.SimpleDateFormat、java.util.Calendar、java.util.Date等類,需要一定時間來適應,還需要對每一個涉及到的類和接口非常了解,才能順利地處理日期和時間。
            Lang組件徹底地簡化了日期的處理,并可對其進行格式化。您可以輕松地格式化日期以進行顯示、比較日期、舍入或截斷日期,甚至能獲取特定范圍內的所有日期。

          清單4. 處理日期和時間
          public static void main(String[] args)
          throws InterruptedException, ParseException {
              //date1 created
              Date date1= new Date();
              //Print the date and time at this instant
              System.out.println("The time right now is >>"+date1);
          
              //Thread sleep for 1000 ms
              Thread.currentThread().sleep(DateUtils.MILLIS_IN_SECOND);
          
              //date2 created.
              Date date2= new Date();
          
              //Check if date1 and date2 have the same day
              System.out.println("Is Same Day >> "
                  + DateUtils.isSameDay(date1, date2));
          
              //Check if date1 and date2 have the same instance
              System.out.println("Is Same Instant >> "
                  +DateUtils.isSameInstant(date1, date2));
          
              //Round the hour
              System.out.println("Date after rounding >>"
                  +DateUtils.round(date1, Calendar.HOUR));
          
              //Truncate the hour
              System.out.println("Date after truncation >>"
                  +DateUtils.truncate(date1, Calendar.HOUR));
          
              //Three dates in three different formats
              String [] dates={"2005.03.24 11:03:26", "2005-03-24 11:03", 
              "2005/03/24"};
          
              //Iterate over dates and parse strings to java.util.Date objects
              for(int i=0; i < dates.length; i++){
                  Date parsedDate= DateUtils.parseDate(dates[i],
                  new String []{"yyyy/MM/dd", "yyyy.MM.dd HH:mm:ss",
                "yyyy-MM-dd HH:mm"});
          
                  System.out.println("Parsed Date is >>"+parsedDate);
              }
          
              //Display date in HH:mm:ss format
              System.out.println("Now >>"
                  +DateFormatUtils.ISO_TIME_NO_T_FORMAT.format
              (System.currentTimeMillis()));
          }
            清單4演示了org.apache.commons.lang.DateUtils和org.apache.commons.lang.DateFormatStringUtils類的部分功能。還有其他許多方法可以進行同樣的操作,但輸入格式不同。故而,如果萬一您必須分析和格式化一個日期值,只需要借助提供的方法之一,利用一行代碼就可以實現了。
            執行清單4中代碼后的輸入如清單5所示。

          清單5. 輸出
          The time right now is >>Sat Apr 09 14:40:41 GMT+05:30 2005
          Is Same Day >> true
          Is Same Instant >> false
          Date after rounding >>Sat Apr 09 15:00:00 GMT+05:30 2005
          Date after truncation >>Sat Apr 09 14:00:00 GMT+05:30 2005
          Parsed Date is >>Thu Mar 24 11:03:26 GMT+05:30 2005
          Parsed Date is >>Thu Mar 24 11:03:00 GMT+05:30 2005
          Parsed Date is >>Thu Mar 24 00:00:00 GMT+05:30 2005
          Now >>14:40:43
          
            在清單4中,我們創建了兩個日期,這兩個日期僅有一秒的差別。然后使用isSameInstant()和isSameDay()方法檢查這兩個日期是否相同。接下來將日期進行舍入和截斷,然后使用在數組中指定的各種格式對特殊日期用例進行解析。
            將您的應用程序集成到第三方應用程序時,經常不能完全確定輸入的格式。我曾經做過一個對舊版應用程序的集成,對于每個問題,該應用程序似乎總是有三個答案。所以,如果必須對此類應用程序提供的日期進行解析,您需要提供三個和四個不同的日期格式。清單4中使用parseDate()方法就是為了完成這項任務。這樣,即使輸入有變化,仍然能更對日期進行解析。還要注意,數組內模式的順序與輸入的順序并不相同,但該方法仍然找到了適當的模式,并據此進行解析。
            最后,我們按照ISO_TIME_NO_T_FORMAT格式(HH:mm:ss)對日期進行格式化并打印輸入。現在我們將了解使用Lang生成常用方法toString()。

          生成toString()方法
            經常要用到equals()、toString()和hashCode()方法。不過,談到實際編寫這些方法的實現時,不僅我們大多數人不愿意這樣做,而且我們也不能確定如何準確簡單地編寫這些方法。生成器程序包提供了一些實用類,可以幫助您方便地創建這些方法的實現。大多數情況下,只需要一行代碼即可。下面我們將了解Lang的toString功能。

          toString()方法
            您可能沒有注意到,在清單4中,即使我們向System.out.println()傳遞一個java.util.Date對象,所獲得的輸出仍然是正確的日期和時間顯示。傳遞對象引用時,將自動調用toString()方法,所以可以實現這一點。那么,在我們的示例中實際上調用了java.util.Date類的toString()方法,我們能夠得到正確的輸出是因為有人重寫了java.util.Date類中的java.lang.Object類的toString()方法。
            如果沒有重寫toString()方法,則獲得的輸出只是類名稱和hashcode的名稱。將不會顯示類中的任何數據。所以,如果編寫了一個新類,且希望能得到正確的打印輸出,則需要重寫該類中的toString()方法。

          清單6. toString()方法
          public class Computer {
          
              String processor;
              String color;
              int cost;
          
              /** Creates a new instance of Computer */
              public Computer(String processor, String color, int cost) {
                  this.processor=processor;
                  this.color=color;
                  this.cost=cost;
              }
          
              public static void main(String[] args) {
                  Computer myComp=new Computer("Pentium","black",1000);
                  System.out.println(myComp);
              }
              
              public String toString(){
                  return ToStringBuilder.reflectionToString(this);
                  /*
                  return ToStringBuilder.reflectionToString(this
                      , ToStringStyle.SHORT_PREFIX_STYLE);
                  return ToStringBuilder.reflectionToString(this
                      , ToStringStyle.MULTI_LINE_STYLE);
                  return new ToStringBuilder(this)
                      .append("processor", processor).toString();
                   */
              }
          }
            清單6演示了具有三個字段的Computer類。其中值得關注的是toString()方法。調用reflectionToString()方法可以判斷哪些是類中的字段,然后打印其名稱和值。main()方法中,我們只創建了該類的一個實例,然后將其打印出來。該類的輸出為dev2dev.Computer@f6a746[processor=Pentium,color=black,cost=1000]。
            因而,如果不希望花太多精力,但又需要您的類有toString()實現,最簡單的方法莫過于將這兩行代碼復制并粘貼到您的所有類中。如果希望更好地控制生成的結果,請參見注釋中提到的選項。通過創建ToStringBuilder的新實例,可以對輸出應用各種樣式,甚至生成全部輸出。如果按照列出的順序執行了全部四個返回語句,則輸出如清單7所示。

          清單7. 基于ToStringBuilder方法的四個可能輸出
          1) dev2dev.Computer@f6a746[processor=Pentium,color=black,cost=1000]
          2) Computer[processor=Pentium,color=black,cost=1000]
          3) dev2dev.Computer@f6a746[
             processor=Pentium
             color=black
             cost=1000
             ]
          4) dev2dev.Computer@192d342[processor=Pentium]
          
          對象比較與排序
            經常需要對數據對象進行比較,并據此進行排序。那么我們如何對清單6中所給出的Computer類的對象進行比較和排序呢?
            您猜猜!讓我們使用Lang根據計算機的成本對Computer對象進行排序。若要比較對象,需要實現java.lang.Comparable接口。此接口具有惟一的方法compareTo(Object)。此方法實現將當前對象和傳遞給此方法的對象進行比較。如果此對象小于、等于或大于指定的對象,此方法將分別返回負數、零或正數。
            為了對Computer對象進行比較,在Computer類中實現compareTo() 方法,如清單8所示。

          清單8. compareTo()方法
          public int compareTo(Object obj) {
              Computer anotherComputer = (Computer)obj;
              //return new CompareToBuilder().reflectionCompare
            (this, anotherComputer);
              return new CompareToBuilder().
          	append(this.cost, anotherComputer.cost).toComparison();
          }
          
            然后,為了實際進行比較,我們編寫一個名為ComputerSor的簡單類,如清單9中所示。我們只向ArrayList添加三個對象,然后進行排序。

          清單9. ComputerSort類
          public class ComputerSort  {
          
              public static void main(String[] args) {
                  ArrayList computerList = new ArrayList();
                  computerList.add(new Computer("Pentium","black", 1000));
                  computerList.add(new Computer("Pentium","chocolate", 334));
                  computerList.add(new Computer("Pentium","darkgray", 2234));
          
                  Collections.sort(computerList);
                  System.out.println(computerList);
              }
          
          }
          
            執行ComputerSort時,將看到對象根據cost字段的值進行了排序。CompareToBuilder與ToStringBuilder類似,也有一個基于反射的用法選項。我們已對清單8中的compareTo()方法中的位元進行了注釋,因為,在此種情況下,反射選項將比較所有字段,最終獲得不正確的結果。如果既不希望比較當前類中的字段,也不希望比較其超類中的字段,CompareToBuilder也提供了可以用于此用途的方法。執行ComputerSort類的輸出如清單10中所示。

          清單10. 排序后的Computer對象
          [dev2dev.Computer@cf2c80[processor=Pentium,color=chocolate,cost=334]
          , dev2dev.Computer@12dacd1[processor=Pentium,color=black,cost=1000]
          , dev2dev.Computer@1ad086a[processor=Pentium,color=darkgray,cost=2234]]

          結束語
            本文中,我們了解了Jakarta Commons Lang組件的一些主要功能。總的說來,Commons項目是非常有用的項目,但并沒有得到充分利用。雖然開源項目使用了許多Commons組件,但其在開源世界之外的應用并不十分廣泛。現在您已經對Lang的功能有所了解,應該考慮立即將其應用到您的應用程序中。另外,還可以在Commons項目中尋找各種有用的組件,從而簡化XML解析、使應用程序進行HTTP會話、實現系統化驗證以及執行很多其他功能。

          下載
            下載本文中用到的代碼:examples.zip (3KB)

          參考資料

            Harshad Oak是Java J2EE門戶網站IndicThreads.com的創始人。他編寫了Pro Jakarta Commons和Oracle JDeveloper 10g:Empowering J2EE Development,并與人合著了Java 2 Enterprise Edition 1.4 Bible。他還是Rightrix Solutions的創始人。

          原文出處
          http://dev2dev.bea.com/pub/a/2005/04/commons_lang.html

          posted on 2007-01-11 16:26 ★yesjoy★ 閱讀(393) 評論(0)  編輯  收藏 所屬分類: 常用Jar包介紹和應用

          只有注冊用戶登錄后才能發表評論。


          網站導航:
           
          主站蜘蛛池模板: 抚顺县| 淮南市| 星座| 鄢陵县| 三门峡市| 乾安县| 米脂县| 德阳市| 昌平区| 屯昌县| 正宁县| 竹山县| 荣成市| 重庆市| 汕头市| 哈巴河县| 元氏县| 大港区| 运城市| 台北市| 平顺县| 承德县| 华坪县| 织金县| 临清市| 交城县| 共和县| 甘孜县| 安图县| 普兰店市| 辛集市| 金塔县| 思南县| 长子县| 安岳县| 鲜城| 勃利县| 儋州市| 平利县| 太谷县| 克什克腾旗|