1.什么是Picocli?
Picocli是一个单文件命令行解析框架,它允许您创建命令行应用而几乎不需要代码。使用 @Option
或 @Parameters
在您的应用中注释字段,Picocli将分别使用命令行选项和位置参数填充这些字段。使用Picocli来编写一个功能强大的命令行程序。
痛点
- 没有成熟的框架来封装参数接收、参数提示以及参数校验
- 很难处理参数的互斥以及特定命令的相互依赖关系
- 无法进行命令自动补全
- 由于JVM解释执行字节码,并且JIT无法在短时执行中发挥作用,Java命令行程序启动缓慢
- 集成SpringBoot及其它组件后,启动更加缓慢
2.代码工程
实现目的:使用Picocli编写一个邮件发送命令
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><parent><artifactId>springboot-demo</artifactId><groupId>com.et</groupId><version>1.0-SNAPSHOT</version></parent><modelVersion>4.0.0</modelVersion><artifactId>picocli</artifactId><properties><maven.compiler.source>8</maven.compiler.source><maven.compiler.target>8</maven.compiler.target></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-autoconfigure</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><dependency><groupId>info.picocli</groupId><artifactId>picocli-spring-boot-starter</artifactId><version>4.7.6</version></dependency><!--email--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-mail</artifactId></dependency></dependencies><!--<build><finalName>demo1</finalName><plugins><plugin><artifactId>maven-assembly-plugin</artifactId><configuration><descriptorRefs><descriptorRef>jar-with-dependencies</descriptorRef></descriptorRefs><archive><manifest><mainClass>com.et.picocli.MySpringMailer</mainClass></manifest></archive></configuration><executions><execution><id>make-assembly</id><phase>package</phase><goals><goal>single</goal></goals></execution></executions></plugin></plugins></build>--><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><executions><execution><goals><goal>repackage</goal></goals></execution></executions></plugin></plugins></build></project>
启动类
package com.et.picocli;import com.et.picocli.command.MailCommand;
import org.springframework.boot.*;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import picocli.CommandLine;
import picocli.CommandLine.IFactory;@SpringBootApplication
public class MySpringMailer implements CommandLineRunner, ExitCodeGenerator {private IFactory factory; private MailCommand mailCommand;private int exitCode;// constructor injectionMySpringMailer(IFactory factory, MailCommand mailCommand) {this.factory = factory;this.mailCommand = mailCommand;}@Overridepublic void run(String... args) {// let picocli parse command line args and run the business logicexitCode = new CommandLine(mailCommand, factory).execute(args);}@Overridepublic int getExitCode() {return exitCode;}public static void main(String[] args) {// let Spring instantiate and inject dependenciesSystem.exit(SpringApplication.exit(SpringApplication.run(MySpringMailer.class, args)));}
}
service
package com.et.picocli.service;import java.util.List;public interface IMailService {void sendMessage(List<String> to, String subject, String text);
}
package com.et.picocli.service;import org.slf4j.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mail.*;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.stereotype.Service;
import java.util.List;@Service("MailService")
public class MailServiceImpl implements IMailService {private static final Logger LOGGER= LoggerFactory.getLogger(MailServiceImpl.class);private static final String NOREPLY_ADDRESS = "noreply@picocli.info";@Autowired(required = false)private JavaMailSender emailSender;@Overridepublic void sendMessage(List<String> to, String subject, String text) {LOGGER.info(" start Mail to {} sent! Subject: {}, Body: {}", to, subject, text);try {SimpleMailMessage message = new SimpleMailMessage(); // create messagemessage.setFrom(NOREPLY_ADDRESS); // compose messagefor (String recipient : to) { message.setTo(recipient); }message.setSubject(subject);message.setText(text);emailSender.send(message); // send messageLOGGER.info(" end Mail to {} sent! Subject: {}, Body: {}", to, subject, text);}catch (MailException e) { e.printStackTrace(); }}
}
command
package com.et.picocli.command;import com.et.picocli.service.IMailService;
import org.springframework.stereotype.Component;
import org.springframework.beans.factory.annotation.Autowired;
import picocli.CommandLine;
import picocli.CommandLine.*;
import java.util.List;
import java.util.concurrent.Callable;@Component
//@Command(name = "mailCommand")
@CommandLine.Command(subcommands = {GitAddCommand.class,GitCommitCommand.class}
)
public classMailCommand implements Callable<Integer> {@Autowiredprivate IMailService mailService;@Option(names = "--to", description = "email(s) of recipient(s)", required = true)List<String> to;@Option(names = "--subject", description = "Subject")String subject;@Parameters(description = "Message to be sent")String[] body = {};public Integer call() throws Exception {mailService.sendMessage(to, subject, String.join(" ", body)); return 0;}
}
application.properties
# configuration mail service
spring.mail.host=smtp.gmail.com
spring.mail.port=587
spring.mail.username=email
spring.mail.password=password
spring.mail.properties.mail.smtp.auth=true
spring.mail.properties.mail.smtp.starttls.enable=true
spring.mail.properties.mail.smtp.starttls.required=true
以上只是一些关键代码,所有代码请参见下面代码仓库
代码仓库
- GitHub - Harries/springboot-demo: a simple springboot demo with some components for example: redis,solr,rockmq and so on.
3.测试
打包Spring Boot应用程序
mvn install
进入target目录
cd target
执行命令
//发送邮件
java -jar picocli-1.0-SNAPSHOT.jar --to ss@163.com --subject testmail text 111111
//执行子命令
java -jar picocli-1.0-SNAPSHOT.jar --to ss@163.com --subject testmail text 111111 add
打印help
java -jar picocli-1.0-SNAPSHOT.jar --help
4.引用
- picocli - a mighty tiny command line interface
- Spring Boot集成Picocli快速入门Demo | Harries Blog™