文档章节

Commons CLI 入门及代码简单分析

jiangmitiao
 jiangmitiao
发布于 2016/08/16 10:21
字数 982
阅读 180
收藏 3

前言

        以前写过一些命令行程序,在需要带参数的时候都是自己来判断args,导致程序光解析args都占了好大一堆,而且解析代码也不美观。

        偶然间发现了apache公共库中的cli库,在这里分享给大家。

入门

commons-cli中把解释参数分为三种状态,分别是定义、解释和询问交互。

接下来,我以一个例子做一下说明:

maven库:

<dependency>
        <groupId>commons-cli</groupId>
        <artifactId>commons-cli</artifactId>
        <version>1.3.1</version>
</dependency>
import org.apache.commons.cli.*;

public class CLI {
    public static void main(String[] args) throws ParseException {
        //定义
        Options options = new Options();
        options.addOption("h",false,"list help");//false代表不强制有
        options.addOption("t",true,"set time on system");

        //解析
        //1.3.1中已经弃用针对不同格式入参对应的解析器
        //CommandLineParser parser = new PosixParser();
        CommandLineParser parser = new DefaultParser();
        CommandLine cmd = parser.parse(options,args);

        //查询交互
        //你的程序应当写在这里,从这里启动
        if (cmd.hasOption("h")){
            String formatstr = "CLI  cli  test";
            HelpFormatter hf = new HelpFormatter();
            hf.printHelp(formatstr, "", options, "");
            return;
        }

        if (cmd.hasOption("t")){
            System.out.printf("system time has setted  %s \n",cmd.getOptionValue("t"));
            return;
        }

        System.out.println("error");
    }
}

在另一个类中做一下测试

String argss[]={"-t  1000"};
CLI.main(argss);

结果是:

system time has setted    1000 

String argss[]={"-h"};
CLI.main(argss);

结果是:

usage: CLI  cli  test
 -h         list help
 -t <arg>   set time on system

 

好啦,入门就到这里了。

代码结构分析

包组织结构:

commons-cli-1.3.1.jar

\org\apache\commons\cli

在cli包中,包含了所有的类,包括定义,解析,查询交互和Exception

类的结构图如下

定义

在定义这一部分,最重要的类是Option,Option类中定义了一个基本的选项,例如-t xxx ,是否为必选项,该命令的解释等等。

Option重写了很多构造函数,但是最终都调用下面这个构造函数:

public Option(String opt, String longOpt, boolean hasArg, String description)
           throws IllegalArgumentException
    {
        //写这个代码的人以前应该是写C++的。。。
        // 判断短选项是否包含非法字符,如果包含抛出异常
        OptionValidator.validateOption(opt);
        //短选项
        this.opt = opt;
        //长选项
        this.longOpt = longOpt;

        // 是否是必要选项
        if (hasArg)
        {
            this.numberOfArgs = 1;
        }
        //选项描述
        this.description = description;
    }

OptionsGroup类中包含了许多个Option,并可以对多个Option进行一些处理。其实现是采用一个HashMap来存储Option的,key是Option中的长选项或者短选项的第一个字符,如果短选项存在,则优先选择短选项。

OptionGroup类还包含了一个组描述和组是否必须存在,相当于对一群Option的群组操作。

Options类是被解析的对象,使用者可以在Options实例中直接添加命令,也可以添加Option实例,也可以添加OptionGroup实例。

其addOption方法最终调用了其重写的一个方法:

public Options addOption(Option opt)
    {
        String key = opt.getKey();

        // add it to the long option list
        if (opt.hasLongOpt())
        {
            longOpts.put(opt.getLongOpt(), opt);
        }

        // if the option is required add it to the required list
        if (opt.isRequired())
        {
            if (requiredOpts.contains(key))
            {
                requiredOpts.remove(requiredOpts.indexOf(key));
            }
            requiredOpts.add(key);
        }

        shortOpts.put(key, opt);

        return this;
    }

添加GroupOption方法如下:

public Options addOptionGroup(OptionGroup group)
    {
        if (group.isRequired())
        {
            requiredOpts.add(group);
        }

        for (Option option : group.getOptions())
        {
            // an Option cannot be required if it is in an
            // OptionGroup, either the group is required or
            // nothing is required
            option.setRequired(false);
            addOption(option);

            optionGroups.put(option.getKey(), group);
        }

        return this;
    }

解析

接下来就是CommandLineParser接口,在1.3.1版本中取消了Parser抽象类,GnuParser、BasicParser、PosixParser类,取而代之的是DefaultParser类。DefaultParser类提供了对Options实例的解析,即对入参命令和Options实例之间对应关系的解析,返回的类是CommandLine。如果入参命令与Options实例对应不上就会抛出解析异常。

DefaultParser类解析方法最基本的方法是handleToken(String token),token是每一个入参字符串。这个方法会在解析错误的时候抛出解析异常。

 

查询交互

CommandLine可以对入参命令进行判断解析,例如可以查询是否存在某个选项,以及获取这个选项的值。

 

cli包还是相当简单的,大家也可以自己看一看commons库的源码。

 

更多文章:http://blog.gavinzh.com

© 著作权归作者所有

共有 人打赏支持
jiangmitiao

jiangmitiao

粉丝 16
博文 48
码字总数 44413
作品 1
朝阳
程序员
rocketmq番外篇(一):开发命令行

匠心零度 转载请注明原创出处,谢谢! 说在前面 虽然是以rocketmq引出的开发命令行,但是任何java应用如果需要都可以借鉴引用,也是通用技术。 主题 rocketmq使用例子 Apache Commons CLI简介...

匠心零度
04/17
0
0
Apache Commons CLI命令行启动

今天又看了下Hangout的源码,一般来说一个开源项目有好几种启动方式——比如可以从命令行启动,也可以从web端启动。今天就看看如何设计命令行启动... Apache Commons CLI Apache Commons CLI...

青夜之衫
2017/12/05
0
0
Apache Commons CLI官方文档翻译 —— 快速构建命令行启动模式

昨天通过几个小程序以及Hangout源码学习了CLI的基本使用,今天就来尝试翻译一下CLI的官方使用手册。 下面将会通过几个部分简单的介绍CLI在应用中的使用场景。 昨天已经联系过几个基本的命令行...

青夜之衫
2017/12/05
0
0
RabbitMQ入门(2)--工作队列

工作队列 (使用Java客户端) 在这第一指南部分,我们写了通过同一命名的队列发送和接受消息。在这一部分,我们将会创建一个工作队列,在多个工作者之间使用分布式时间任务。工作队列(亦称:任...

-悟空-
2015/02/24
0
8
使用 Apache Commons CLI 开发命令行工具示例

概念说明 Apache Commons CLI 简介 Apache Commons CLI 是 Apache 下面的一个解析命令行输入的工具包,该工具包还提供了自动生成输出帮助文档的功能。 Apache Commons CLI 支持多种输入参数格...

cloud-coder
2015/01/05
0
11

没有更多内容

加载失败,请刷新页面

加载更多

下一页

又一个centos文件顺序导致的问题

背景 新的centos似乎对于文件顺序做了特别的优化 和文件顺序出现的问题确实多了不少 centos7导致的spring循环依赖【实际上和这个问题不一样 不过由此衍生出的问题】 某应用放在新的系统开始报...

Mr_Qi
12分钟前
0
0
阿里云国际版香港CN2测评 月付9美元/30M带宽/1T流量

市面上很多家香港VPS服务商,一直都说阿里云国际版香港CN2线路好,延迟低,速度快,价格便宜流量还多,那么这个香港线路到底怎么样呢?本文从性能、延时、路由、速度方面来全方面测评一下阿里...

flyzy2005
54分钟前
0
0
撤销git commit --amend

it commit -amend之后想撤销 git reset HEAD@{1}

xiaomge
今天
0
0
有意思的TimeUnit

java.util.concurrent.TimeUnit 这个类,相信童鞋们都不陌生。它是一个enum: public enum TimeUnit 好吧,我一直把它当做一个枚举类来用。偶然看到还有别的用法,大吃一斤,原来 TimeUnit 并...

polly
今天
10
0
生成pyc

Python生成pyc文件 pyc文件是py文件编译后生成的字节码文件(byte code)。pyc文件经过python解释器最终会生成机器码运行。所以pyc文件是可以跨平台部署的,类似Java的.class文件。一般py文件改...

Mr_Tea伯奕
今天
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部