写点什么

Java 命令行解析方式探索(二):Apache Commons CLI

作者:冰心的小屋
  • 2023-07-26
    北京
  • 本文字数:2642 字

    阅读完需:约 9 分钟

Java 命令行解析方式探索(二):Apache Commons CLI

使用 Apache Commons CLI 工具包可以更加规范的处理命令行参数,同时支持多种参数风格:


  • POSIX:tar -zxvf foo.tar.gz

  • GNU:du --human-readable --max-depth=1

  • Java:java -Djava.awt.headless=true -Djava.net.useSystemProxies=true Foo

  • 其他:gcc -O2 foo.c ant -projecthelp


该工具处理命令行参数可分为三个阶段:定义阶段、解析阶段和服务阶段。

1. 定义阶段

定义待解析的命令行参数,设置命令行参数的限定属性,例如名称、是否必须、类型和描述信息等。

你可以通过创建 Option 类的实例来定义命令行参数,创建 Option 类的实例有多种途径:

Options options = new Options();
// 方式1:通过调用Options提供的方法options.addOption("t", "thread",true, "并发数");
// 方式2:通过创建Option类的实例options.addOption(new Option("c", "count", true, "调用次数"));
// 方式3:通过Option内部类Builder使用流式方式构建options.addOption(Option.builder("s") .longOpt("second") .required() .hasArg() .desc("调用时长:单位秒") .build());
复制代码


推荐使用流式方式构建 Option,直观流畅:

package com.ice.impl;
import com.ice.Parameter;import com.ice.Starter;import org.apache.commons.cli.CommandLine;import org.apache.commons.cli.Option;import org.apache.commons.cli.Options;
public class CommonCLIStarter extends Starter { private static final String THREAD_NAME = "t"; private static final String COUNT_NAME = "c"; private static final String SECOND_NAME = "s"; private static final String PROPERTY_NAME = "p"; private static final String OUTPUT_NAME = "o";
public CommonCLIStarter(String[] args) { super(args); }
@Override protected Parameter parse() { // 1. 定义阶段 Options options = stage1();
// 2. 解析阶段 CommandLine commandLine = stage2(options);
// 3. 服务阶段 return stage3(commandLine); }
private Options stage1() { return new Options() .addOption(Option.builder(THREAD_NAME) .longOpt("thread") .required() .hasArg() .desc("并发数") .build()) .addOption(Option.builder(COUNT_NAME) .longOpt("count") .required() .hasArg() .desc("调用次数") .build()) .addOption(Option.builder(SECOND_NAME) .longOpt("second") .required().hasArg() .desc("调用时长:单位秒") .build()) .addOption(Option.builder(PROPERTY_NAME) .longOpt("property") .hasArgs() .valueSeparator() .numberOfArgs(2) .desc("自定义扩展属性") .build()) .addOption(Option.builder(OUTPUT_NAME) .longOpt("output") .hasArg() .desc("结果输出到文件中") .build()); }
private CommandLine stage2(Options options) { return null; }
private Parameter stage3(CommandLine commandLine) { return null; }}
复制代码

2. 解析阶段

命令行参数定义完毕,你需要使用默认的解析器 DefaultParser 类来解析实际的 args 数组,对于 DefaultParser 类主要的工作内容如下:

  1. 通过访问者模式处理 args 数组元素,验证该元素的合法性,校验参数的类型是标识符还是具体值等;

  2. 校验必要参数是否缺失;

  3. 参数默认值的设置。

继续编写解析阶段的代码:

private CommandLine stage2(Options options) {    CommandLineParser parser = new DefaultParser();
try { return parser.parse(options, args); } catch (Exception e) { throw new IllegalArgumentException("Parsed parameters error", e); }}
复制代码

3. 服务阶段

通过解析阶段返回的 CommandLine 类的实例来访问命令行参数实际的值:

private Parameter stage3(CommandLine commandLine) {    PlanParameter parameter = new PlanParameter();    parameter.setThread(Integer.parseInt(commandLine.getOptionValue(THREAD_NAME)));    parameter.setCount(Integer.parseInt(commandLine.getOptionValue(COUNT_NAME)));    parameter.setSecond(Integer.parseInt(commandLine.getOptionValue(SECOND_NAME)));    parameter.setOutput(commandLine.getOptionValue(OUTPUT_NAME));
if (commandLine.hasOption(PROPERTY_NAME)) { Properties properties = commandLine.getOptionProperties(PROPERTY_NAME); if (properties != null && properties.size() > 0) { Map<String, String> property = new HashMap<>(); parameter.setProperty(property); for (Map.Entry<Object, Object> entity : properties.entrySet()) { property.put(String.valueOf(entity.getKey()), String.valueOf(entity.getValue())); } } }
return parameter;}
复制代码


三个阶段的涉及代码编写完毕,让我们来编写单元测试用例,校验结果的正确性:

package com.ice;
import com.ice.impl.CommonCLIStarter;import org.junit.Test;
public class CLIParameterTest extends ParameterTest { @Test @Override public void startTest() { Starter starter = new CommonCLIStarter(args); Parameter parameter = starter.parse(); validate(parameter); }}
复制代码


单元测试通过:


该项目的代码已经上传 github:https://github.com/libingxin/api-test

发布于: 刚刚阅读数: 5
用户头像

分享技术上的点点滴滴! 2013-08-06 加入

一杯咖啡,一首老歌,一段代码,欢迎做客冰屋。

评论

发布
暂无评论
Java 命令行解析方式探索(二):Apache Commons CLI_Java_冰心的小屋_InfoQ写作社区