commons-cli(命令行参数解析)
1、概述
commons-cli(Apache Commons CLI)是 Java 用于解析命令行参数(Command-Line Arguments)的标准工具包。它能自动解析传给 main(String\[\] args) 的参数,支持短选项(如 -h)、长选项(如 --help)、参数取值、必需项校验,并能自动生成排版整齐的帮助(Usage)信息。
| 分类 | 模块常用类 (Class) | 核心功能与解决问题 | 核心 API / 典型使用场景 |
|---|---|---|---|
| 参数模型 (Model) | Option Options OptionGroup |
定义命令行参数规则与约束 • Option: 描述单个参数(长/短名称、是否带值、描述信息等) • Options: 存放所有可用参数的容器 • OptionGroup: 定义组内参数互斥(例如 --verbose 与 --quiet 不能同时存在) |
• Option.builder("c").longOpt("config").hasArg().build() • options.addOptionGroup(group) |
| 解析器 (Parser) | CommandLineParser DefaultParser |
将输入的 String[] args 转换为结构化的解析结果 根据定义好的 Options 规则逐项校验输入参数,处理单字母叠加(如 -xvf)、带值参数等 |
• CommandLineParser parser = new DefaultParser(); • CommandLine cmd = parser.parse(options, args); |
| 解析结果 (Result) | CommandLine |
提供类型安全的参数提取与查询接口 用于获取运行时传递的具体参数值,判断某标记是否存在,或提取未被定义的剩余参数(Extra Args) | • cmd.hasOption("config") • cmd.getOptionValue("config", "default.conf") |
| 帮助生成器 (Help) | HelpFormatter |
自动生成规范的终端帮助文档 在参数解析失败或用户输入 -h/--help 时,自动排版打印命令行用法(Usage)及参数说明手册 |
• HelpFormatter formatter = new HelpFormatter(); • formatter.printHelp("appName", options); |
xml
<dependency>
<groupId>commons-cli</groupId>
<artifactId>commons-cli</artifactId>
<version>1.8.0</version>
</dependency>
2、参数模型
commons-cli(Apache Commons CLI)是 Apache 专门用于解析命令行参数(Command Line Arguments)的轻量级 Java 工具包。
它的核心设计思想是将参数定义(Model)、参数解析(Parser)和结果查询(CommandLine)解耦。其中,参数模型是整个库的基础。
| 核心类 | 架构职责 | 典型场景 | 核心配置方法 / 最佳实践 |
|---|---|---|---|
Option |
代表单个命令行参数 定义单个参数的属性(如 -h 或 --port 8080),包含短名、长名、参数值要求及描述信息。 |
声明具体的命令行选项(如 -c / --config 指定配置文件路径,-v 开启详细日志)。 |
• Option.builder("p").longOpt("port").hasArg().argName("PORT").desc("Server port").build() • 使用 required(true) 标记必填参数。 |
Options |
代表参数集合,是配置入口 作为容器注册并管理应用程序支持的所有可选(Optional)、必选(Required)及互斥 Option 对象。 | 建立全局命令行规则容器,传递给 CommandLineParser 进行解析或给 HelpFormatter 打印帮助手册。 |
• options.addOption(Option...) • options.addOptionGroup(OptionGroup) |
OptionGroup |
代表互斥参数组 定义一组逻辑上互斥的参数,强制解析时只能出现其中最多一个参数。 | 冲突选项控制(例如 -v/--verbose 输出详细日志与 -q/--quiet 静默模式不能同时使用)。 |
• group.setRequired(true)(若需组内必须 N 选 1) • group.addOption(optionA).addOption(optionB) |
2.1、Option(单个参数配置)
Option 是最基础的组件。在现代版本中,推荐使用 Option.builder() 建造者模式进行创建。
2.1.1、核心API
Option.builder(String opt):指定短参数名(如 "p" 对应 -p)。若无短参数,可传 null。longOpt(String longOpt):指定长参数名(如 "port" 对应 --port)。hasArg(boolean hasArg) / hasArg():指定该选项后是否跟有参数值。numberOfArgs(int count):指定该选项后面跟随的参数值个数(例如 -file file1 file2)。required(boolean required):标识该选项是否为必填项。argName(String name):设置帮助信息中参数值的显示名称(如 -p <port> 中的 <port>)。desc(String description):设置选项的描述信息,用于生成 Help 帮助手册。type(Class<?> type):指定参数值类型(如 Integer.class、File.class)。
2.1.2、使用示例
java
import org.apache.commons.cli.Option;
public class OptionDemo {
public static void main(String[] args) {
// 1. 无参选项(如帮助选项 -h / --help)
Option helpOpt = Option.builder("h")
.longOpt("help")
.desc("显示帮助信息")
.build();
// 2. 带参数值的选项(如 -p 8080 / --port 8080)
Option portOpt = Option.builder("p")
.longOpt("port")
.hasArg()
.argName("port_num")
.type(Integer.class)
.required(true) // 必填参数
.desc("指定服务启动端口")
.build();
// 3. 多参数值选项(如 -f file1.txt file2.txt)
Option filesOpt = Option.builder("f")
.longOpt("files")
.numberOfArgs(2)
.argName("file1 file2")
.desc("指定输入的两个文件路径")
.build();
}
}
2.2、Options(参数模型容器)
Options 容器用于整合项目中所有的 Option。它提供了快速添加简易选项以及注册复杂 Option / OptionGroup 的入口。
2.2.1、核心API
addOption(String opt, String description):快速添加无值开关选项。addOption(String opt, String longOpt, boolean hasArg, String description):快速添加常见配置选项。addOption(Option opt):注册由 Option.builder() 构建的完整选项。addOptionGroup(OptionGroup group):注册一个互斥参数组。hasOption(String opt):检查容器中是否存在某个选项配置。getRequiredOptions():获取当前模型中所有的必填参数集合。
2.2.2、使用示例
java
import org.apache.commons.cli.Option;
import org.apache.commons.cli.Options;
public class OptionsDemo {
public static Options createCommandLineOptions() {
Options options = new Options();
// 方式 A:快捷添加简单选项
options.addOption("v", "version", false, "显示当前软件版本");
options.addOption("c", "config", true, "指定配置文件路径");
// 方式 B:添加建造者构建的复杂 Option
Option timeoutOpt = Option.builder("t")
.longOpt("timeout")
.hasArg()
.argName("seconds")
.desc("指定超时时间(单位:秒)")
.build();
options.addOption(timeoutOpt);
return options;
}
}
2.3、OptionGroup(互斥参数组)
在实际业务场景中,某些参数是互斥的(例如只能选择以"调试模式 -d"或"静默模式 -q"运行,两者不可同时传)。OptionGroup 专门用来实现这种逻辑。
2.3.1、核心API
addOption(Option option):向互斥组中添加一个选项。setRequired(boolean required):指定该互斥组是否必须 N 选 1(若设为 true 且用户未传组内任何参数,解析时会抛出 MissingOptionException)。
2.3.2、使用示例
java
import org.apache.commons.cli.Option;
import org.apache.commons.cli.OptionGroup;
import org.apache.commons.cli.Options;
public class OptionGroupDemo {
public static Options createGroupOptions() {
Options options = new Options();
// 创建互斥组:详细日志 (-v) 与 静默模式 (-q) 互斥
OptionGroup verbosityGroup = new OptionGroup();
Option verboseOpt = Option.builder("v")
.longOpt("verbose")
.desc("输出详细日志信息")
.build();
Option quietOpt = Option.builder("q")
.longOpt("quiet")
.desc("静默模式,只输出错误信息")
.build();
verbosityGroup.addOption(verboseOpt);
verbosityGroup.addOption(quietOpt);
// 设置为强制 N 选 1
verbosityGroup.setRequired(true);
// 将互斥组添加到 Options 容器
options.addOptionGroup(verbosityGroup);
return options;
}
}
2.4、完整端到端解析示例
以下将参数模型(Options)、参数解析(CommandLineParser)、结果查询(CommandLine)与帮助菜单自动生成(HelpFormatter)整合展示:
java
import org.apache.commons.cli.*;
public class FullCliApplication {
public static void main(String[] args) {
// 模拟传入的命令行参数
String[] mockArgs = {"-h"};
// 1. 定义参数模型 (Model)
Options options = new Options();
options.addOption(Option.builder("h").longOpt("help").desc("打印帮助文档").build());
Option hostOpt = Option.builder("H")
.longOpt("host")
.hasArg()
.argName("ip/domain")
.desc("服务器连接地址")
.build();
Option portOpt = Option.builder("p")
.longOpt("port")
.hasArg()
.argName("port")
.type(Number.class)
.desc("服务器连接端口")
.build();
options.addOption(hostOpt);
options.addOption(portOpt);
// 2. 解析参数 (Parser)
CommandLineParser parser = new DefaultParser();
HelpFormatter formatter = new HelpFormatter();
try {
CommandLine cmd = parser.parse(options, mockArgs);
// 3. 业务逻辑判断与取值 (CommandLine)
if (cmd.hasOption("h")) {
// 打印排版格式良好的帮助菜单
formatter.printHelp("java -jar app.jar [options]", "==== App 命令行工具说明 ====", options, "=========================");
return;
}
String host = cmd.getOptionValue("host", "127.0.0.1"); // 提供默认值
String port = cmd.getOptionValue("port", "8080");
System.out.println("正在连接到 " + host + ":" + port);
} catch (ParseException e) {
System.err.println("命令行参数解析失败: " + e.getMessage());
formatter.printHelp("java -jar app.jar", options);
}
}
}
3、解析器
commons-cli(Apache Commons CLI)在执行命令行参数解析时,主要围绕 CommandLineParser 接口及其实现类 以及存储解析结果的 CommandLine 类 展开。
commons-cli 的解析流非常清晰:将定义好的 Options 模型和原始输入参数数组 String\[\] args 传入 CommandLineParser,最终生成 CommandLine 对象供业务取值。
| 类 / 接口 | 角色与职责 | 最佳实践 / 状态 |
|---|---|---|
CommandLineParser (接口) |
参数解析器的顶层接口 定义了核心 .parse(Options options, String[] arguments) 方法规范,为不同解析算法提供统一契约。 |
面向接口编程的类型声明;通常使用 DefaultParser 构造实例。 |
DefaultParser |
最推荐的通用解析器实现 无缝融合了 POSIX(-xvf)、GNU(--long-option=value)及 Java 风格属性(-Dkey=value)的解析逻辑。 |
1.3+ 版本推荐首选 。线程不安全,建议单次解析时局部实例化;优先使用带 Properties 参数的 parse 方法实现环境变量与命令行默认值融合。 |
CommandLine |
解析结果容器 存储解析后的状态,提供判断参数是否存在、获取参数值、类型转换以及提取剩余未识别参数(getArgs())的 API。 |
推荐通过 getOptionValue("p", "8080") 提供保底默认值;配合 getParsedOptionValue(...) 直接获取转换后的类型对象。 |
GnuParser / PosixParser |
历史遗留解析器 早期版本中针对不同参数风格(GNU 风格 vs POSIX 风格)的分开实现。 | 已被废弃(Deprecated) 。禁止在新项目中使用,老旧代码建议统一重构迁移至 DefaultParser。 |
3.1、核心API
DefaultParser 是 Apache Commons CLI 中功能最全面、最现代的解析器。它能够智能识别短选项(-h)、长选项(--help)、复合短选项(-vq 相当于 -v -q)、带 = 的参数(--port=8080)以及选项后的独立参数(Stop-At-Non-Option)。
DefaultParser():默认构造器。DefaultParser.builder() (1.5+):建造者模式,可配置更高级的解析行为(如忽略未知参数、允许不匹配的参数等)。parse(Options options, String[] arguments):核心解析方法,解析失败会抛出 ParseException 及其子类。parse(Options options, String[] arguments, boolean stopAtNonOption):当 stopAtNonOption 为 true 时,一旦遇到第一个无法被识别为选项的参数(如文件名),解析器将立刻停止后续选项解析,将其余参数原样留作普通参数。
3.2、使用示例
java
import org.apache.commons.cli.*;
public class DefaultParserDemo {
public static void main(String[] args) {
// 1. 构建参数模型
Options options = new Options();
options.addOption("v", "verbose", false, "输出详细日志");
options.addOption("f", "file", true, "指定文件");
// 模拟复杂命令输入: 包含复合选项 -v、带等号的参数 --file=app.log
String[] mockArgs = {"-v", "--file=app.log", "extraParam1", "extraParam2"};
// 2. 创建 DefaultParser 执行解析
CommandLineParser parser = new DefaultParser();
try {
CommandLine cmd = parser.parse(options, mockArgs);
// 3. 校验与获取解析结果
if (cmd.hasOption("v")) {
System.out.println("已开启详细日志 (verbose)");
}
System.out.println("指定的文件名: " + cmd.getOptionValue("f"));
// 获取未被识别为 Option 的额外参数列表 (如 input 文件列表或子命令)
String[] remainingArgs = cmd.getArgs();
System.out.println("剩余非选项参数: " + String.join(", ", remainingArgs));
} catch (ParseException e) {
System.err.println("参数解析失败: " + e.getMessage());
}
}
}
java
已开启详细日志 (verbose)
指定的文件名: app.log
剩余非选项参数: extraParam1, extraParam2
4、解析结果
在 commons-cli 中,解析结果的核心载体是 CommandLine 类。当你使用解析器(如 DefaultParser)对命令行参数执行 .parse(...) 后,返回的就是 CommandLine 对象。它封装了所有被成功识别的选项、参数值以及未被识别的附加参数。
此外,在处理复杂解析结果时,还会配合使用 Option(用于反向查询已匹配选项的元数据)以及 ParseException 及其子类(用于处理解析异常结果)。
4.1、核心API
CommandLine 提供了丰富的 API 用于检索用户传入的参数。
| API 方法 | 作用说明 | 返回值类型 | 典型应用场景与最佳实践 |
|---|---|---|---|
hasOption(String opt) |
检查命令行中是否存在某个选项(支持短名如 "p" 或长名如 "port")。 |
boolean |
校验开关标记(布尔型 Flag,如 -v / --verbose 或 -h / --help)。 |
getOptionValue(String opt) |
获取选项对应的参数值。若用户未指定该选项,则返回 null。 |
String |
提取可选字符串参数(如获取 -c 指定的配置文件路径)。 |
getOptionValue(String opt, String defaultValue) |
获取选项参数值。若用户未指定该选项,则返回设定的默认值。 | String |
为配置提供保底逻辑(如 --port 缺省时自动使用 "8080")。 |
getOptionValues(String opt) |
获取选项后跟随的多个参数值 (如包含多次 -f file1 -f file2 或使用分隔符)。 |
String[] |
批量处理多文件输入、多日志级别设定或列表参数传入。 |
getParsedOptionValue(String opt) |
自动类型转换提取 。 根据定义 Option 时设定的类型(或传入 Class/Converter),将字符串参数直接转换为对应的 Java 对象。 |
T (泛型) |
免去手动转型。可直接提取为 Number、URL、File、Path 或自定义 Type 对象。 |
getOptions() |
获取命令行中所有被匹配成功的 Option 结构化对象数组。 |
Option[] |
动态遍历当前生效的所有命令行选项,用于日志审计或全局参数映射。 |
getArgs() |
获取所有未被识别为 Option 的剩余位置参数(Positional Arguments)。 | String[] |
提取不带连字符标记的纯文件名或操作指令(例如 tar -xvf archive.tar file1 file2 中的 file1 与 file2)。 |
getArgList() |
功能同 getArgs(),但将剩余位置参数包装为 List 集合。 |
List<String> |
方便使用 Stream API 或 List 方法直接处理剩余位置参数。 |
4.2、使用示例
1. 基础判断与值获取(含默认值)
java
import org.apache.commons.cli.*;
public class CommandLineValueDemo {
public static void main(String[] args) throws ParseException {
Options options = new Options();
options.addOption("h", "host", true, "服务器地址");
options.addOption("p", "port", true, "端口号");
options.addOption("v", "verbose", false, "是否开启日志");
// 模拟用户只传了 -h 和 -v
String[] mockArgs = {"-h", "192.168.1.1", "-v"};
CommandLineParser parser = new DefaultParser();
CommandLine cmd = parser.parse(options, mockArgs);
// 1. 布尔开关检查
if (cmd.hasOption("v")) {
System.out.println("日志模式:已开启");
}
// 2. 获取显式传入的值
String host = cmd.getOptionValue("host");
System.out.println("Host: " + host); // 输出: 192.168.1.1
// 3. 获取带有默认值的值(用户未传 -p,因此返回默认值 8080)
String port = cmd.getOptionValue("port", "8080");
System.out.println("Port: " + port); // 输出: 8080
}
}
java
日志模式:已开启
Host: 192.168.1.1
Port: 8080
2. 一参多值与剩余非选项参数处理
在很多 CLI 工具中(如 tar -czf archive.tar.gz file1.txt file2.txt),不仅有带多个值的选项,还有结尾的自由文件列表。
java
import org.apache.commons.cli.*;
import java.util.Arrays;
public class MultiValueAndArgsDemo {
public static void main(String[] args) throws ParseException {
Options options = new Options();
// 定义一个可接收多个值的选项 -i/--include
options.addOption(Option.builder("i")
.longOpt("include")
.hasArgs() // 允许多个参数值
.desc("包含的模块")
.build());
// 用户输入包含多值选项以及末尾的独立参数
String[] mockArgs = {"-i", "modA", "modB", "modC", "extra_arg1", "extra_arg2"};
CommandLineParser parser = new DefaultParser();
CommandLine cmd = parser.parse(options, mockArgs);
// 1. 获取一个选项对应的多个值
if (cmd.hasOption("i")) {
String[] modules = cmd.getOptionValues("i");
System.out.println("包含的模块: " + Arrays.toString(modules));
// 输出: [modA, modB, modC]
}
// 2. 获取未被解析为选项的剩余参数 (Non-option arguments)
String[] remainingArgs = cmd.getArgs();
System.out.println("剩余自由参数: " + Arrays.toString(remainingArgs));
// 输出: [extra_arg1, extra_arg2]
}
}
java
包含的模块: [modA, modB, modC, extra_arg1, extra_arg2]
剩余自由参数: []
3. 自动类型转换 (getParsedOptionValue)
commons-cli 可以自动将参数字符串转为 Number、File、URL 或自定义类型,免去手动强转的麻烦。
java
import org.apache.commons.cli.*;
import java.io.File;
public class TypeConversionDemo {
public static void main(String[] args) throws ParseException {
Options options = new Options();
// 注册带类型的 Option
options.addOption(Option.builder("c")
.longOpt("config")
.hasArg()
.type(File.class) // 指定为 File 类型
.build());
options.addOption(Option.builder("n")
.longOpt("count")
.hasArg()
.type(Number.class) // 指定为 Number 类型
.build());
String[] mockArgs = {"-c", "app.conf", "-n", "100"};
CommandLineParser parser = new DefaultParser();
CommandLine cmd = parser.parse(options, mockArgs);
// 使用 getParsedOptionValue 直接获取转换后的类型
File configFile = cmd.getParsedOptionValue("config");
Number count = cmd.getParsedOptionValue("n");
System.out.println("配置文件路径: " + configFile.getAbsolutePath());
System.out.println("数值 (加上10): " + (count.intValue() + 10)); // 110
}
}
java
配置文件路径: /Users/acton_zhang/J2EE/MavenWorkSpace/apachecommonspro/app.conf
数值 (加上10): 110
5、帮助生成器
在 commons-cli 中,帮助生成器负责将定义好的参数模型(Options)自动格式化并输出为标准的命令行帮助信息(如 --help 的输出菜单)。
核心类是 HelpFormatter,它提供了控制排版、列宽、排序方式以及页眉页脚控制的丰富 API。
5.1、核心API
HelpFormatter 提供了丰富的控制属性与控制方法:
1. 常用属性控制 API
setWidth(int width):设置控制台输出的最大行宽(默认 74 字符)。setPadding(int padding):设置参数名称与参数描述之间的间距(默认 1 个空格)。setLeftPadding(int leftPadding):设置左侧缩进空格数(默认 1 个空格)。setSyntaxPrefix(String prefix):设置用法说明的前缀文本(默认 "usage: ")。setOptionComparator(Comparator<Option> comparator):自定义选项的排序规则。若设为 null,则按照代码中添加的顺序输出。
2. 核心打印 API
printHelp(String cmdLineSyntax, Options options):最简打印方法,传入命令语法示例和 Options 对象。printHelp(String cmdLineSyntax, String header, Options options, String footer):带有页眉(Header)和页脚(Footer)的打印。printHelp(String cmdLineSyntax, String header, Options options, String footer, boolean autoUsage):指定是否自动在首行生成参数用法提示(autoUsage 默认为 true)。printHelp(PrintWriter pw, int width, String cmdLineSyntax, String header, Options options, int leftPadding, int descPadding, String footer):高度可定制的重载方法,可直接输出到指定流或日志文件。
5.2、使用示例
1. 基础用法示例
最常见的用法是在捕获 ParseException 异常或用户主动输入 -h/--help 时调用。
java
import org.apache.commons.cli.*;
public class BasicHelpDemo {
public static void main(String[] args) {
Options options = new Options();
options.addOption("h", "help", false, "显示帮助信息");
options.addOption(Option.builder("c")
.longOpt("config")
.hasArg()
.argName("file")
.desc("指定配置文件路径")
.build());
// 创建 HelpFormatter 实例
HelpFormatter formatter = new HelpFormatter();
// 基础打印:传入命令调用语法和 Options 容器
formatter.printHelp("java -jar myapp.jar", options);
}
}
java
usage: java -jar myapp.jar
-c,--config <file> 指定配置文件路径
-h,--help 显示帮助信息
2. 高级排版与页眉页脚(Header / Footer)
通过配置 Header 和 Footer,可以为 CLI 工具添加版权、说明文本以及联系方式。
java
import org.apache.commons.cli.*;
public class AdvancedHelpDemo {
public static void main(String[] args) {
Options options = new Options();
options.addOption("v", "verbose", false, "开启详细日志打印");
options.addOption(Option.builder("p")
.longOpt("port")
.hasArg()
.argName("port_num")
.desc("服务绑定端口号")
.build());
HelpFormatter formatter = new HelpFormatter();
// 样式微调
formatter.setWidth(100); // 设置每行最大宽度为 100 字符
formatter.setLeftPadding(3); // 左侧缩进 3 个空格
formatter.setPadding(5); // 参数与描述间距 5 个空格
String cmdSyntax = "my-service [OPTIONS]";
String header = "\n=== My-Service 命令行工具 v1.0 ===\n启动并配置后台服务节点。\n";
String footer = "\n如需进一步协助,请联系 support@example.com";
// 打印带 Header 和 Footer 的帮助信息
formatter.printHelp(cmdSyntax, header, options, footer, true);
}
}
3. 自定义参数排序方式
默认情况下,HelpFormatter 会按字母表升序(A-Z)排序列出各个 Option。如果希望按照添加顺序输出,或者自定义规则,可使用 setOptionComparator。
java
import org.apache.commons.cli.*;
public class CustomSortHelpDemo {
public static void main(String[] args) {
Options options = new Options();
options.addOption("z", "zero", false, "末尾字母选项");
options.addOption("a", "apple", false, "首字母选项");
HelpFormatter formatter = new HelpFormatter();
// 1. 取消默认的字母排序,保持 Options 代码注入的原始顺序
formatter.setOptionComparator(null);
System.out.println("--- 保持代码添加顺序 ---");
formatter.printHelp("app", options);
// 2. 自定义排序逻辑 (如按 Option 描述字符串长度排序)
formatter.setOptionComparator((opt1, opt2) ->
Integer.compare(opt1.getDescription().length(), opt2.getDescription().length())
);
System.out.println("\n--- 按描述文本长度排序 ---");
formatter.printHelp("app", options);
}
}
java
--- 保持代码添加顺序 ---
usage: app
-z,--zero 末尾字母选项
-a,--apple 首字母选项
--- 按描述文本长度排序 ---
usage: app
-a,--apple 首字母选项
-z,--zero 末尾字母选项
6、异常处理体系
解析参数时如果缺少必填参数、参数格式不对,CommandLineParser 会抛出 ParseException 的具体子类。捕获这些异常有助于打印精准的提示信息。
6.1、常见异常类
| 常见异常类 | 触发原因 | 诊断与恢复策略 (Best Practices) |
|---|---|---|
MissingOptionException |
缺失必选参数 命令行中未传入标有 required(true) 的必需参数,或未提供 setRequired(true) 互斥组中的任意参数。 |
捕获后提示缺少关键配置,调用 HelpFormatter.printHelp() 打印用法说明,并以状态码 1 退出程序。 |
MissingArgumentException |
参数缺失附加值 某个选项定义了 hasArg()(需要接收值),但用户传入该选项时未在其后跟具体的参数值(如传入 -p 但未指定端口)。 |
提示指定参数缺少对应的值(如 Option -p requires an argument),引导用户补充参数值。 |
UnrecognizedOptionException |
未定义非法参数 用户传入了未在 Options 容器中注册的非法选项(如拼写错误或输入了不支持的 -xyz)。 |
检查拼写是否正确,避免盲目忽略;也可配合 DefaultParser(true) (StopAtNonOption) 将未识别参数交由后续流程处理。 |
AlreadySelectedException |
互斥参数冲突 在定义了 OptionGroup 的互斥参数组中,用户同时传入了两个或更多相互排斥的参数(如同时指定 -v 与 -q)。 |
明确提示参数冲突信息,说明某些选项不能同时使用,要求用户修改命令行输入。 |
6.2、使用示例
java
import org.apache.commons.cli.*;
public class ExceptionHandlingDemo {
public static void main(String[] args) {
Options options = new Options();
options.addOption(Option.builder("f").longOpt("file").hasArg().required(true).build());
String[] invalidArgs = {"-f"}; // 缺失 file 的参数值,且缺少其他必填项
CommandLineParser parser = new DefaultParser();
try {
parser.parse(options, invalidArgs);
} catch (MissingArgumentException e) {
System.err.println("错误:选项 '" + e.getOption().getOpt() + "' 缺失必需的参数值!");
} catch (MissingOptionException e) {
System.err.println("错误:缺少必选命令行选项: " + e.getMissingOptions());
} catch (UnrecognizedOptionException e) {
System.err.println("错误:无法识别的选项: " + e.getOption());
} catch (ParseException e) {
System.err.println("命令行解析错误: " + e.getMessage());
}
}
}