原创

Spring Boot集成Picocli快速入门Demo

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 injection
    MySpringMailer(IFactory factory, MailCommand mailCommand) {
        this.factory = factory;
        this.mailCommand = mailCommand;
    }

    @Override
    public void run(String... args) {
        // let picocli parse command line args and run the business logic
        exitCode = new CommandLine(mailCommand, factory).execute(args);
    }

    @Override
    public int getExitCode() {
        return exitCode;
    }

    public static void main(String[] args) {
        // let Spring instantiate and inject dependencies
        System.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;

    @Override
    public 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 message
            message.setFrom(NOREPLY_ADDRESS);                    // compose message
            for (String recipient : to) { message.setTo(recipient); }
            message.setSubject(subject);
            message.setText(text);
            emailSender.send(message);                           // send message

            LOGGER.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 class

MailCommand implements Callable<Integer> {

    @Autowired
    private 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

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
123

4.引用

 
正文到此结束
Loading...