资讯专栏INFORMATION COLUMN

Commons CLI 入门及代码简单分析

Apollo / 2453人阅读

摘要:入门中把解释参数分为三种状态,分别是定义解释和询问交互。如果入参命令与实例对应不上就会抛出解析异常。查询交互可以对入参命令进行判断解析,例如可以查询是否存在某个选项,以及获取这个选项的值。

前言

以前写过一些命令行程序,在需要带参数的时候都是自己来判断args,导致程序光解析args都占了好大一堆,而且解析代码也不美观。
偶然间发现了apache公共库中的cli库,在这里分享给大家。

入门

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

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

maven库:


        commons-cli
        commons-cli
        1.3.1

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 
",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 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抽象类,GnuParserBasicParserPosixParser类,取而代之的是DefaultParser类。DefaultParser类提供了对Options实例的解析,即对入参命令和Options实例之间对应关系的解析,返回的类是CommandLine。如果入参命令与Options实例对应不上就会抛出解析异常。

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

查询交互

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

总结

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

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

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/65114.html

相关文章

  • 180718-jar包执行传参使用小结

    摘要:包执行时传参的使用姿势虽说我们现在大多不太直接使用包运行方式,目前比较主流的是将自己的服务丢在某个容器中如,等运行,比如我之前所属的电商公司,就是将项目打包为包,丢到容器中运行的在使用时,可能会出现直接打包一个可执行的,然后运行,这种时候, showImg(https://segmentfault.com/img/remote/1460000015684728); jar包执行时传参的...

    red_bricks 评论0 收藏0
  • #yyds干货盘点# Spring Boot的前世今生以它和Spring Cloud的关系详解。

    摘要:经过年时间的发展,到目前为止,最新稳定版为版本。的发展刚出生的时候,引起了很多开源社区的关注,并且也有个人和企业开始尝试使用。通过项目搭建过程来对比的差异和优势。当然它的作用不仅于此,后续会逐步揭开它的真实面目。而和就相当于当年的和的关系。 要了解Spring Boot的发展背景,还得从2004年Spring ...

    番茄西红柿 评论0 收藏2637
  • 强推!大牛程序员必备的Java日志框架,性能无敌

    摘要:本文要来分享给大家程序员最常用的日志框架组件。没有基础的同学也不要着急,这套教程覆盖了目前所有的日志框架,只要你学,就一定用得到,先收藏,以备不时之需。 作为一名Java程序员,我们开发了很多Java应用程序,包括桌面应用、WEB应用以及移动应用。然而日志系统是一个成熟Java应用所必不可少的。在开发和调试阶段,日志可以帮...

    zebrayoung 评论0 收藏0
  • 关于Vue2一些值得推荐的文章 -- 五、六月份

    摘要:五六月份推荐集合查看最新的请点击集前端最近很火的框架资源定时更新,欢迎一下。苏幕遮燎沈香宋周邦彦燎沈香,消溽暑。鸟雀呼晴,侵晓窥檐语。叶上初阳乾宿雨,水面清圆,一一风荷举。家住吴门,久作长安旅。五月渔郎相忆否。小楫轻舟,梦入芙蓉浦。 五、六月份推荐集合 查看github最新的Vue weekly;请::点击::集web前端最近很火的vue2框架资源;定时更新,欢迎 Star 一下。 苏...

    sutaking 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<