使用JCommander开发命令行交互(CLI)式JAVA程序

2020-12-10 10:55:45 浏览数 (1)

参考链接: Java中的命令行参数

一、前言 

最近在看pulsar源码时,发现他们使用了JCommander来开发命令行交互程序,便对这个framework产生了兴趣。 传统意义上讲,JAVA并不是开发命令行程序最合适的语言,但是因为依赖一些特定JAVA库(特别是大数据相关的)的CLI程序,用java来开发却是最方便的。 

pulsar相关源码:https://github.com/apache/pulsar/blob/branch-2.1/pulsar-testclient/src/main/java/org/apache/pulsar/testclient/PerformanceProducer.javaJCommander相关源码:https://github.com/cbeust/jcommander 

二、常见的linux命令行风格 

首先我们先了解下常见的linux命令行风格: 

Unix 风格参数,前面加单破折线 -BSD 风格参数,前面不加破折线GNU 风格参数,前面加双破折线 –JAVA 风格参数 

Unix风格 

Unix是从贝尔实验室开发的AT&T Unix系统上原有的命令继承下来的。 

ls -a

ls -lah

-后面可以跟多个字母,多个字母就是多个参数 

BSD风格 

ps aux

参数不带- 

GNU风格 

两个减号 – 加参数,一般后边的参数是跟上一个单词或短语 

ps --no-headers

当然Unix和GUN风格很多混用,如ls -a 等于ls --all,-h 往往对应 --help 

JAVA风格 

比如java的命令行,-后面直接是单词 

java -version

java -Djava.awt.headless=true -Djava.net.useSystemProxies=true Foo

三、JCommander 

快速入门 

首先我们看下官方的demo快速入门 

java源程序 

public class JCommanderTest {

    @Parameter

    public List<String> parameters = Lists.newArrayList();

    @Parameter(names = { "-log", "-verbose" }, description = "Level of verbosity")

    public Integer verbose = 1;

    @Parameter(names = "-groups", description = "Comma-separated list of group names to be run")

    public String groups;

    @Parameter(names = "-debug", description = "Debug mode")

    public boolean debug = false;

    @DynamicParameter(names = "-D", description = "Dynamic parameters go here")

    public Map<String, String> dynamicParams = new HashMap<String, String>();

}

所以我们这样调用 

JCommanderTest jct = new JCommanderTest();

String[] argv = { "-log", "2", "-groups", "unit1,unit2,unit3",

                    "-debug", "-Doption=value", "a", "b", "c" };

JCommander.newBuilder()

  .addObject(jct)

  .build()

  .parse(argv);

Assert.assertEquals(2, jct.verbose.intValue());

Assert.assertEquals("unit1,unit2,unit3", jct.groups);

Assert.assertEquals(true, jct.debug);

Assert.assertEquals("value", jct.dynamicParams.get("option"));

Assert.assertEquals(Arrays.asList("a", "b", "c"), jct.parameters);

不难发现,JCommander有如下几个特点: 

注解驱动:@DynamicParameter(names = “-D”, description = “Dynamic parameters go here”) 一个类似注解(装饰)轻松做到命令行参数与属性的映射功能强大:支持多种风格,并可自动生成文档拓展性强 

Jcommander属性值 

names 设置命令行参数,如-oldrequired 设置此参数是否必须description 设置参数的描述order 设置帮助文档的顺序help 设置此参数是否为展示帮助文档或者辅助功能 

其中help最为强大,如demo 

    @Parameter(names = "--help", help = true, order = 5)

    private boolean help;

则如下使用即可生成完善的文档 

        if (help) {

            jCommander.usage();

            return;

        }

Usage: <main class> [options]

  Options:

    --help

    -debug

      Debug mode

      Default: true

    -host

      The host

      Default: []

    -password

      Connection password

密码类参数处理 

在实际程序中,我们往往会遇到很多类似要输入密码的场景。此时我们并不希望密码出现在history中,你可以使用password这种类型,这样JCommander会让你在console中输入。 

public class ArgsPassword {

  @Parameter(names = "-password", description = "Connection password", password = true)

  private String password;

}

正则表达式校验 

当用户产生于预期不一致的输入时,我们希望便捷地使用正则表达式来校验这些值。 

@Parameter(names = "-v",  validateWith = RegexValidator.class)

@Regex("(2\.0|1\.0)")

private String version = "2.0";

其他 

当然我们还可以使用Apache Commons CLI实现相关功能 

四、参考 

http://www.jcommander.orghttps://blog.csdn.net/adalf90/article/details/80492795 

文章首发云 社区:https://cloud.tencent.com/developer/article/1366912

0 人点赞