首页 > 资讯 >

使用 JCommander 解析命令行参数

2023-06-21 18:39:42 来源:程序员客栈
前言

如果你想构建一个支持命令行参数的程序,那么 jcommander 非常适合你,jcommander 是一个只有几十 kb 的 Java 命令行参数解析工具,可以通过注解的方式快速实现命令行参数解析。

这篇教程会通过介绍 jcommadner ,快速的创建一个命令行程序,最后支持的命令参数功能如下图。

这个命令行工具仿照 git 操作命令,主要提供了如下功能命令:


(资料图片仅供参考)

1. git-app.jar -help查看命令帮助信息。

2. git-app.jar -version查看当前版本号。

3. git-app.jar clone http://xxxx通过 URL 克隆一个仓库。

4. git-app.jar add file1 file2暂存 file1 文件 file2 文件。

5. git-app.jar commit -m "注释"提交并添加注释。

jcommander 引入

截止文章编写时间,最新版本如下:

com.beustjcommander1.82

jcommander 参数绑定

命令行解析中,参数解析与绑定是最实用的一个场景,jcommander 使用 Parameter注解进行参数绑定。我们定义一个 GitCommandOptions.java类来测试参数绑定。

package com.wdbyte.jcommander.v1;import com.beust.jcommander.Parameter;/** * @author https://www.wdbyte.com */public class GitCommandOptions {    @Parameter(names = {"clone"},        description = "克隆远程仓库数据")    private String cloneUrl;    public String getCloneUrl() {        return cloneUrl;    }}

使用 jcommander 结合 GitCommandOptions 来解析参数。

package com.wdbyte.jcommander.v1;import com.beust.jcommander.JCommander;/** * @author https://www.wdbyte.com */public class GitApp {    public static void main(String[] args) {            // args = new String[]{"clone","http://www.wdbyte.com/test.git"};        GitCommandOptions gitCommandOptions = new GitCommandOptions();        JCommander commander = JCommander.newBuilder()            .addObject(gitCommandOptions)            .build();        commander.parse(args);        System.out.println("clone " + gitCommandOptions.getCloneUrl());    }}

打包后可以执行命令参数:

$ java -jar git-app.jar clone http://www.wdbyte.com/test.gitclone http://www.wdbyte.com/test.git

这里是一个字符串参数,需要在命令中输出参数值,对于 boolean 类型的参数,不需要传值,有命令即为 true 值。

参数名称

@Parameter注解中的 names属性可以定义参数的名称。且可以指定多个参数名称,让我再添加 version参数和 help参数,同时设置参数别名。这两个参数是 boolean 类型。

@Parameter(names = {"help", "-help", "-h"},    description = "查看帮助信息",    help = true)private boolean help;@Parameter(names = {"version", "-version", "-v"},    description = "显示当前版本号")private boolean version = false;

参数限制

clone参数可以接受一个要克隆的 URL 链接,但是正常情况下只需要一个 URL 链接。可以通过 arity = 1进行限制。

@Parameter(names = {"clone"},    description = "克隆远程仓库数据",    arity = 1)private String cloneUrl;

帮助信息

使用 usage()参数可以打印命令帮助信息。

GitCommandOptions gitCommandOptions = new GitCommandOptions();JCommander commander = JCommander.newBuilder()    .addObject(gitCommandOptions)    .build();commander.parse(args);// 打印帮助信息commander.usage();

运行输出帮助信息:

$ java -jar git-app.jarUsage: [options]  Options:    clone      克隆远程仓库数据    help, -help, -h      查看帮助信息    version, -version, -v      显示当前版本号      Default: false

虽然正确的输出了帮助信息,但是其中有 main class这段,是因为我们没有指定项目名称,我们指定项目名称为 git-app。

JCommander commander = JCommander.newBuilder()            .programName("git-app")            .addObject(gitCommandOptions)            .build();

参数排序

在帮助信息中,如果想要自定义参数顺序,可以通过 order = 来排序,数字越小越靠前。

@Parameter(names = {"version", "-version", "-v"},    description = "显示当前版本号",    order = 2)private boolean version = false;

参数绑定完整测试

package com.wdbyte.jcommander.v2;import com.beust.jcommander.Parameter;/** * @author https://www.wdbyte.com */public class GitCommandOptions {    @Parameter(names = {"help", "-help", "-h"},        description = "查看帮助信息",        order = 1,        help = true)    private boolean help;    @Parameter(names = {"clone"},        description = "克隆远程仓库数据",        order = 3,        arity = 1)    private String cloneUrl;    @Parameter(names = {"version", "-version", "-v"},        description = "显示当前版本号",        order = 2)    private boolean version = false;    //...get method}

GitApp.java

package com.wdbyte.jcommander.v2;import com.beust.jcommander.JCommander;public class GitApp {    public static void main(String[] args) {        GitCommandOptions gitCommandOptions = new GitCommandOptions();        JCommander commander = JCommander.newBuilder()            .programName("git-app")            .addObject(gitCommandOptions)            .build();        commander.parse(args);        // 打印帮助信息        if (gitCommandOptions.isHelp()) {            commander.usage();            return;        }        if (gitCommandOptions.isVersion()) {            System.out.println("git version 2.24.3 (Apple Git-128)");            return;        }        if (gitCommandOptions.getCloneUrl() != null) {            System.out.println("clone " + gitCommandOptions.getCloneUrl());        }    }}

运行测试:

jcommander 参数验证

在上面的例子中, 假设 clone 命令传入的参数必须是一个 URL,那么我们就要进行参数验证,jcommander 也提供了特有的参数验证方式。

1. 编写参数验证类,需要实现 IParameterValidator接口。

package com.wdbyte.jcommander.v3;import java.net.MalformedURLException;import java.net.URL;import com.beust.jcommander.IParameterValidator;import com.beust.jcommander.ParameterException;/** * @author https://www.wdbyte.com */public class UrlParameterValidator implements IParameterValidator {    @Override    public void validate(String key, String value) throws ParameterException {        try {            new URL(value);        } catch (MalformedURLException e) {            throw new ParameterException("参数 " + key + " 的值必须是 URL 格式");        }    }}

2. clone参数指定验证类。

@Parameter(names = {"clone"},    description = "克隆远程仓库数据",    validateWith = UrlParameterValidator.class,    order = 3,    arity = 1)private String cloneUrl;

运行测试:

$ java -jar git-app.jar clone https://www.wdbyte.com/test.gitclone https://www.wdbyte.com/test.git$ java -jar git-app.jar clone test.gitException in thread "main" com.beust.jcommander.ParameterException: 参数 clone 的值必须是 URL 格式    at com.wdbyte.jcommander.v3.UrlParameterValidator.validate(UrlParameterValidator.java:19)    at com.beust.jcommander.ParameterDescription.validateParameter(ParameterDescription.java:377)    at com.beust.jcommander.ParameterDescription.validateParameter(ParameterDescription.java:344)

jcommander 子命令

在使用 git 时,我们经常会使用下面两个命令。

1. git add file1 file2暂存 file1 文件 file2 文件。

2. git commit -m "注释"提交并添加注释。

什么是子命令

这是一种很常见的操作,git commit除了可以跟 -m子参数外,还可以跟各种参数,通过 git 帮助文档可以看到。

git commit [-a | --interactive | --patch] [-s] [-v] [-u] [--amend]           [--dry-run] [(-c | -C | --fixup | --squash) ]           [-F | -m ] [--reset-author] [--allow-empty]           [--allow-empty-message] [--no-verify] [-e] [--author=]           [--date=] [--cleanup=] [--[no-]status]           [-i | -o] [-S[]] [--] [...]

这种有子参数的情况,我们可以称 commit为 git 的一个子命令,使用 jcommander 如何配置子命令呢?

jcommander 子命令实现

我们新增子命令对应的参数类 GitCommandCommit.java.

package com.wdbyte.jcommander;import com.beust.jcommander.Parameter;import com.beust.jcommander.Parameters;/** * git commit -m "desc" * @author https://www.wdbyte.com */@Parameters(commandDescription = "提交文件", commandNames = "commit")public class GitCommandCommit {      public static final String COMMAND = "commit";      @Parameter(names = {"-comment", "-m"},        description = "请输入注释",        arity = 1,        required = true)    private String comment;    public String getComment() {        return comment;    }}

代码中使用 @Parameters注解指定了子命令为 commit,同时使用 @Paramete注解指定子参数 -m,同时 -m参数是必须的,使用属性 required = true来指定。

使用 GitCommandCommit:

使用 addCommand添加 Commit命令参数类。

GitCommandOptions gitCommandOptions = new GitCommandOptions();GitCommandCommit commandCommit = new GitCommandCommit();JCommander commander = JCommander.newBuilder()    .programName("git-app")    .addObject(gitCommandOptions)    .addCommand(commandCommit)    .build();commander.parse(args);String parsedCommand = commander.getParsedCommand();if ("commit".equals(parsedCommand)) {    System.out.println(commandCommit.getComment());}

运行测试:

$ java -jar git-app.jar commit -m "注释一下"注释一下

同上,我们可以添加 add命令对应的参数类:GitCommandAdd.java. 这次我们定义一个 List 类型参数,但是不在属性上指定子参数名称。

package com.wdbyte.jcommander.v5;import java.util.List;import com.beust.jcommander.Parameter;import com.beust.jcommander.Parameters;/** * git add file1 file2 * * @author https://www.wdbyte.com */@Parameters(commandDescription = "暂存文件", commandNames = "add", separators = " ")public class GitCommandAdd {    public static final String COMMAND = "add";    @Parameter(description = "暂存文件列表")    private Listfiles;    public ListgetFiles() {        return files;    }}

同样添加到子命令:

JCommander commander = JCommander.newBuilder()    .programName("git-app")    .addObject(gitCommandOptions)    .addCommand(commandCommit)    .addCommand(commandAdd)    .build();commander.parse(args);if ("add".equals(parsedCommand)) {    for (String file : commandAdd.getFiles()) {        System.out.println("暂存文件:" + file);    }}

运行测试:

$ java -jar git-app.jar add file1.txt file2.txt暂存文件:file1.txt暂存文件:file2.txt

jcommander 参数转换

在上面的 GitCommandAdd代码中,add命令传入的都是文件路径,现在是使用 List来接收入参,通常情况想我们可能需要直接转换成方便操作的类型,如 File 或者 Path,这该如何方面的转换呢,jcommander 也提供了方便转换类。

首先编写一个转换类 FilePathConverter 用于把入参转换成 Path 类,同时校验文件是否存在

package com.wdbyte.jcommander;import java.nio.file.Files;import java.nio.file.Path;import java.nio.file.Paths;import com.beust.jcommander.IStringConverter;import com.beust.jcommander.ParameterException;/** * * @author https://www.wdbyte.com */public class FilePathConverter implements IStringConverter{    @Override    public Path convert(String filePath) {        Path path = Paths.get(filePath);        if (Files.exists(path)) {            return path;        }        throw new ParameterException(String.format("文件不存在,path:%s", filePath));    }}

通过注解指定转换类:

@Parameter(description = "暂存文件列表", converter = FilePathConverter.class)private Listfiles;

打包测试:

$ java -jar git-app.jar add file1 file2文件不存在,path:file1$ ls -ltotal 12448drwxr-xr-x  2 darcy  staff    64B  6 15 21:10 archive-tmpdrwxr-xr-x  3 darcy  staff    96B  6 15 21:10 classesdrwxr-xr-x  3 darcy  staff    96B  6 15 21:10 generated-sources-rw-r--r--  1 darcy  staff   5.6M  6 16 20:44 git-app.jar$ git-app.jar git-app.jar暂存文件:git-app.jar

总体测试

一如既往,文章代码都存放在 Github.com/niumoo/javaNotes.

参考:https://jcommander.org/

上一篇:

小龙虾尾肉多少钱一斤?

下一篇:

最后一页

x
推荐阅读

使用 JCommander 解析命令行参数

小龙虾尾肉多少钱一斤?

世界实时:从郑州站到郑州东站坐地铁需要多长时间_郑州站到郑州东站多远

《堡垒之夜》或再次联动《巫师》推出希里角色捆绑包

科学幼小衔接,高埂学校助力孩子有准备地进入小学

环球百事通!民生银行济南高新支行:警惕高息诱惑 远离非法集资

切尔西告别坎特:帮助球队拿到多个冠军,谢谢你所做的一切 当前资讯

焦点消息!买到“农夫山贼”矿泉水?警方:当事人图好玩转发,已被行拘

热水瓶多少升合适_热水瓶多少升|环球焦点

【全球时快讯】2024年5G智能手机渗透率预计将达到72%

天天视点!多措并举凝聚转型发展“青力量”

一加 Ace 2V拍照有微距模式吗 每日消息

端午旅游“热度”攀升 文化游受青睐

当前信息:幽门螺杆菌口臭动图_幽门螺杆菌会口臭吗

【全球快播报】假期见闻手抄报模板_假期见闻手抄报

刘秀萍_关于刘秀萍的介绍-世界报资讯

二乙二醇(二甘醇)商品报价动态(2023-06-21)-观热点

唐山全力营造一流营商环境

郏县:早熟甜桃抢“鲜”上市 桃果经济促增收

世界热议:绵阳警方:一男子造谣“大学生涉嫌卖淫800多次”,已刑拘

通讯!江苏、奥地利举办技术创新合作对接交流会

十万嬉皮田馥甄 十万嬉皮

中国戏曲文化周“小戏台”群众性票房展演好戏不断|环球精选

亚洲藤球运动员浙江金华开赛 竞技“脚踢的排球”

天天微资讯!200场123球!C罗里程碑狂刷三大历史纪录,绝杀后疯狂庆祝

画眼线的五种简单方法视频教程_画眼线的五种简单方法 环球即时看

“熊猫走世界”再开课!七一实验小学学子与新西兰学子共画“蓉宝” 全球球精选

可喜可贺!国乒功勋名帅陈玘身份升级,任周雨证婚人,马龙送祝福-环球热门

海南椰岛管理层变动频繁 董事长王晓晴辞职后 董秘也辞职了-世界速递

李呈金:6.20黄金继续昨日未完成的跌势,美原油看震荡反弹冲高,黄金原油操作建议

全球快讯:日本茨城县一购物中心停车场内3人死亡 初步认定为自杀

环球热讯:赶潮流,迎风而上,智慧梁场打造智慧工地加速中华建设

丙二醇乙醚商品报价动态(2023-06-20) 世界动态

【世界时快讯】基本面数据全面下滑,新房二手房价格走弱

教育部公布最新高校名单!这些在天津!

天天速读:均普智能墨西哥工厂获美国造车新势力Rivian电驱订单

东风本田2023款CR-V e:PHEV全系降价2万元

2023年上海一级建造师考试报名网站

快消息!不点台大生提问遭呛声?侯办批民进党造谣

大举招兵买马!富士康造车之路再提速

当前热讯:大学生赚钱的方法门路_大学生赚钱的方法

2036年申奥结果(2036)

签约面积近1万平方米 第七届进博会招展正式启动

天天快播:百日千万招聘专项行动举办

眼馋ETF规模飙增机会 中小券商多业务线全面出击 新资讯

江丰电子(300666):6月19日北向资金减持9.59万股

Ale成Uzi比赛服首个好友:希望明年还能和你在比赛服上见!

欧足3消息:梅西夺冠半年发文 卢卡库宣誓留国米 恩里克入主巴黎-每日头条

宿建德江古诗带拼音正版 宿建德江古诗原文拼音

当前通讯!神偷奶爸(关于神偷奶爸介绍)