﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-★yesjoy★-文章分类-常用Jar包介绍和应用</title><link>http://www.blogjava.net/yesjoy/category/19130.html</link><description>&lt;font color="red"&gt;★&lt;/font&gt;&lt;font color="blue"&gt;总在爬山 所以艰辛;总在寻梦 所以苦痛&lt;/font&gt;&lt;font color="red"&gt;★&lt;/font&gt;</description><language>zh-cn</language><lastBuildDate>Thu, 02 Sep 2010 04:39:45 GMT</lastBuildDate><pubDate>Thu, 02 Sep 2010 04:39:45 GMT</pubDate><ttl>60</ttl><item><title>利用Jakarta Commons Lang简化Java</title><link>http://www.blogjava.net/yesjoy/articles/93203.html</link><dc:creator>★yesjoy★</dc:creator><author>★yesjoy★</author><pubDate>Thu, 11 Jan 2007 08:26:00 GMT</pubDate><guid>http://www.blogjava.net/yesjoy/articles/93203.html</guid><wfw:comment>http://www.blogjava.net/yesjoy/comments/93203.html</wfw:comment><comments>http://www.blogjava.net/yesjoy/articles/93203.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/yesjoy/comments/commentRss/93203.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/yesjoy/services/trackbacks/93203.html</trackback:ping><description><![CDATA[
		<table cellspacing="0" cellpadding="0" width="100%" border="0">
				<tbody>
						<tr>
								<td height="64">时间：2005-07-19<br />作者：<a href="http://dev2dev.bea.com.cn/author/345.html">Harshad Oak</a><br />浏览次数：
<script language="JavaScript" src="/beadevcount.jsp?d_id=161690" type="text/JavaScript"></script>
 3473 <br />本文关键字：<a href="http://dev2dev.bea.com.cn/products/search.jsp?searchtype=keywords&amp;keywords=java">java</a>, <a href="http://dev2dev.bea.com.cn/products/search.jsp?searchtype=keywords&amp;keywords= 基础"> 基础</a>, <a href="http://dev2dev.bea.com.cn/products/search.jsp?searchtype=keywords&amp;keywords= Jakarta Commons"> Jakarta Commons</a>  <br />转自:http://dev2dev.bea.com.cn/techdoc/2005071902.html<br />作为企业Java开发人员，我们总是需要实现各种功能，如解析XML、使用HTTP、验证输入以及处理日期等。使用Jakarta Commons项目的目的在于创建负责处理所有此类常用任务的组件，从而节约时间，让您集中精力处理核心业务解决方案。在本文中，我们将对<a href="http://jakarta.apache.org/commons/" target="_blank">Jakarta Commons</a> 项目作简单介绍，然后演示如何使用Jakarta Commons内的<a href="http://jakarta.apache.org/commons/lang/" target="_blank">Lang</a>组件来处理和简化日常Java任务，比如字符串操作、使用日期和日历、比较数据对象以及对象排序等。对于本文中的所有例子，我们都将使用最新的Lang版本（即2.1版本）。 <br />　　编者按：本文中的代码是根据Commons Lang的 <a href="http://people.apache.org/%7Ebayard/commons-lang-2.1/distributions/" target="_blank">RC1版本</a> 编写的。其最终版不久将发行。<br /><br /><strong>Commons和Lang组件简介</strong><br />　　<a href="http://jakarta.apache.org/commons/" target="_blank">Jakarta Commons</a> 项目旨在实现可重用的 Java 组件。此项目包含数十个组件，用以简化 Java 的开发，每个组件负责满足一个特定需求。有大量的组件可用，且不仅限于在特定类型的Java应用程序中使用。<br /><br />项目分类在两个部件中： 
<p></p><ol><li>Commons Proper：Commons Proper中的项目已可以投入实际使用。 
</li><li>Commons Sandbox：sandbox内的项目仍然处于实验阶段。 </li></ol><p>　　目前Commons Proper中有33个项目，Commons Sandbox中有22个项目，故而，任何一类Java项目都有其存在的意义。<br />　　<a href="http://jakarta.apache.org/commons/lang/" target="_blank">Lang</a>组件是Jakarta Commons中较为流行的组件之一。Lang是要呈现在J2SE本身中的一组类。 <br />　　在本文中，我们将了解Lang最有用的一些功能。要注意的是，也可以只使用基本Java类来完成Lang的每个功能，但相对于自己学习、理解并编写代码而言，使用Lang要简单得多。即使您能够写出最好的代码，使用经过实验和测试的Lang的功能会更快一些，能节省大量的检查与测试时间。随着Lang一起提供了特有的JUnit测试用例，Lang的使用极其广泛，已经历了其创建者和现实世界的种种考验。<br />　　Lang的一个重要特征是其简单性。通常来说，新的Java组件十分复杂，要了解若干种技术才能使用这些组件。要理解组件的用途通常都很难，更别说实际使用该组件了。但对于大多数Commons组件而言，这就不是问题了。Lang一类组件使用方便，无论对Java初学者还是高级Java用户都非常有用。<br />　　如果在采用技术前需要有十足的保证，则请在保存您的Java软件的目录中搜索commons-lang*.jar。结果会让您感到很意外。 <a href="http://jakarta.apache.org/tomcat/" target="_blank">Tomcat</a>、<a href="http://struts.apache.org/" target="_blank">Struts</a>、<a href="http://hibernate.org/" target="_blank">Hibernate</a>、<a href="http://springframework.org/" target="_blank">Spring</a>和<a href="http://www.opensymphony.com/webwork/" target="_blank">WebWork</a> 等常见Java项目都使用Lang。<br />　　首先让我们看一看使用Lang进行大多数开发人员几乎每天必须进行的操作——字符串操作。 <br /><br /><strong>处理字符串</strong><br />　　无论应用程序是基于Swing、J2EE或J2ME的，它都必须使用字符串。所以，尽管在Java中使用字符串相当简单，但是如果希望按照一定的条件修改和处理字符串，事情就不那么简单了。您不得不在各种与字符串相关的类中寻找各种不常用的方法，然后想办法使其协同工作，以获得所需的结果。虽然有些Lang方法与J2SE中的某些方法重叠，但在大多数情况下，一个Lang方法就可提供各种类中的多个J2SE方法的功能，从而帮助您获得所需的输出。 <br />　　Lang组件有许多专门用于字符串操作的类。现在我们将使用一个简单的Java应用程序来演示一些较为有用的类和方法。 <br />　　当应用程序接受用户输入时，由于用户可能会存在输入错误的情况，或用户可能以各种格式输入数据，而您希望只采用一种格式进行处理和存储，则通常会涉及到对字符串进行操作。 <br />　　例如，您有一个带输入框的窗体，用户在此输入框内输入许可证密钥。您希望允许输入1111-JAVA格式的密钥。您必须进行以下操作：</p><ol><li>检查是否为空字符串。 
</li><li>忽略空格。 
</li><li>密钥区分大小写。 
</li><li>用“-”标记分隔密钥字符串，然后检查第一部分是否全部是数字，第二部分包含的字符是否只来自有效字符集“J”、“A”、“V”、“A”。 
</li><li>两个部分均应有四个字符。 
</li><li>第一部分的第四个数字应该是“0”。 </li></ol><p>　　只有当密钥满足所有这些条件时，应用程序才会查询数据库，检查该密钥是否合法。 <br />　　如果不花大量的时间浏览String、StringTokenizer和其他类的API文档，您能完成以上的任务么？我不能，所以现在我将试着用Lang组件来管理验证。<br /><strong>清单1. checkLicenseKey()方法</strong></p><pre class="code">/**
 * 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;
}</pre>　　在清单1中，我们使用了org.apache.commons.lang.StringUtils类中提供的各种方法，根据我们先前定义的所有规则对字符串进行验证。isBlank()方法检查字符串是否为空。deleteWhitespace()方法确保字符串不包含空格。然后我们使用split()方法对字符串进行分隔，并使用isNumeric()、containsOnly()和indexOf()方法对密钥的两部分进行验证。<br />　　请注意，尽管在J2SE中已经有了indexOf()方法，最好使用StringUtils中的indexOf()。与J2SE indexOf()方法不同，使用StringUtils indexOf()时无需担心空指针的问题。触发NullPointerException被认为是Java程序员最常犯的错误。Lang可以确保您不会犯同样的错误。即使向indexOf()或其他此类方法传递一个null，都不会引发NullPointerException。indexOf()将直接返回-1。<br />　　这样，只需几行简单代码，就可以实现相应的功能，而采用其他方法需要编写很多行代码，而且十分麻烦。如果使用清单2中所示的主方法执行checkLicenseKey()方法，所得到的结果如清单3所示。<br /><br /><strong>清单2. main()方法</strong><pre class="code">public static void main(String[] args) {
    String []key= {"1210-JVAJ","1211-JVAJ", "210-JVAJ", "1210-ZVAJ"};
    for (int i=0; i &lt; key.length; i++){
        if(checkLicenseKey(key[i])){
            System.out.println(key[i]+ " &gt;&gt; Is Valid");
        }
        else{
            System.out.println(key[i]+ " &gt;&gt; Is InValid");
        }
    }
}
</pre><strong>清单3. 输出</strong><pre class="code">1210-JVAJ &gt;&gt; Is Valid
1211-JVAJ &gt;&gt; Is InValid
210-JVAJ &gt;&gt; Is InValid
1210-ZVAJ &gt;&gt; Is InValid
</pre>　　大部分用于进行字符串操作的方法都隶属于org.apache.commons.lang.StringUtils，但也有其他的类可以使用。CharUtils和CharSetUtils分别提供使用字符和字符集的实用方法。WordUtils是在2.0版中首次出现的类，用于承载专门用于处理字的实用方法。不过，由于字符串和字的处理上有大量的重叠操作，使得此类似乎有点没有存在的必要了。RandomStringUtils类可以根据各种规则生成随机字符串。 <br />　　现在，让我们了解一下Lang的另一个有用的方面：处理日期和时间的能力。<br /><br /><strong>时间技术</strong><br />　　在Java中处理日期和时间是一件相当棘手的事。如果要使用java.text.SimpleDateFormat、java.util.Calendar、java.util.Date等类，需要一定时间来适应，还需要对每一个涉及到的类和接口非常了解，才能顺利地处理日期和时间。 <br />　　Lang组件彻底地简化了日期的处理，并可对其进行格式化。您可以轻松地格式化日期以进行显示、比较日期、舍入或截断日期，甚至能获取特定范围内的所有日期。 <br /><br /><strong>清单4. 处理日期和时间</strong><pre class="code">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 &gt;&gt;"+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 &gt;&gt; "
        + DateUtils.isSameDay(date1, date2));

    //Check if date1 and date2 have the same instance
    System.out.println("Is Same Instant &gt;&gt; "
        +DateUtils.isSameInstant(date1, date2));

    //Round the hour
    System.out.println("Date after rounding &gt;&gt;"
        +DateUtils.round(date1, Calendar.HOUR));

    //Truncate the hour
    System.out.println("Date after truncation &gt;&gt;"
        +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 &lt; 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 &gt;&gt;"+parsedDate);
    }

    //Display date in HH:mm:ss format
    System.out.println("Now &gt;&gt;"
        +DateFormatUtils.ISO_TIME_NO_T_FORMAT.format
    (System.currentTimeMillis()));
}</pre>　　清单4演示了org.apache.commons.lang.DateUtils和org.apache.commons.lang.DateFormatStringUtils类的部分功能。还有其他许多方法可以进行同样的操作，但输入格式不同。故而，如果万一您必须分析和格式化一个日期值，只需要借助提供的方法之一，利用一行代码就可以实现了。 <br />　　执行清单4中代码后的输入如清单5所示。<br /><br /><strong>清单5. 输出</strong><pre class="code">The time right now is &gt;&gt;Sat Apr 09 14:40:41 GMT+05:30 2005
Is Same Day &gt;&gt; true
Is Same Instant &gt;&gt; false
Date after rounding &gt;&gt;Sat Apr 09 15:00:00 GMT+05:30 2005
Date after truncation &gt;&gt;Sat Apr 09 14:00:00 GMT+05:30 2005
Parsed Date is &gt;&gt;Thu Mar 24 11:03:26 GMT+05:30 2005
Parsed Date is &gt;&gt;Thu Mar 24 11:03:00 GMT+05:30 2005
Parsed Date is &gt;&gt;Thu Mar 24 00:00:00 GMT+05:30 2005
Now &gt;&gt;14:40:43
</pre>　　在清单4中，我们创建了两个日期，这两个日期仅有一秒的差别。然后使用isSameInstant()和isSameDay()方法检查这两个日期是否相同。接下来将日期进行舍入和截断，然后使用在数组中指定的各种格式对特殊日期用例进行解析。<br />　　将您的应用程序集成到第三方应用程序时，经常不能完全确定输入的格式。我曾经做过一个对旧版应用程序的集成，对于每个问题，该应用程序似乎总是有三个答案。所以，如果必须对此类应用程序提供的日期进行解析，您需要提供三个和四个不同的日期格式。清单4中使用parseDate()方法就是为了完成这项任务。这样，即使输入有变化，仍然能更对日期进行解析。还要注意，数组内模式的顺序与输入的顺序并不相同，但该方法仍然找到了适当的模式，并据此进行解析。<br />　　最后，我们按照ISO_TIME_NO_T_FORMAT格式（HH:mm:ss）对日期进行格式化并打印输入。现在我们将了解使用Lang生成常用方法toString()。<br /><br /><strong>生成toString()方法</strong><br />　　经常要用到equals()、toString()和hashCode()方法。不过，谈到实际编写这些方法的实现时，不仅我们大多数人不愿意这样做，而且我们也不能确定如何准确简单地编写这些方法。生成器程序包提供了一些实用类，可以帮助您方便地创建这些方法的实现。大多数情况下，只需要一行代码即可。下面我们将了解Lang的toString功能。<br /><br /><strong>toString()方法</strong><br />　　您可能没有注意到，在清单4中，即使我们向System.out.println()传递一个java.util.Date对象，所获得的输出仍然是正确的日期和时间显示。传递对象引用时，将自动调用toString()方法，所以可以实现这一点。那么，在我们的示例中实际上调用了java.util.Date类的toString()方法，我们能够得到正确的输出是因为有人重写了java.util.Date类中的java.lang.Object类的toString()方法。 <br />　　如果没有重写toString()方法，则获得的输出只是类名称和hashcode的名称。将不会显示类中的任何数据。所以，如果编写了一个新类，且希望能得到正确的打印输出，则需要重写该类中的toString()方法。 <br /><br /><strong>清单6. toString()方法</strong><pre class="code">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();
         */
    }
}</pre>　　清单6演示了具有三个字段的Computer类。其中值得关注的是toString()方法。调用reflectionToString()方法可以判断哪些是类中的字段，然后打印其名称和值。main()方法中，我们只创建了该类的一个实例，然后将其打印出来。该类的输出为dev2dev.Computer@f6a746[processor=Pentium,color=black,cost=1000]。<br />　　因而，如果不希望花太多精力，但又需要您的类有toString()实现，最简单的方法莫过于将这两行代码复制并粘贴到您的所有类中。如果希望更好地控制生成的结果，请参见注释中提到的选项。通过创建ToStringBuilder的新实例，可以对输出应用各种样式，甚至生成全部输出。如果按照列出的顺序执行了全部四个返回语句，则输出如清单7所示。<br /><br /><strong>清单7. 基于ToStringBuilder方法的四个可能输出</strong><pre class="code">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]
</pre><strong>对象比较与排序</strong><br />　　经常需要对数据对象进行比较，并据此进行排序。那么我们如何对清单6中所给出的Computer类的对象进行比较和排序呢？ <br />　　您猜猜！让我们使用Lang根据计算机的成本对Computer对象进行排序。若要比较对象，需要实现java.lang.Comparable接口。此接口具有惟一的方法compareTo(Object)。此方法实现将当前对象和传递给此方法的对象进行比较。如果此对象小于、等于或大于指定的对象，此方法将分别返回负数、零或正数。 <br />　　为了对Computer对象进行比较，在Computer类中实现compareTo() 方法，如清单8所示。<br /><br /><strong>清单8. compareTo()方法</strong><pre class="code">public int compareTo(Object obj) {
    Computer anotherComputer = (Computer)obj;
    //return new CompareToBuilder().reflectionCompare
  (this, anotherComputer);
    return new CompareToBuilder().
	append(this.cost, anotherComputer.cost).toComparison();
}
</pre>　　然后，为了实际进行比较，我们编写一个名为ComputerSor的简单类，如清单9中所示。我们只向ArrayList添加三个对象，然后进行排序。<br /><br /><strong>清单9. ComputerSort类</strong><pre class="code">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);
    }

}
</pre>　　执行ComputerSort时，将看到对象根据cost字段的值进行了排序。CompareToBuilder与ToStringBuilder类似，也有一个基于反射的用法选项。我们已对清单8中的compareTo()方法中的位元进行了注释，因为，在此种情况下，反射选项将比较所有字段，最终获得不正确的结果。如果既不希望比较当前类中的字段，也不希望比较其超类中的字段，CompareToBuilder也提供了可以用于此用途的方法。执行ComputerSort类的输出如清单10中所示。<br /><br /><strong>清单10. 排序后的Computer对象</strong><pre class="code">[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]]</pre><p><strong>结束语</strong><br />　　本文中，我们了解了Jakarta Commons Lang组件的一些主要功能。总的说来，Commons项目是非常有用的项目，但并没有得到充分利用。虽然开源项目使用了许多Commons组件，但其在开源世界之外的应用并不十分广泛。现在您已经对Lang的功能有所了解，应该考虑立即将其应用到您的应用程序中。另外，还可以在Commons项目中寻找各种有用的组件，从而简化XML解析、使应用程序进行HTTP会话、实现系统化验证以及执行很多其他功能。<br /><br /><strong>下载</strong><br />　　下载本文中用到的代码：<a href="http://dev2dev.bea.com/2005/04/examples.zip">examples.zip</a> (3KB)<br /><br /><strong>参考资料</strong></p><ul><li><a href="http://jakarta.apache.org/commons/" target="_blank">Jakarta Commons </a></li><li><a href="http://jakarta.apache.org/commons/lang/" target="_blank">Jakarta Commons Lang</a></li></ul><p>　　<a href="http://dev2dev.bea.com/pub/au/288" target="_blank">Harshad Oak</a>是Java J2EE门户网站IndicThreads.com的创始人。他编写了Pro Jakarta Commons和Oracle JDeveloper 10g:Empowering J2EE Development，并与人合著了Java 2 Enterprise Edition 1.4 Bible。他还是Rightrix Solutions的创始人。 </p><p><strong>原文出处</strong><br /><a href="http://dev2dev.bea.com/pub/a/2005/04/commons_lang.html" target="_blank">http://dev2dev.bea.com/pub/a/2005/04/commons_lang.html</a></p><!--文章其他信息--></td>
						</tr>
				</tbody>
		</table>
<img src ="http://www.blogjava.net/yesjoy/aggbug/93203.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/yesjoy/" target="_blank">★yesjoy★</a> 2007-01-11 16:26 <a href="http://www.blogjava.net/yesjoy/articles/93203.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>