使用Apache Commons CLI开发命令行工具

时间:2022-02-04 17:06:44

使用Apache Commons CLI开发命令行工具分成三步: 
1)定义CLI 
2)解析CLI 
3)处理CLI 
首先我们参考官网给出的一个例子:

ant [options] [target [target2 [target3] ...]]
Options:
-help print this message
-projecthelp print project help information
-version print the version information and exit
-quiet be extra quiet
-verbose be extra verbose
-debug print debugging information
-emacs produce logging information without adornments
-logfile <file> use given file for log
-logger <classname> the class which is to perform logging
-listener <classname> add an instance of class as a project listener
-buildfile <file> use given buildfile
-D<property>=<value> use value for given property
-find <file> search for buildfile towards the root of the
filesystem and use it
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

该例子是ant的命令,我们可以对照着进行开发(其实官网就有,英文好的可以直接移步 
(https://commons.apache.org/proper/commons-cli/usage.html))。

定义CLI:

首先参照上面的三部曲,第一步定义CLI: 
Apache Commons CLI使用Option表示每一个命令,使用Options封装多个Option,创建Option的方式有三种:

  1. Option op = new Option(…);//构造器
  2. Options.addOption(…);//Options直接构造
  3. Option.Builder辅助类 
    1.2适合简单的创建的命令,如上面logfile命令以上的命令。我们举几个例子:
Options ops = new Options();
Option help = new Option( "help", "print this message" );
ops.addOption(help);
ops.addOption("projecthelp", "print project help information");
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4

同时如果我们假设debug命令后可跟值true/false,那么我们可以这样定义命令:

ops.addOption("debug", true, "print debugging information"); //第二个参数true表示该命令后可跟参数,其实就是命令后面跟上值
 
 
  • 1
  • 1

下面我们看logfile以下除去-D<property>=<value> 之外的的命令如何创建,这里使用第三种方式:

Option logfile = Option.builder("logfile").argName("file").hasArg().desc("use given file for log").build();// argName指定命令后跟的参数名称
ops.addOption(logfile);
  • 1
  • 2
  • 1
  • 2

最后我们看看如何定义-D<property>=<value>

Option D = Option.builder("D").argName("property=value").numberOfArgs(2).valueSeparator("=")
.desc("use value for given property").build();// 这里numberOfArgs指定了后跟两个参数,且valueSeparator指定了连接符是=,这样CLI可以自动帮我们解析键值对
ops.addOption(D);
  • 1
  • 2
  • 3
  • 1
  • 2
  • 3

解析CLI:

以上全部定义好之后,就可以对传入的参数进行解析了。DefaultParser类是用来解析参数,得到每个命令以及对应的值,而且对于如上面的-D<property>=<value> 这种命令,由于我们制定了“=”为分隔符,DefaultParser可以自动为我们将参数解析成Properties,很方便。

CommandLine comm = null;
try {
comm = new DefaultParser().parse(ops, args);
} catch (ParseException e) {
e.printStackTrace();
log.error("解析参数失败,参数:[" + Arrays.asList(args).toString() + "]");
throw new IllegalArgumentException();
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

处理CLI

上面已经对传入的参数解析好了,剩下的就是获取到这些命令的值,以及进行相应的处理了,也就是我们的业务逻辑了。

if (comm.getOptions().length == 0) {
log.info("No any param to specify.");
return;
}
if (comm.hasOption("h")) {// help
HelpFormatter formatter = new HelpFormatter();
formatter.printHelp("options", ops);
}
if (comm.hasOption("s")) {// 执行命令
new SystemCommand().execute(comm.getOptionValue("s"));
}
if (comm.hasOption("D")) {// 传递参数
Properties props = comm.getOptionProperties("D");
new ParamParser(props).parse();
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

上面是一个简单的例子,这里有个getOptionProperties方法,这个方法是针对使用分隔符的命令方便获取键值对行为的属性值而设计的,很好用,免去了自己再做字符串切分的麻烦。 
到这里整个使用Apache Commons CLI开发命令行工具的工作就完成了,很简单。

  • Apache Commons CLI总共支持的几种命令模式:
  • POSIX like options (ie. tar -zxvf foo.tar.gz)
  • GNU like long options (ie. du –human-readable –max-depth=1)
  • Java like properties (ie. java -Djava.awt.headless=true -Djava.net.useSystemProxies=true Foo)
  • Short options with value attached (ie. gcc -O2 foo.c)
  • long options with single hyphen (ie. ant -projecthelp) 
    对于GNU模式官网还有一个例子,可以自行参考下。 
    附上官网的一个Option的属性表:
Name Type Description
opt java.lang.String the identification string of the Option.
longOpt java.lang.String an alias and more descriptive identification string.
description java.lang.String a description of the function of the option.
required boolean a flag to say whether the option must appear on the command line.
arg boolean a flag to say whether the option takes an argument.
args boolean a flag to say whether the option takes more than one argument.
optionalArg boolean a flag to say whether the option’s argument is optional.
argName java.lang.String the name of the argument value for the usage statement.
valueSeparator char the character value used to split the argument string, that is used in conjunction with multipleArgs e.g. if the separator is ‘,’ and the argument string is ‘a,b,c’ then there are three argument values, ‘a’, ‘b’ and ‘c’.
type java.lang.Object the type of the argument.
value java.lang.String the value of the option.
values java.lang.String[] the values of the option.

参考文章: 
使用 Apache Commons CLI 开发命令行工具 
Apache Commons CLI

原文地址点击打开链接