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 组件 为了组织方便我将个(包括ELLatka和Jexl)Commons组件分为五类如下表 组件类别 组件 Web相关 FileUploadHTTPClient和Net XML相关 BetwixtDigesterJelly和JXPath 工具 BeanUtilsLoggingDBCPPool和 Validator 打包 Codec 和 Modeler 小程序 CLIDiscoveryLang和 Collections 要注意的是这个分类只是对本文而言在Commons项目中是不存在的在某种程度上分类是重叠的本文将介绍Web相关和小程序类下篇文章包括XML相关和打包类工具类在最后一篇文章中 小程序类 将CLIDiscoveryLang和 Collections归入小程序类是因为它们都是为了一个小而实用的目的编写的 CLI 概要CLI(Command Line Interface)为你的Java程序提供读取和解析命令行参数的通用接口 在那得到主页程序源代码 何时使用需要统一操作命令行参数时 例子程序CLIDemojava需要将commonsclijarcommons加入CLASSPATH中 描述通常在完成一个Java程序时不得不重写应用程序输入参数的处理部分如果有一个唯一的接口用来定义﹑解析和读取输入参数以决定程序的运行方式不是很好吗?CLI就是答案 对于CLI命令行中每个要处理的参数都是一个Option创建一个Options对象将Option对象添加进去然后用CLI提供的函数解析用户的输入参数一个Option也许也需要用户输入一个值例如文件名这时Option必须在指定处创建 CLI使用步骤如下 创建Options Options options = new Options(); OptionsaddOption(tfalsecurrent time); 创建解析器解析用户输入 CommandLineParser parser = new BasicParser(); CommandLine cmd; try{ cmd = parserparse(options args); } catch(ParseException pe) { usage(options); return; } 根据用户输入执行相应操作 if(cmdhasOption(n)) { Systemerrprintln(Nice to meet you: + cmdgetOptionvalue(n)); } 以上基本就是使用CLI的全过程当然CLI提供其他高级选项用于控制各种格式和解析器但基本操作是相同的完整的例子可以看demo Discovery 概要discovery模式的实现提供定位与实例化类或其他资源的通用方法 在那得到主页程序源代码该包处于prerelease状态 何时使用需要快速找到你的代码中Java接口的实现时 例子程序DiscoveryDemojavaMyInterfacejavaMyImpljavaMyImpljava MyInterface需要将commonsdiscoveryjar和commonsloggingjar添到CLASSPATH中 描述Discovery的目的是使用最好的算法得到接口的所有实现当用户想找到所有的提供某一服务的提供商时这将特别有用 假设你写了一个针对某一难题的接口这个接口的所有实现将以唯一的编码方式解决这一难题真正的用户在实际解决这一难题时将会有多种选择他怎么才能知道接口的那种实现在他的系统中是可行的? 这就是Service与Service Provider结构Service就是你定义的接口Service Providers提供Service的实现用户需要选择Service ProvidersDiscovery组件用多种方法提供帮助注意Discovery不仅用于发现实现类而且可以寻找资源例如图像或其他文件它遵照Sun的Service Provider Architecture规范 同样Discovery的使用也很简单例子程序中MyImpl和MyImpl是MyInterface接口的实现MyInterface文件必须在METAINF/services目录下注意这个文件必须对应接口的全路径如果接口在包内那么文件名也要相应改动 .取得ClassLoader ClassLoaders loaders = ClassLoadersgetAppLoaders(MyInterfaceclass getClass() false); .创建DiscoverClass用于查找实现类 DiscoverClass discover = new DiscoverClass(loaders); .查找实现类 Class implClass = discoverfind(MyInterfaceclass); Systemerrprintln(Implementing Provider: + implClassgetName()); 运行以上代码(DiscoveryDemojava)将得到MyInterface文件中注册的类如下所示再次提醒如果实现包含在一个包结构内文件名必须做相应的修改如果这个文件不在规定目录下或实现类不能实例化或定位将抛出DiscoveryException异常表明找不到MyInterface的实现 MyImpl # Implementation 当然这不是注册实现的唯一方法否则Discovery还有什么用!事实上这是Discovery发现类的内部机制的最后一步其他方法包括在系统属性或用户属性中定义实现类的名字例如删除METAINF/services目录下的文件按以下输入运行demo结果相同这里系统属性是接口名而值是接口实现提供者 java DMyInterface=MyImpl DiscoveryDemo Discovery也可用于创建(单例)服务提供者的实例并调用它们的函数如下 ((MyInterface)discovernewInstance(MyInterfaceclass))myMethod(); 注意此时我们并不知道那个服务提供者实现myMethod函数我们也不关心这个函数的实现取决于以何种方式运行以上代码以及注册的服务提供者 Lang 概要javalang包的扩展增加许多对String的操作提供类C语言的枚举 在那得到主页程序源代码这里介绍的是Lang翻译本文时Lang已经发布 何时使用当对javalang提供的默认实现感到厌烦想更好的控制String的操作数值函数以及系统属性时还有想使用C语言风格的枚举时 例子程序LangDemojava Mortgagejava OnTVjava需要将commonslangjar加入CLASSPATH中 描述这个包中提供的很多工具函数可以简化Java程序员的工作这些函数可以减少实现日常功能的编程量特别是StringUtils类它提供比标准的javalangString包更强的操作字符串的功能它们的使用十分简单只要用正确的参数调用一个静态函数例如要将一句话变为以大写开头只要 StringUtilscapitalise(name); 这个函数的输出就象我们需要的Name浏览StringUtils API的其他静态函数你可能会发现对你有用的例子程序中使用了一些 另一个有趣的类是RandomStringUtils这个类中的函数产生随机字符串这在生成随机密码时很有用 类NumberUtils提供数据操作的函数包括最大最小值函数以及将字符串转换为数字的函数NumberRange和CharRange分别处理数字与字符的范围 Builder包中的类提供为类添加toStringhashCodecompareTo和equals函数的功能也就是说自己不需编码就可以在类中添加高质量的toStringhashCodecompareTo和equals函数只要使用Builder包中的函数就可以了例如用ToStringBuilder函数给类添加toString方法 public class Mortgage { private float rate; private int years; public String toString() { return new ToSt |