东东
发布于 2024-12-20 / 3 阅读 / 0 评论 / 0 点赞

Picocli命令行开发

Picocli 命令行开发

学习指路

https://blog.csdn.net/it_freshman/article/details/125458116

基础

什么是命令行程序,俗称CLI(command line interface)

就是通过命令行界面运行的程序,通过终端窗口接收用户的纯文本指令,执行相应的任务

结构

  • command 命令:就是具体要做的事情
  • option 选项:用于改变命令的行为
  • parameter 参数:传递给命令行程序的内容

使用

引入坐标

<!-- https://picocli.info -->
<dependency>
    <groupId>info.picocli</groupId>
    <artifactId>picocli</artifactId>
    <version>4.7.5</version>
</dependency>

官方示例

package com.yupi.cli.example;

import picocli.CommandLine;
import picocli.CommandLine.Command;
import picocli.CommandLine.Option;
import picocli.CommandLine.Parameters;

@Command(name = "ASCIIArt", version = "ASCIIArt 1.0", mixinStandardHelpOptions = true) 
public class ASCIIArt implements Runnable { 

    @Option(names = { "-s", "--font-size" }, description = "Font size") 
    int fontSize = 19;

    @Parameters(paramLabel = "<word>", defaultValue = "Hello, picocli", 
               description = "Words to be translated into ASCII art.")
    private String[] words = { "Hello,", "picocli" }; 

    @Override
    public void run() {
        // 自己实现业务逻辑
        System.out.println("fontSize = " + fontSize);
        System.out.println("words = " + String.join(",", words));
    }

    public static void main(String[] args) {
        int exitCode = new CommandLine(new ASCIIArt()).execute(args); 
        System.exit(exitCode); 
    }
}

这段代码中:

1、首先先实现了Runnable接口,这就是一个命令

2、通过使用注解来给命令进行命令,并指定是否开启帮助手册

比如我们打开终端,输入java -help一样,会给我们进行提示

3、下面option注解标注的变量,其实就是选项,代表这个命令有哪些行为可以使用

4、run方法是当用户在终端敲了回车之后,要执行的逻辑

5、main方法就是程序主入口

上面这个程序,我们在运行的时候就可以在idea的启动参数中加上配置

-s 12 good

这样,程序就是输出

fontSize = 12
words = good

功能

帮助手册

通过mixinStandardHelpOptions选项来标记是否开启帮助手册

@Command(name = "ASCIIArt", mixinStandardHelpOptions = true) 

命令解析

@Option(names = { "-s", "--font-size" }, description = "Font size") 
int fontSize = 19;

@Parameters(paramLabel = "<word>", defaultValue = "Hello, picocli", 
           description = "Words to be translated into ASCII art.")
private String[] words = { "Hello,", "picocli" }; 

上面这个就是命令的定义、参数的定义,包含参数的命名,默认值,描述等

交互式输入

package com.yupi.cli.example;

import picocli.CommandLine;
import picocli.CommandLine.Option;

import java.util.concurrent.Callable;

public class Login implements Callable<Integer> {
    @Option(names = {"-u", "--user"}, description = "User name")
    String user;

    @Option(names = {"-p", "--password"}, description = "Passphrase", interactive = true)
    String password;

    public Integer call() throws Exception {
        System.out.println("password = " + password);
        return 0;
    }

    public static void main(String[] args) {
        new CommandLine(new Login()).execute("-u", "user123", "-p");
    }
}

比如上面这个示例,执行的时候,带了用户的姓名,但是需要用户输入密码,这时候就需要等待用户输入密码后,再进行确认。

多选项交互式输入

public class Login implements Callable<Integer> {
    @Option(names = {"-u", "--user"}, description = "User name")
    String user;

    @Option(names = {"-p", "--password"}, description = "Passphrase", interactive = true)
    String password;

    @Option(names = {"-cp", "--checkPassword"}, description = "Check Password", interactive = true)
    String checkPassword;

    public Integer call() throws Exception {
        System.out.println("password = " + password);
        System.out.println("checkPassword = " + checkPassword);
        return 0;
    }

    public static void main(String[] args) {
        new CommandLine(new Login()).execute("-u", "user123", "-p", "-cp");
    }
}

上面这个示例,就是在用户输入密码后,再提示用户需要重复输入密码。然后全部输入完之后再执行call方法

子命令

就是对命令进行嵌套。

给出示例进行测试

package com.yupi.cli.example;

import picocli.CommandLine;
import picocli.CommandLine.Command;

@Command(name = "main", mixinStandardHelpOptions = true)
public class SubCommandExample implements Runnable {

    @Override
    public void run() {
        System.out.println("执行主命令");
    }

    @Command(name = "add", description = "增加", mixinStandardHelpOptions = true)
    static class AddCommand implements Runnable {
        public void run() {
            System.out.println("执行增加命令");
        }
    }

    @Command(name = "delete", description = "删除", mixinStandardHelpOptions = true)
    static class DeleteCommand implements Runnable {
        public void run() {
            System.out.println("执行删除命令");
        }
    }

    @Command(name = "query", description = "查询", mixinStandardHelpOptions = true)
    static class QueryCommand implements Runnable {
        public void run() {
            System.out.println("执行查询命令");
        }
    }

    public static void main(String[] args) {
        // 执行主命令
        String[] myArgs = new String[] { };
        // 查看主命令的帮助手册
//        String[] myArgs = new String[] { "--help" };
        // 执行增加命令
//        String[] myArgs = new String[] { "add" };
        // 执行增加命令的帮助手册
//        String[] myArgs = new String[] { "add", "--help" };
        // 执行不存在的命令,会报错
//        String[] myArgs = new String[] { "update" };
        int exitCode = new CommandLine(new SubCommandExample())
                .addSubcommand(new AddCommand())
                .addSubcommand(new DeleteCommand())
                .addSubcommand(new QueryCommand())
                .execute(myArgs);
        System.exit(exitCode);
    }
}