如何使用 picocli 处理多类型选项

问题描述

我正在将现有应用程序转换为使用 picocli。现有选项之一如下所示:

-t,--threads           [1,n] for fixed thread pool,'cpus' for number of cpus,'cached' for cached

这允许选项是一个正整数或几个特殊字符串之一。现有代码将其视为字符串,如果它不是特殊字符串之一,则将其传递给 Integer.parseInt

当然,我可以用 picocli 做同样的事情,但我想知道是否有更好的方法来处理这个问题。例如,允许将多个字段用于同一选项的东西,根据传递的内容填写适当的字段?这也可能允许我对可能的字符串选项使用枚举。

解决方法

一个想法是为此创建一个类,例如 ThreadPoolSize,它封装了固定数值或动态值的枚举。您需要为此数据类型创建自定义转换器。

那么你可以如下定义选项:

@Option(names = { "-t","--threads" },converter = ThreadPoolSizeConverter.class,description = "[1,n] for fixed thread pool,'cpus' for number of cpus,'cached' for cached")
ThreadPoolSize threadPoolSize;

线程池大小和转换器的自定义数据类型可能如下所示:

class ThreadPoolSize {
    enum Dynamic { cpus,cached }

    int fixed = -1;  // if -1,then use the dynamic value
    Dynamic dynamic; // if null,then use the fixed value
}

class ThreadPoolSizeConverter implements CommandLine.ITypeConverter<ThreadPoolSize> {

    @Override
    public ThreadPoolSize convert(String value) throws Exception {
        ThreadPoolSize result = new ThreadPoolSize();
        try {
            result.fixed = Integer.parseInt(value);
            if (result.fixed < 1) {
                throw new CommandLine.TypeConversionException("Invalid value " +
                        value + ": must be 1 or more.");
            }
        } catch (NumberFormatException nan) {
            try {
                result.dynamic = ThreadPoolSize.Dynamic.valueOf(
                        value.toLowerCase(Locale.ENGLISH));
            } catch (IllegalArgumentException ex) {
                throw new CommandLine.TypeConversionException("Invalid value " +
                        value + ": must be one of " + 
                        Arrays.toString(ThreadPoolSize.Dynamic.values()));
            }
        }
        return result;
    }
}

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...