Every Java programmer has used Scanner at one time or another and is excited to write a command-line program.
The command line program is also quite useful. However, it is not easy to write a powerful command line program in Java, which has several pain points:
- There is no mature framework to encapsulate parameter reception, parameter prompting, and parameter verification
- It is difficult to deal with the mutual exclusion of parameters and the interdependence of specific commands
- Command auto-completion cannot be performed
- Java command line programs start slowly because the JVM interprets the execution of bytecode and the JIT is unable to function in short execution
- The integration of SpringBoot and other components slows startup
All of these problems can be solved using Picocli
This article mainly introduces Picocli, and analyzes how it solves the above problems, and introduces the basic process of using it to build a console program, detailed instructions please go to the official documentation.
Liverpoolfc.tv: picocli. Info
Basic introduction
Picocli strives to create a powerful COMMAND line program based on the JVM in the simplest way possible.
Picocli aims to be the easiest way to create rich command line applications that can run on and off the JVM.
Checksum -h: checksum -h: checksum -h: checksum -h: checksum -h: checksum -h: checksum -h: checksum -h: checksum -h: checksum -h
Quick start
There are two ways to define a command:
- useMember attributeTo receive command line arguments to implement
Callable
Interface and overwritecall()
Method defines the business process - Using the arguments of a class method to receive command line arguments, which is the business process inside the method, I recommend this.
Here are two ways to define it:
Implement Callable interface
// Define the checksum command and its prompt
@command (name = "checksum", mixinStandardHelpOptions = true, version = "checksum 4.0", description = "Prints the checksum (MD5 by default) of a file to STDOUT.")
class CheckSum implements Callable<Integer> {
@Parameters(index = "0", description = "The file whose checksum to calculate.")
private File file;
@Option(names = {"-a", "--algorithm"}, description = "MD5, SHA-1, SHA-256, ..." )
private String algorithm = "MD5";
@Override
public Integer call(a) throws Exception { // your business logic goes here...
byte[] fileContents = Files.readAllBytes(file.toPath());
byte[] digest = MessageDigest.getInstance(algorithm).digest(fileContents);
System.out.printf("% 0" + (digest.length*2) + "x%n".new BigInteger(1, digest));
return 0;
}
// this example implements Callable, so parsing, error handling and handling user
// requests for usage help or version help can be done with one line of code.
public static void main(String... args) {
int exitCode = new CommandLine(newCheckSum()).execute(args); System.exit(exitCode); }}Copy the code
Class method
# The above code can be simplified as:@command (name = "checksum", mixinStandardHelpOptions = true, version = "checksum 4.0", description = "Prints the checksum (MD5 by default) of a file to STDOUT.")
public int checkSum(@Parameters(index = "0", description = "The file whose checksum to calculate.") File file,
@Option(names = {"-a", "--algorithm"}, description = "MD5, SHA-1, SHA-256, ..." ) String algorithm) throws Exception {
byte[] fileContents = Files.readAllBytes(file.toPath());
byte[] digest = MessageDigest.getInstance(algorithm).digest(fileContents);
System.out.printf("% 0" + (digest.length * 2) + "x%n".new BigInteger(1, digest));
return 0;
}
Copy the code
How to solve pain points
Now that you’ve gotten a feel for Picocli, let’s begin by answering how Picocli addresses the pain points raised at the beginning of this article.
@ Option with @ Parameter
The difference between
@Option
是Option parameter,Divided intoParameter namesAnd ** parameter content, ** uses parameter names to distinguish different parameters@Parameter
为Position parameter,uselocationTo distinguish between different parameters@Option
Can be stacked@Option
If the parameter is of Boolean type, the parameter content may not be omitted
The same
- You can define default values
- Can be optional parameters, default
@Option(required = false)
,@Parameter
Default is mandatory, but can passarity
Property to control the number of parameters,arity = "0.. 1"
Indicates that the number of parameters is 0-1. - You can use it
interactive = true
Enable interactive input for sensitive information, such as passwords
Default values for and how to use arity:
See: picocli info / # _arity
Rich parameter types
If we use Scanner to read parameters, we need to manually perform parameter parsing and type conversion, and Picocli provides a parameter type parser out of the box, support most of the common Java classes, you can check the type in advance, and simplify the type parsing process.
See: picocli info / # _built_in_…
Parameter calibration
Picocli supports various parameter verification modes:
- Built-in required and arity checks
- Manually check services
- JSR – 380 BeanValidation annotation
BeanValidation annotations are often used in Spring MVC parameter validation, and Picocli also supports BeanValidation annotations, such as @notnull, @notempty, @min, @max, etc.
See: picocli info / # _validatio…
@arggroup (parameter group)
@arggroup (exclusive = true /false, multiplicity = “…”) ) with @option (required=ture/false) and @parameter (@arity = “…” ) can realize the following functions:
- A set of mutually exclusive commands
- The user must enter at least one set of parameters
- A set of commands that have dependencies, meaning that certain parameters cannot be entered without entering one.
- Compound parameter,
@ArgGroup
Can be nested
See: picocli info / # _argument_…
SpringBoot integration
Picocli can be easily combined with SpringBoot.
<dependency>
<groupId>info.picocli</groupId>
<artifactId>picocli-spring-boot-starter</artifactId>
<version>${picocli.version}</version>
</dependency>
Copy the code
@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(a) {
return exitCode;
}
public static void main(String[] args) {
// let Spring instantiate and inject dependenciesSystem.exit(SpringApplication.exit(SpringApplication.run(MySpringMailer.class, args))); }}Copy the code
See: picocli info / # _spring_bo…
Automatic completion
Picocli can automatically generate command completion scripts, so as to realize the completion prompt and automatic completion when the key is pressed.
See: picocli info / # _tab_autoc…
Execute the command
Command line programs built using Picocli can be used in two general ways:
- use
alias
Command to simplify executionjava -jar
- Package it as an executable and add environment variables
alias
alias mycommand='Java - cp/path/to/" picocli - 4.6.1. Jar: / path/to/myapp. Jar "org. Myorg MainClass'
Copy the code
GraalVM Native
GraalVM Native Image enables developers to AOT(Ahead-of-time compile ahead) Java code into an executable file, that is, a Native Image.
As we all know, it usually takes tens of seconds to start a SpringBoot program, which is very unfriendly to command-line users because each command requires a long delay to get a response.
However, the executable compiled by GraalVM Native Image has a very fast startup speed, which is fast enough to meet the response delay required by the command line program.
At the same time, we can rely on the dependencies and Maven plug-ins provided by the Spring Native project to simplify the packaging process.
See:
Picocli documentation: picocli.info/#_graalvm_n…
Spring Native documentation: docs.spring. IO /spring-nati…
Example project: docs.spring. IO /spring-nati…
conclusion
Due to limited space and time, this article only shares the features and usage of Picocli. Readers are advised to check the official documentation for the latest and most complete usage guide. I will continue to update the detailed usage mode if there is time or interest in the future.
Thank you for reading this article, your attention and likes are my biggest support!
Follow my public account “Yubing Yubing” to receive the latest push, which also has some quality resources I share.