1

我得到了一些与 picocli 配合得很好的代码:

 @Command(name = "parse", sortOptions = false, description = "parse input files and write to database")
class CommandLineArgumentParser {


@Option(names = { "-h", "--help" }, usageHelp = true, description = "display this message")
private boolean helpRequested = false;


@Option(names = { "-s", "--startDate"}, description = "First day at which to parse data",
        converter = GermanDateConverter.class, paramLabel = "dd.MM.yyyy")
public LocalDate start;

@Option(names = { "-e", "--endDate"}, description = "Last day (inclusive) at which to stop parsing",
        converter = GermanDateConverter.class, paramLabel = "dd.MM.yyyy")
public LocalDate end;


private static class GermanDateConverter implements ITypeConverter<LocalDate> {
    @Override
    public LocalDate convert(String value) throws Exception {
        LocalDate result = null;

            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd.MM.yyyy");
            result = LocalDate.parse(value, formatter);
            if (result.getYear() < 1900) {
                throw new IllegalArgumentException("year should be after 1900");
            }
        return result;
    }
}


@SpringBootApplication
public class Application implements CommandLineRunner {

public void run(String... args) throws Exception {
    CommandLineArgumentParser commandlineparser = new CommandLineArgumentParser();

    CommandLine commandLine = new CommandLine(commandlineparser);
    try {
        commandLine.parseArgs(args);

    } catch (MissingParameterException e) {
        System.out.println(e);
        System.out.println();
        CommandLine.usage(CommandLineArgumentParser.class, System.out);
        System.exit(1);
    } catch (ParameterException e) {
        System.out.println(e);
        System.out.println();
        CommandLine.usage(CommandLineArgumentParser.class, System.out);
        System.exit(1);
    }

    if (commandLine.isUsageHelpRequested()) {
        commandLine.usage(System.out);
        return;
    } else if (commandLine.isVersionHelpRequested()) {
        commandLine.printVersionHelp(System.out);
        return;
    }

    if (commandlineparser.start == null) {
        log.warn("no start date specified, using: 01.01.2005");
        commandlineparser.start = LocalDate.of(2005, 01, 01);
    }

    if (commandlineparser.end == null) {
        LocalDate timePoint = LocalDate.now();
        log.warn("no end date specified, using today: " + timePoint.toString());
        commandlineparser.end = timePoint;
    }
}

但我没有找到一个显示使用的多个命令的简单示例,例如这个:
https ://github.com/remkop/picocli/blob/master/src/test/java/picocli/Demo.java

不编译:

int exitCode = new CommandLine(new Demo()).execute(args);

The method execute(CommandLine, List<Object>) in the type CommandLine is not applicable for the    arguments (String[])

有人可以发布一个关于如何使用多个命令的示例吗?

4

1 回答 1

1

我怀疑您使用的是旧版本的库。该execute(String []) : int方法在 picocli 4.0 中引入。

升级和使用execute方法而不是parseArgs方法将允许您从应用程序中删除大量样板代码:使用方法自动处理使用/版本帮助请求和处理无效输入execute

您的命令应该实现 Runnable 或 Callable,这是每个命令的业务逻辑所在。

修改您的示例并给它一个子命令

@Command(name = "parse", sortOptions = false,
        mixinStandardHelpOptions = true, version = “1.0”,
        description = "parse input files and write to database",
        subcommands = MySubcommand.class)
class CommandLineArgumentParser implements Callable<Integer> {

    @Option(names = { "-s", "--startDate"}, description = "First day at which to parse data",
            converter = GermanDateConverter.class, paramLabel = "dd.MM.yyyy")
    public LocalDate start;

    @Option(names = { "-e", "--endDate"}, description = "Last day (inclusive) at which to stop parsing",
            converter = GermanDateConverter.class, paramLabel = "dd.MM.yyyy")
    public LocalDate end;


    private static class GermanDateConverter implements ITypeConverter<LocalDate> {
        @Override
        public LocalDate convert(String value) throws Exception {
            LocalDate result = null;

                DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd.MM.yyyy");
                result = LocalDate.parse(value, formatter);
                if (result.getYear() < 1900) {
                    throw new IllegalArgumentException("year should be after 1900");
                }
            return result;
        }
    }

    @Override
    public Integer call() {
        if (start == null) {
            log.warn("no start date specified, using: 01.01.2005");
            start = LocalDate.of(2005, 01, 01);
        }

        if (end == null) {
            LocalDate timePoint = LocalDate.now();
            log.warn("no end date specified, using today: " + timePoint.toString());
            end = timePoint;
        }

        // more business logic here ...

        // add finally return an exit code 
        int exitCode = ok ? 0 : 1;
        return exitCode;
    }
}

@Command(name = "foo")
class MySubcommand implements Callable<Integer> {
    @Override
    public Integer call() {
        System.out.println("hi");
        return 0;
    }
}


@SpringBootApplication
public class Application implements CommandLineRunner {

    public void run(String... args) throws Exception {
        int exitCode = new CommandLine(
                CommandLineArgumentParser.class,
                new picocli.spring.PicocliSpringFactory())
                .execute(args);
        System.exit(exitCode);
     }
}

请注意,将 Spring 与 picocli 子命令结合使用时,您需要CommandLine使用picocli.spring.PicocliSpringFactory.

有关更完整的 Spring 示例,请参阅picocli-spring-boot-starter自述文件。

于 2019-09-27T23:45:12.013 回答