使用 Picocli 创建 Java 命令行程序
使用 Picocli 创建 Java 命令行程序
Hello World 程序(快速入门)
创建maven项目,使用依赖
<dependency>
<groupId>info.picocli</groupId>
<artifactId>picocli</artifactId>
<version>4.7.0</version>
</dependency>
在命令类名上添加 @Command
注释,可以通过name
、description
指明相关属性。
@CommandLine.Command(name = "hello", description = "say hello")
public class HelloWorldCommand{
}
要能够使用命令,首先要在主程序中添加main方法,并在main方法中调用CommandLine.run(Runnable, String[])
方法,第一个是传入我们的命令类,因此需要继承Runnable
类,并在run()
方法中编写需要执行的代码;第二个则传入主函数接收到的参数args。
@CommandLine.Command(name = "hello", description = "say hello")
public class HelloWorldCommand implements Runnable{
public static void main(String[] args) {
CommandLine.run(new HelloWorldCommand(), args);
}
@Override
public void run() {
System.out.println("Hello Word Command");
}
}
运行主函数,会打印出 Hello Word Command
具体使用
这里我们以实现类似git命令的效果为例
先创建一个GitCommand.class
@CommandLine.Command
public class GitCommand implements Runnable{
public static void main(String[] args) {
CommandLine.run(GitCommand, args);
}
@Override
public void run() {
System.out.println("常见的git命令");
}
}
添加子命令
在子命令类上添加@Command注释
在@Command
注释中添加subcommands
属性,在属性中写明子类。
@Command(
subcommands = {
GitAddCommand.class,
GitCommitCommand.class
}
)
这里创建GitAddCommand.class以及GitCommitCommand.class两个子命令类。子命令类也要加上@Command
注释。
@Command(
name = "add"
)
public class GitAddCommand implements Runnable {
@Override
public void run() {
System.out.println("提交文件到暂存区");
}
}
@Command(
name = "commit"
)
public class GitCommitCommand implements Runnable {
@Override
public void run() {
System.out.println("将缓存区的文件提交到仓库");
}
}
在方法上添加@Command注释
@Command(name = "add")
public void addCommand() {
System.out.println("提交文件到暂存区");
}
@Command(name = "commit")
public void commitCommand() {
System.out.println("将缓存区的文件提交到仓库");
}
以编程方式添加子命令
CommandLine commandLine = new CommandLine(new GitCommand());
commandLine.addSubcommand("add", new GitAddCommand());
commandLine.addSubcommand("commit", new GitCommitCommand());
不再使用CommandLine.run()
,而是使用commandLine.parseWithHandler();
commandLine.parseWithHandler(new RunLast(), args);
parseWithHandler
会解析命令行参数,处理错误等,RunLast()
会确保只有在参数正确解析后才会执行run()
方法。
添加选项
无参数选项
想要实现的效果:在add中添加一个选项,在add后输入这个选项则添加所有文件,没有这个选项则添加部分文件
使用@Option
@Option(names = {"-A", "--all"})
private boolean allFiles;
@Override
public void run() {
if (allFiles) {
System.out.println("添加所有文件到暂存区");
} else {
System.out.println("添加某些文件到暂存区");
}
}
只要在add命令后添加-A或者--all 即可打印"添加所有文件到暂存区"
add -A(-all)
有一个参数选项
想要实现的效果:在commit中添加一个备注选项,在输入该选项后并输入参数
@Option(names = {"-m", "--message"})
private String message;
@Override
public void run() {
System.out.println("将缓存区的文件提交到仓库");
if (message != null) {
System.out.println("备注内容是" + message);
}
}
命令示例:
commit -m xxx
有多个参数选项
想要实现的效果:在commit中添加一个备注选项,在输入该选项后并输入一些参数
@Option(names = {"-m", "--message"})
private String[] messages;
@Override
public void run() {
System.out.println("将缓存区的文件提交到仓库");
if (messages != null) {
System.out.println("备注内容是");
for (String message : messages) {
System.out.println(message);
}
}
}
命令示例:
commit -m xxx -m xxx
可以使用split属性,就不需要写多个-m了
@Option(names = {"-m", "--message"}, split = ",")
private String[] messages;
命令示例:
commit -m xxx,xxx,xxx
必须选项
required属性赋值为true,则在输入命令时必须带上该选项
@Option(names = {"-m", "--message"}, required = true)
private String[] messages;
在使用commit时,如果不带-m,则会报错
管理位置参数
捕获位置参数
位置参数可以捕获特定位置的参数,比如,我想在add命令中增加一个功能,如果在add命令后继续输入某文件的位置,则会将这些文件添加到暂存区
使用@Parameters
注释
@Parameters
private List<Path> files;
@Override
public void run() {
if (allFiles) {
System.out.println("添加所有文件到暂存区");
}
if (files != null) {
files.forEach(path -> System.out.println("添加文件 " + path + " 到暂存区"));
}
}
命令示例:
add file1 file2...