Jakarta Commons是Jakarta的一个子项目,目的是创建和维护独立于其他框架和产品的程序包(packages)。这些程序包是一些服务于小范围的有效组件的集合,通常适用于服务器端编程。
Commons项目分为两部分:Sandbox和Commons库。Sandbox用于测试。本文关注库组件,包括它们什么时候使用,在那里,以及用例子说明如何使用。
简要介绍
Jakarta Commons项目源于重用,其中的程序包必须确保能够重用。有一些包来自于其他项目,例如通用日志包是Jakarta Struts的一部分。当开发者发现某个包对于其他项目很有用,可以缩短开发周期,他们决定将这些包做成通用组件。这就是Jakarta Commons项目。
要真正做到可重用,每个程序包必须独立于其他较大的框架和项目。因此,Commons项目中的每个包在很大程度上是独立的,不仅相对于其他项目,甚至对于其他包也是如此。违反这一原则的情况是存在的,但决大多数情况是使用成熟的APIs。例如,Betwixt包建立在XML APIs基础之上。尽管这个项目的本意是建立不依赖其他组件的程序包。
大多数程序包十分简洁,以至于缺少必要的文档、维护和帮助。有些包甚至只有错误的连接和极少的文档。大多数情况下,你只能自己摸索如何使用它们,为什么使用它们。希望这篇文章对你有帮助。
注意:Jakarta Commons与Apache Commons是不同的。后者是Apache Software Foundation(ASF)的顶级项目。而前者是ASF的另一个顶级项目Jakarta的子项目,是本文介绍的对象。而且,Jakarta Commons只使用Java。在本文中Commons指的是Jakarta Commons。
组件
为了组织方便,我将18个(包括EL,Latka和Jexl)Commons组件分为五类。如下表:
组件类别
组件
Web相关
FileUpload,HTTPClient和Net
XML相关
Betwixt,Digester,Jelly和JXPath
工具
BeanUtils,Logging,DBCP,Pool和 Validator
打包
Codec 和 Modeler
小程序
CLI,Discovery,Lang和 Collections
要注意的是这个分类只是对本文而言,在Commons项目中是不存在的。在某种程度上分类是重叠的。本文将介绍Web相关和小程序类,下篇文章包括XML相关和打包类,工具类在最后一篇文章中。
小程序类
将CLI,Discovery,Lang和 Collections归入小程序类是因为它们都是为了一个小而实用的目的编写的。
1.CLI
概要:CLI(Command Line Interface)为你的Java程序提供读取和解析命令行参数的通用接口。
在那得到:主页,程序,源代码。
何时使用:需要统一操作命令行参数时。
例子程序:CLIDemo.java,需要将commons-cli-1.0.jarcommons加入CLASSPATH中。
描述:通常在完成一个Java程序时不得不重写应用程序输入参数的处理部分。如果有一个唯一的接口用来定义?解析和读取输入参数,以决定程序的运行方式不是很好吗?CLI就是答案。
对于CLI,命令行中每个要处理的参数都是一个Option。创建一个Options对象,将Option对象添加进去,然后用CLI提供的函数解析用户的输入参数。一个Option也许也需要用户输入一个值,例如文件名。这时Option必须在指定处创建。
CLI使用步骤如下:
1.创建Options:
Options options = new Options();
Options.addOption(“t”,false,”current time”);
2.创建解析器解析用户输入:
CommandLineParser parser = new BasicParser();
CommandLine cmd;
try{
cmd = parser.parse(options, args);
} catch(ParseException pe) {
usage(options);
return;
}
3.根据用户输入执行相应操作:
if(cmd.hasOption(“n”)) {
System.err.println(“Nice to meet you: ”+
cmd.getOptionvalue(‘n’));
}
以上基本就是使用CLI的全过程。当然,CLI提供其他高级选项用于控制各种格式和解析器,但基本操作是相同的。完整的例子可以看demo。
2.Discovery
概要:discovery模式的实现,提供定位与实例化类或其他资源的通用方法。
在那得到:主页,程序,源代码。该包处于pre-release状态。
何时使用:需要快速找到你的代码中Java接口的实现时。
例子程序:DiscoveryDemo.java,MyInterface.java,MyImpl1.java,MyImpl2.java, MyInterface。需要将commons-discovery.jar和commons-logging.jar添到CLASSPATH中。
描述:Discovery的目的是使用最好的算法得到接口的所有实现。当用户想找到所有的提供某一服务的提供商时,这将特别有用。
假设你写了一个针对某一难题的接口。这个接口的所有实现将以唯一的编码方式解决这一难题。真正的用户在实际解决这一难题时将会有多种选择。他怎么才能知道接口的那种实现在他的系统中是可行的?
这就是Service与Service Provider结构。Service就是你定义的接口。Service Providers提供Service的实现。用户需要选择Service Providers。Discovery组件用多种方法提供帮助。注意Discovery不仅用于发现实现类,而且可以寻找资源,例如图像或其他文件。它遵照Sun的Service Provider Architecture规范。
同样,Discovery的使用也很简单。例子程序中,MyImpl1和MyImpl2是MyInterface接口的实现。MyInterface文件必须在META-INF/services目录下。注意这个文件必须对应接口的全路径。如果接口在包内,那么文件名也要相应改动。
1.取得ClassLoader:
ClassLoaders loaders =
ClassLoaders.getAppLoaders(MyInterface.class, getClass(), false);
2.创建DiscoverClass用于查找实现类:
DiscoverClass discover = new DiscoverClass(loaders);
3.查找实现类:
Class implClass = discover.find(MyInterface.class);
System.err.println("Implementing Provider: " + implClass.getName());
运行以上代码(DiscoveryDemo.java)将得到MyInterface文件中注册的类,如下所示。再次提醒,如果实现包含在一个包结构内,文件名必须做相应的修改。如果这个文件不在规定目录下,或实现类不能实例化或定位,将抛出DiscoveryException异常,表明找不到MyInterface的实现。
MyImpl2 # Implementation 2
当然,这不是注册实现的唯一方法,否则Discovery还有什么用!事实上,这是Discovery发现类的内部机制的最后一步。其他方法包括在系统属性或用户属性中定义实现类的名字。例如,删除META-INF/services目录下的文件,按以下输入运行demo,结果相同。这里系统属性是接口名,而值是接口实现提供者。
java -DMyInterface=MyImpl1 DiscoveryDemo
Discovery也可用于创建(单例)服务提供者的实例并调用它们的函数。如下:
((MyInterface)discover.newInstance(MyInterface.class)).myMethod();
注意此时我们并不知道那个服务提供者实现myMethod函数,我们也不关心。这个函数的实现取决于以何种方式运行以上代码以及注册的服务提供者。
3.Lang
概要:java.lang包的扩展,增加许多对String的操作。提供类C语言的枚举。
在那得到:主页,程序,源代码。这里介绍的是Lang1.0,翻译本文时Lang2.0已经发布。
何时使用:当对java.lang提供的默认实现感到厌烦,想更好的控制String的操作,数值函数以及系统属性时,还有,想使用C语言风格的枚举时。
例子程序:LangDemo.java, Mortgage.java, OnTV.java。需要将commons-lang.jar加入CLASSPATH中。
描述:这个包中提供的很多工具函数可以简化Java程序员的工作。这些函数可以减少实现日常功能的编程量。特别是StringUtils类,它提供比标准的java.lang.String包更强的操作字符串的功能。它们的使用十分简单,只要用正确的参数调用一个静态函数。例如,要将一句话变为以大写开头只要:
StringUtils.capitalise("name");
这个函数的输出就象我们需要的“Name”。浏览StringUtils API的其他静态函数,你可能会发现对你有用的。例子程序中使用了一些。
另一个有趣的类是RandomStringUtils。这个类中的函数产生随机字符串,这在生成随机密码时很有用。
类NumberUtils提供数据操作的函数,包括最大最小值函数,以及将字符串转换为数字的函数。NumberRange和CharRange分别处理数字与字符的范围。
Builder包中的类提供为类添加toString,hashCode,compareTo和equals函数的功能。也就是说,自己不需编码就可以在类中添加高质量的toString,hashCode,compareTo和equals函数,只要使用Builder包中的函数就可以了。例如,用ToStringBuilder函数给类添加toString方法:
public class Mortgage {
private float rate;
private int years;
....
public String toString() {