// …
// ① 创建一个Options:
Options options = new Options();
options.addOption("t", false, "current time");
// …
// ② 创建一个解析器,分析输入:
CommandLineParser parser = new BasicParser();
CommandLine cmd;
try {
cmd = parser.parse(options, args);
} catch (ParseException pe) {
usage(options);
return;
}
// …
// ③ 最后就可以根据用户的输入,采取相应的操作:
if (cmd.hasOption("n")) {
System.err.println("Nice to meet you: " +
cmd.getOptionValue('n'));
}
这就是使用CLI的完整过程了。当然,CLI还提供了其他高级选项,例如控制格式和解析过程等,但基本的使用思路仍是一致的。请参见本文最后提供的示例程序。
2.2 Discovery
■ 概况:Discovery组件是发现模式(Discovery Pattern)的一个实现,它的目标是按照一种统一的方式定位和实例化类以及其他资源。
■ 官方资源:主页,二进制,源代码。
■ 何时适用:当你想用最佳的算法在Java程序中查找Java接口的各种实现之时。
■ 应用实例:DiscoveryDemo.java,MyInterface.java,MyImpl1.java,MyImpl2.java, MyInterface。要求CLASSPATH中必须包含commons-discovery.jar和commons-logging.jar。
■ 说明:
Discovery的意思就是"发现",它试图用最佳的算法查找某个接口的所有已知的实现。在使用服务的场合,当我们想要查找某个服务的所有已知的提供者时,Discovery组件尤其有用。
考虑一下这种情形:我们为某个特别复杂的任务编写了一个接口,所有该接口的实现都用各不相同的方式来完成这个复杂任务,最终用户可以根据需要来选择完成任务的具体方式。那么,在这种情形下,最终用户应该用什么办法来找出接口的所有可用实现(即可能的完成任务的方式)呢?
上面描述的情形就是所谓的服务-服务提供者体系。服务的功能由接口描述,服务提供者则提供具体的实现。现在的问题是最终用户要用某种办法来寻找系统中已经安装了哪些服务提供者。在这种情形下,Discovery组件就很有用了,它不仅可以用来查找那些实现了特定接口的类,而且还可以用来查找资源,例如图片或其他文件等。在执行这些操作时,Discovery遵从Sun的服务提供者体系所定义的规则。
由于这个原因,使用Discovery组件确实带来许多方便。请读者参阅本文后面示例程序中的接口 MyInterface.java和两个实现类MyImpl1.java、MyImple2.java,了解下面例子的细节。在使用Discovery的时候要提供MyInterface文件,把它放入META-INF/services目录,注意该文件的名字对应接口的完整限定名称(Fully Qualified Name),如果接口属于某个包,该文件的名字也必须相应地改变。
// …
// ① 创建一个类装入器的实例。
ClassLoaders loaders =
ClassLoaders.getAppLoaders(MyInterface.class, getClass(), false);
// …
// ② 用DiscoverClass的实例来查找实现类。
DiscoverClass discover = new DiscoverClass(loaders);
// …
// ③ 查找实现了指定接口的类:
Class implClass = discover.find(MyInterface.class);
System.err.println("Implementing Provider: " + implClass.getName());
运行上面的代码,就可以得到在MyInterface文件中注册的类。再次提醒,如果你的实现是封装在包里面的,在这里注册的名字也应该作相应地修改,如果该文件没有放在正确的位置,或者指定名字的实现类不能找到或实例化,程序将抛出DiscoverException,表示找不到符合条件的实现。下面是MyInterface文件内容的一个例子:MyImpl2 # Implementation 2。
当然,实现类的注册办法并非只有这么一种,否则的话Discovery的实用性就要大打折扣了!实际上,按照Discovery内部的类查找机制,按照这种方法注册的类将是Discovery最后找到的类。另一种常用的注册方法是通过系统属性或用户定义的属性来传递实现类的名字,例如,放弃META-INF/services目录下的文件,改为执行java -DMyInterface=MyImpl1 DiscoveryDemo命令来运行示例程序,这里的系统属性是接口的名字,值是该接口的提供者,运行的结果是完全一样的。
Discovery还可以用来创建服务提供者的(singleton)实例并调用其方法,语法如下:((MyInterface) discover.newInstance(MyInterface.class)).myMethod();。注意在这个例子中,我们并不知道到底哪一个服务提供者实现了myMethod,甚至我们根本不必关心这一点。具体的情形与运行这段代码的方式以及运行环境中已经注册了什么服务提供者有关,在不同的环境下运行,实际得到的服务提供者可能不同。
2.3 Lang
■ 概况:Lang是java.lang的一个扩展包,增加了许多操作String的功能,另外还支持C风格的枚举量。
■ 官方资源:主页,二进制,源代码。
■ 何时适用:当java.lang包提供的方法未能满足需要,想要更多的功能来处理String、数值和System属性时;还有,当你想要使用C风格的枚举量时。
■ 示例应用:LangDemo.java,Mortgage.java,OnTV.java。CLASSPATH中必须包含commons-lang.jar。
■ 说明:
这个包提供了许多出于方便目的而提供的方法,它们中的大多数是静态的,简化了日常编码工作。StringUtils类是其中的一个代表,它使得开发者能够超越标准的java.lang.String包来处理字符串。使用这些方法很简单,通常只要在调用静态方法时提供适当的参数就可以了。例如,如果要将某个单词的首字符改为大写,只需调用:StringUtils.capitalise("name"),调用的输出结果是Name。请浏览StringUtils API文档了解其他静态方法,也许你会找到一些可以直接拿来使用的代码。本文提供的示例程序示范了其中一些方法的使用。
另一个值得注意的类是RandomStringUtils,它提供了生成随机字符串的方法,用来创建随机密码实在太方便了。
NumberUtils类提供了处理数值数据的方法,许多方法值得一用,例如寻找最大、最小数的方法,将String转换成数值的方法,等等。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() { return new ToStringBuilder(this). append("rate", this.rate). append("years", this.years). toString(); } }
本文地址:http://com.8s8s.com/it/it12015.htm