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

4.引用

相关推荐
Victor3562 分钟前
Hibernate(3)Hibernate的优点是什么?
后端
Victor3563 分钟前
Hibernate(4)什么是Hibernate的持久化类?
后端
BF06244 分钟前
EPICS Archiver Appliance部署Quickstart方式
java·tomcat
JaguarJack5 分钟前
PHP True Async 最近进展以及背后的争议
后端·php
想不明白的过度思考者2 小时前
Spring Boot 配置文件深度解析
java·spring boot·后端
第二只羽毛2 小时前
Java图书管理系统的设计与实现
java·大数据·安全·系统安全
cike_y7 小时前
Mybatis之解析配置优化
java·开发语言·tomcat·mybatis·安全开发
WanderInk8 小时前
刷新后点赞全变 0?别急着怪 Redis,这八成是 Long 被 JavaScript 偷偷“改号”了(一次线上复盘)
后端
是一个Bug8 小时前
Java基础50道经典面试题(四)
java·windows·python
Slow菜鸟8 小时前
Java基础架构设计(三)| 通用响应与异常处理(分布式应用通用方案)
java·开发语言