ApacheCommons——commons-cli(命令行参数解析)

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 (泛型) 免去手动转型。可直接提取为 NumberURLFilePath 或自定义 Type 对象。
getOptions() 获取命令行中所有被匹配成功的 Option 结构化对象数组。 Option[] 动态遍历当前生效的所有命令行选项,用于日志审计或全局参数映射。
getArgs() 获取所有未被识别为 Option 的剩余位置参数(Positional Arguments) String[] 提取不带连字符标记的纯文件名或操作指令(例如 tar -xvf archive.tar file1 file2 中的 file1file2)。
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());
        }
    }
}
相关推荐
小小猪的春天1 小时前
Java 手写第一个 MCP Server:Spring AI MCP 半小时跑通
java·人工智能·spring boot·ai编程
find1star1 小时前
LeetCode 141:环形链表
java·算法·leetcode·链表
今天AI了吗2 小时前
DeepSeek Harness 深度解析:从评测架构到实战落地
java·网络·数据库·人工智能·架构·java-ee
benchmark_cc2 小时前
REST API 和 Python SDK 应该怎么选?量化交易数据接口选型实战
开发语言·python·数据分析·pandas·量化交易·股票数据·quantdash
王的宝库2 小时前
Go 项目结构:从单文件到标准工程布局
开发语言·后端·golang
Tairitsu_H2 小时前
[C++] 深入理解红黑树:封装set与map
开发语言·c++·set·map·红黑树·模拟实现
许彰午2 小时前
27-AuthService登录链路
java·低代码·架构
泡海椒2 小时前
JQuick-Curl 性能分析:并发场景下的性能表现与调优,第三方接口调用不只要快写也要稳跑
java·开发语言·okhttp
小智老师PMP2 小时前
2026深度解析|PMP第八版与NPDP核心侧重点本质区别(管理类证书怎么选)
开发语言·分布式·算法·职场和发展·产品经理