commons-io

最初于2002年发布的Apache Commons CLI可能是使用最广泛的Java命令行解析器,但是它的API显示了它的年龄。 寻找具有最少样板代码的现代方法的应用可能对picocli感兴趣。 为什么要花麻烦的钱进行迁移,以及如何将基于Commons CLI的应用程序迁移到picocli? Picocli提供了一种流畅的API,具有强大的输入功能,ANSI颜色的使用帮助,自动补全功能以及许多其他功能。 让我们以Checkstyle为例。

为什么要迁移?

从Commons CLI迁移到picocli是否值得解决? 从一个命令行解析器转到另一个命令行解析器有什么好处? 这不仅仅是重新装修我们应用程序的客厅吗?

最终用户体验

对最终用户有什么好处?

命令行完成。 基于Picocli的应用程序可以在bash和zsh shell以及基于JLine的交互式shell应用程序中具有命令行完成功能。

漂亮的,易读的用法帮助消息。 Commons CLI生成的使用帮助有点简单。 picocli开箱即用,可生成使用ANSI样式和颜色进行对比的帮助,以强调诸如命令,选项和参数之类的重要信息。 使用注释可以轻松自定义帮助消息的布局。 此外,如果您需要其他帮助,还有一个帮助API。 有关一些示例屏幕截图,请参见picocli自述文件。

通过@ -files或“ argument files”支持非常大的命令行。 有时用户需要指定比操作系统或外壳程序支持的命令行更长的命令行。 当picocli遇到以字符@开头的参数时,它将文件的内容扩展到参数列表中。 这允许应用程序处理任意长度的命令行。

开发人员经验

作为开发人员,对您有什么好处?

通常,picocli应用程序的代码要比Commons CLI的代码少得多。 picocli批注允许应用程序以声明性的方式定义选项和位置参数,所有信息都放在一个位置。 此外,picocli还提供了许多便利,例如类型转换和自动帮助,这些便利照顾了一些机制,因此应用程序可以将更多精力放在业务逻辑上。 本文的其余部分将更详细地说明这一点。

文档:picocli具有广泛的用户手册和详细的javadoc 。

故障排除。 Picocli具有内置的跟踪工具,以方便进行故障排除。 最终用户可以使用系统属性picocli.trace来控制跟踪级别。 支持的级别为OFFWARNINFODEBUG 。 默认跟踪级别为WARN

未来扩展

最后,除了立即获得回报之外,从Commons CLI迁移到picocli还可以获得任何未来的好处吗?

Picocli具有许多高级功能。 您的应用程序可能尚未使用这些功能,但是如果您想将来扩展应用程序,picocli支持嵌套子命令(以及子子命令到任何深度),可重复使用的mixins ,可轻松与Dependency Injection容器集成以及一个不断发展的工具框架,可从picocli CommandSpec模型生成源代码,文档和配置文件。

最终,picocli得到了积极维护,而Commons CLI似乎在16年内发布了6个版本,几乎处于停滞状态。

迁移示例:CheckStyle

命令行应用程序需要做三件事:

  1. 定义支持的选项
  2. 解析命令行参数
  3. 处理结果

让我们以CheckStyle的com.puppycrawl.tools.checkstyle.Main命令行实用工具为例,比较在Commons CLI和picocli中如何完成此操作。

完整的源代码之前和之后的迁移是在GitHub上。

定义选项和位置参数

使用Commons CLI定义选项

Commons CLI有多种定义选项的方式: Options.addOption ,构造一个new Options(…​)并在此对象,已弃用的OptionBuilder类和推荐的Option.Builder类上调用方法。

Checkstyle Main类使用Options.addOption方法。 首先为选项名称定义一些常量:

/** Name for the option 's'. */
private static final String OPTION_S_NAME = "s";/** Name for the option 't'. */
private static final String OPTION_T_NAME = "t";/** Name for the option '--tree'. */
private static final String OPTION_TREE_NAME = "tree";... // and more. Checkstyle Main has 26 options in total.

Main.buildOptions方法使用以下常量来构造和返回Commons CLI Options对象,该对象定义了受支持的选项:

private static Options buildOptions() {final Options options = new Options();options.addOption(OPTION_C_NAME, true, "Sets the check configuration file to use.");options.addOption(OPTION_O_NAME, true, "Sets the output file. Defaults to stdout");...options.addOption(OPTION_V_NAME, false, "Print product version and exit");options.addOption(OPTION_T_NAME, OPTION_TREE_NAME, false,"Print Abstract Syntax Tree(AST) of the file");...return options;
}

使用Picocli定义选项

在picocli中,您可以使用类似于Commons CLI方法的构建器以编程方式定义支持的选项,也可以使用注释以声明方式定义支持的选项。

对于并非事先知道所有选项的动态应用程序,Picocli的编程API可能会有用。 如果您对编程方法感兴趣,请查看CommandSpecOptionSpecPositionalParamSpec类。 另请参阅编程API 。

在本文中,我们将使用picocli批注。 对于CheckStyle示例,它看起来类似于以下内容:

@Option(names = "-c", description = "Sets the check configuration file to use.")
private File configurationFile;@Option(names = "-o", description = "Sets the output file. Defaults to stdout")
private File outputFile;@Option(names = "-v", versionHelp = true, description = "Print product version and exit")
private boolean versionHelpRequested;@Option(names = {"-t", "--tree"}, description = "Print Abstract Syntax Tree(AST) of the file")
private boolean printAST;

比较方式

陈述式

使用Commons CLI,您可以通过调用具有String值的方法来构建规范。 此类API的一个缺点是,良好的样式会迫使客户端代码定义常量以避免“不可思议的值”,就像Checkstyle Main类尽职尽责。

使用picocli,所有信息都集中在一个地方。 注释仅接受String文字,因此定义和用法会自动放在一起,而无需声明常量。 这样可以使代码更简洁,代码更少。

强类型

Commons CLI使用布尔标志来表示该选项是否带有参数。

Picocli使您可以直接使用类型。 根据类型,picocli“知道”该选项需要多少个参数: boolean字段没有参数, CollectionMap和array字段可以有零个到任意数量的参数,任何其他类型意味着这些选项只包含一个参数论据。 可以对其进行自定义(请参阅arity ),但是大多数情况下,默认值就足够了。

Picocli鼓励您将enum类型用于带有有限有效值集的选项或位置参数。 picocli不仅会为您验证输入,还可以使用@Option(description = "Valid values: ${COMPLETION-CANDIDATES}")在使用帮助消息中显示所有值。 枚举还允许命令行补全功能为选项值建议补全候选值。

更少的代码

Picocli将选项参数String值转换为字段类型。 它不仅可以节省应用程序的工作量,而且还可以对用户输入进行最小程度的验证。 如果转换失败,则会抛出ParameterException并显示用户友好的错误消息。

让我们看一个例子,看看这有多有用。 Checkstyle Main类定义了-x--exclude-regexp exclude --exclude-regexp选项,该选项允许用于指定要排除的目录的多个正则表达式。

使用Commons CLI,您需要将在命令行上匹配的String值转换为应用程序java.util.regex.Pattern对象:

/*** Gets the list of exclusions from the parse results.* @param commandLine object representing the result of parsing the command line* @return List of exclusion patterns.*/
private static List<Pattern> getExclusions(CommandLine commandLine) {final List<Pattern> result = new ArrayList<>();if (commandLine.hasOption(OPTION_X_NAME)) {for (String value : commandLine.getOptionValues(OPTION_X_NAME)) {result.add(Pattern.compile(value));}}return result;
}

根据合同,在picocli中,您只需在List<Pattern> (或Pattern[]数组)字段上声明该选项。 由于picocli具有java.util.regex.Pattern的内置转换器,因此只需声明该选项即可。 转换代码完全消失了。 如果在命令行上指定了一个或多个-x选项,Picocli将实例化并填充列表。

/** Option that allows users to specify a regex of paths to exclude. */
@Option(names = {"-x", "--exclude-regexp"},description = "Regular expression of directory to exclude from CheckStyle")
private List<Pattern> excludeRegex;

选项名称

Commons CLI支持“短”和“长”选项,例如-t--tree 。 这并不总是您想要的。

Picocli允许选项具有任意数量的名称和前缀。 例如,这在picocli中会很好:

@Option(names = {"-cp", "-classpath", "--class-path"})

位置参数

在Commons CLI中,您无法预先定义位置参数。 相反,其CommandLine解析结果类具有方法getArgs ,该方法以字符串数组形式返回位置参数。 Checkstyle Main类使用它来创建要处理的File对象的列表。

在picocli中,位置参数是一等公民,例如命名选项。 不仅可以强类型化它们,而且位于不同位置的参数可以具有不同的类型,并且每个参数将在用法帮助消息中列出单独的条目和描述。

例如,Checkstyle Main类需要处理的文件列表,因此我们声明一个字段并使用@Parameters对其进行@Parametersarity = "1..*"属性意味着必须至少指定一个文件,否则picocli将显示有关缺少参数的错误消息。

@Parameters(paramLabel = "file", arity = "1..*", description = "The files to process")
private List<File> filesToProcess;

帮助选项

在Commons CLI中,用必需的选项创建一个具有--help选项的应用程序是非常困难的。 Commons CLI对帮助选项没有特殊处理,当用户指定<command> --help时,它将抱怨缺少必需的选项。

Picocli具有对常见(和自定义)帮助选项的内置支持。

解析命令行参数

Commons CLI具有一个CommandLineParser接口和一个parse方法,该方法返回一个代表解析结果的CommandLine 。 然后,应用程序调用CommandLine.hasOption(String)来查看是否设置了标志,或者调用CommandLine.hasOption(String) CommandLine.getOptionValue(String)来获取选项值。

Picocli在解析命令行参数时填充带注释的字段。 Picocli的parse…​方法也返回ParseResult可以上指定的选项并且什么的价值他们有,但大多数应用程序实际上并不需要使用查询ParseResult类,因为它们可以简单地检查该注入的注释值解析期间的字段。

处理结果

经营理念上白色隔离

解析器完成后,应用程序需要运行其业务逻辑,但是首先要检查一些事情:

  • 是否需要版本信息或使用帮助? 如果是这样,请打印出所需的信息并退出。
  • 用户输入是否无效? 打印出一条包含详细信息的错误消息,打印使用帮助消息并退出。
  • 最后运行业务逻辑–处理业务逻辑引发的错误。

使用Commons CLI,这看起来像这样:

int exitStatus;
try {CommandLine commandLine = new DefaultParser().parse(buildOptions(), args);if (commandLine.hasOption(OPTION_VERSION)) { // --versionSystem.out.println("Checkstyle version: " + version());exitStatus = 0;} else if (commandLine.hasOption(OPTION_HELP)) { // --helpprintUsage(System.out);exitStatus = 0;} else {exitStatus = runBusinessLogic(); // business logic}
} catch (ParseException pex) { // invalid inputexitStatus = EXIT_WITH_CLI_VIOLATION;System.err.println(pex.getMessage());printUsage(System.err);
} catch (CheckstyleException ex) { // business logic exceptionexitStatus = EXIT_WITH_CHECKSTYLE_EXCEPTION_CODE;ex.printStackTrace();
}
System.exit(exitStatus);

Picocli提供了一些方便的方法来解决以上大部分问题。 通过使您的命令实现RunnableCallable ,应用程序可以专注于业务逻辑。 最简单地说,它可能看起来像这样:

public class Main implements Callable<Integer> {public static void main(String[] args) {CommandLine.call(new Main(), args);}public Integer call() throws CheckstyleException {// business logic here}
}

Checkstyle Main类需要控制退出代码,并且对错误处理有一些严格的内部要求,因此我们最终不使用便捷方法,并且使解析结果处理与Commons CLI极为相似。 在picocli待办事项清单上可以改善这个领域。

使用帮助信息

Picocli在支持的平台上的使用帮助消息中使用ANSI颜色和样式。 这不仅看起来不错,而且还减轻了用户的认知负担:对比度使重要的信息(如命令,选项和参数)从周围的文本中脱颖而出。

应用程序还可以在使用帮助消息的描述或其他部分中使用带有简单标记的ANSI颜色和样式,例如@|bg(red) text with red background|@ 。 请参阅用户手册的相关部分。

对于CheckStyle,我们将其保持在最低限度,而CheckStyle的结果输出如下所示:

总结:最后的提示

请注意,即使使用帮助消息仅显示带有双连字符的选项,Commons CLI的默认解析器也会识别单连字符( - )和双连字符( -- )长选项。 您需要确定是否继续支持此操作。

在picocli中@Option(names = "-xxx", hidden = true)如果您想模仿与Commons CLI完全相同的行为,则可以使用@Option(names = "-xxx", hidden = true)声明带有单个连字符的长选项:用法中未显示picocli中的隐藏选项帮助信息。

结论

从Commons CLI迁移到picocli可以为最终用户提供更好的用户体验,并且可以为开发人员带来显着的好处,即提高其可维护性和未来扩展的潜力。 迁移是手动过程,但相对简单。

更新:CheckStyle项目接受了本文中所做更改的请求请求。 从CheckStyle 8.15开始,其命令行工具将使用picocli。 CheckStyle维护人员对结果感到满意:

Checkstyle从Apache CLI迁移到@picocli(将在8.15中发布),最后,CLI参数的文档现在已经以声明性的方式在代码中井井有条地组织起来,而Checkstyle的CLI遵循CLI最佳实践。

— CheckStyle维护者Roman Ivanov

翻译自: https://www.javacodegeeks.com/2018/11/migrating-commons-cli-picocli.html

commons-io

commons-io_从Commons CLI迁移到picocli相关推荐

  1. commons cli_从Commons CLI迁移到picocli

    commons cli 最初于2002年发布的Apache Commons CLI可能是使用最广泛的Java命令行解析器,但是它的API显示了它的年龄. 寻找具有最少样板代码的现代方法的应用可能对pi ...

  2. 从Commons CLI迁移到picocli

    最初于2002年发布的Apache Commons CLI可能是使用最广泛的Java命令行解析器,但是它的API显示了它的年龄. 寻找具有最少样板代码的现代方法的应用可能对picocli感兴趣. 为什 ...

  3. Apache Commons 系列简介 之 CLI

    原文链接:http://www.blogways.net/blog/2014/01/15/apache-commons-cli.html Apache Commons的主要目的就是,创建和维护一个可重 ...

  4. uniapp 从可视化项目 向 cli 迁移

    前言 为满足自动化部署对 uniapp 进行迁移 本地环境 node -v # 14.20.0 npm -v # 6.14.17 vue -V # vue-cli 5.0.8 一.安装并且搭建cli项 ...

  5. 编写更少量的代码:使用apache commons工具类库

    Commons-configuration Commons-FileUploadCommons DbUtilsCommons BeanUtils Commons CLI Commons CodecCo ...

  6. Jakarta Commons:巧用类和组件1

    From http://linux.ccidnet.com/art/322/20030805/57869_1.html Jakarta Commons是Jakarta的子项目,它创建和维护着许多独立软 ...

  7. 常用Apache Commons工具类备忘

    常用Apache Commons工具类 ----------------------------------------------------------------- 例如:commons.lan ...

  8. java apache commons_Apache commons(Java常用工具包)简介

    Apache Commons是一个非常有用的工具包,解决各种实际的通用问题,下面是一个简述表,详细信息访问http://jakarta.apache.org/commons/index.html Be ...

  9. 一篇关于apache commons类库的详解

    1.1. 开篇 在Java的世界,有很多(成千上万)开源的框架,有成功的,也有不那么成功的,有声名显赫的,也有默默无闻的.在我看来,成功而默默无闻的那些框架值得我们格外的尊敬和关注,Jakarta C ...

最新文章

  1. UIScollerViewUIPageControl的一些使用方法
  2. 互联网1分钟 |0103
  3. TypeError: Cannot read property ‘range‘ of null
  4. C++多线程快速入门(四)shared_mutex以及读写锁应用
  5. 如何查看linux 是否安装软件包,linux 查看软件包是否安装 linux查看软件包
  6. python给js变量赋值_python 之 前端开发( JavaScript变量、数据类型、内置对象、运算符、流程控制、函数)...
  7. 二叉链表的建立和遍历 完整的前,中,后和层序建立和遍历
  8. 全奖博士招生,美国中佛罗里达大学计算机视觉研究中心
  9. 【OpenCV】OpenCV函数精讲之 -- 多通道图像混合
  10. 移动网页广告引入mraid.js使用指南
  11. GitHub:我们为什么会弃用jQuery?
  12. TensorFlow windows之Tensorboard使用
  13. jQ1.5中的事件系统(低版本的事件系统)
  14. python的模拟登录原理_python---cookie模拟登陆和模拟session原理
  15. 2021-06-10 JUC01DAY
  16. C语言段错误-core文件
  17. 海康大华PC客户端集成播放器
  18. win10 VS2015社区版本 64位 TensorFlow 安装
  19. 爱奇艺网络流量分析引擎QNSM及其应用
  20. 彩虹php域名授权系统,彩虹云域名授权系统(正版源码+教程)

热门文章

  1. Html5 Canvas 学习之路(一)
  2. HDoj-1042 大数阶乘
  3. mysql表名忽略大小写
  4. [转载]项目风险管理七种武器-孔雀翎
  5. nginx收到空包问题
  6. 第 16 章 MySQL Cluster
  7. golang net/http 超时机制完全手册
  8. linux shell 命令执行超时终止
  9. python3 多进程 multiprocessing对僵尸进程的处理
  10. golang 获取当前执行程序路径