一提到Java程式開發,你腦海中立馬浮現出來的應該是Web服務端和手機程式開發。今天帶你看看Java開發模式的一股清流,基于指令行的應用程式開發。雖然基于指令行的程式對于使用者來說并不友好,但是對于開發人員使用指令行模式也是必不可少的,在某種程度上也是不可避免的,比如之前提到的sdkman、mvn和gradle等指令行程式,這次咱們一起看下使用Quarkus開發指令行程式。
先看一下效果
使用效果跟Linux/Mac腳本是一樣的,隻是實作是使用Java實作的。
入門
- 通過IDEA建立Quarkus項目,并勾選依賴quarkus-picocli
- 建立成功之後,會有一個demo程式
import io.quarkus.picocli.runtime.annotations.TopCommand;
import picocli.CommandLine.Command;
import picocli.CommandLine.Parameters;
@TopCommand
@Command(name = "greeting", mixinStandardHelpOptions = true)
public class GreetingCommand implements Runnable {
@CommandLine.Option(names = {"-n", "--name"}, description = "Who will we greet?", defaultValue = "World")
String name;
@Override
public void run() {
System.out.printf("Hello %s!\n", name);
}
}
@TopCommand: picocli執行個體指令的入口點
@Command:聲明一個指令,name:指定指令名稱,mixinStandardHelpOptions:顯示标準的-h,—help和-V,—version
@CommandLine.Option:設定指令的參數
GreetingCommand implements Runnable: 聲明指令需要實作Runnable或者Callable接口
- 打包和運作程式
./mvnw package
quarkus-run.jar将會在target/quarkus-app/下面生成,這個jar可以直接通過指令執行。java -jar
target/quarkus-app/quarkus-run.jar
- 建構本地可執行程式,
通過這種方式建構,需要本地安裝GraalVM并正确配置環境變量(可以使用SDKman安裝)
./mvnw package -Pnative
通過docker的方式,建構本地可執行程式
./mvnw package -Pnative -Dquarkus.native.container-build=true
- 建構成功之後,在target目錄,會有一個名為<artifactId>-<version>-runner的可執行檔案,可以直接在Linux上通過指令bash <artifactId>-<version>-runner執行該檔案。
-
執行效果
執行行為基本跟Linux/Mac的script一緻。
案例實作
- 代碼
import io.quarkus.picocli.runtime.annotations.TopCommand;
import picocli.CommandLine;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
@TopCommand
@CommandLine.Command(mixinStandardHelpOptions = true, subcommands = {ListFilesCommand.class, HelloCommand.class, GoodbyeCommand.class, TimeCommand.class})
public class EntryCommand {
}
@CommandLine.Command(name = "list", description = "List all files!")
class ListFilesCommand implements Runnable {
@CommandLine.Option(names = {"-p", "--path"}, description = "Files path")
private String path;
@Override
public void run() {
try {
Files.list(Path.of(path)).forEach(path1 -> System.out.println(path1.getFileName()));
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
@CommandLine.Command(name = "hello", description = "Say hello world!")
class HelloCommand implements Runnable {
@Override
public void run() {
System.out.println("Hello World!");
}
}
@CommandLine.Command(name = "goodbye", description = "Say goodbye world!")
class GoodbyeCommand implements Runnable {
@Override
public void run() {
System.out.println("Goodbye World!");
}
}
@CommandLine.Command(name = "time", description = "Current time")
class TimeCommand implements Runnable {
@Override
public void run() {
System.out.println(LocalDateTime.now().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME));
}
}
@TopCommand: picocli執行個體指令的入口點
@CommandLine.Command: 設定程式參數和一些子指令,每個子指令都需要實作Runnable或者Callable接口
-
建構docker鏡像
如果使用Linux可以不建構docker鏡像,執行完第一步之後,就會在target目錄,會有一個名為<artifactId>-<version>-runner的可執行檔案。
# Step1
./mvnw package -Pnative -Dquarkus.native.container-build=true
# Step2
docker build -f src/main/docker/Dockerfile.native-micro -t quarkus/command-line .
檢視docker鏡像大小,可以看到隻有59M,跟其他基于JVM運作的docker鏡像相比,還是相當具有優勢的。
- 建立執行腳本
vim myscript
# 内容
#!/usr/bin/env bash
docker run --rm -it docker.io/quarkus/command-line ./application "$@"
授予執行權限
chmod +x myscript
-
執行
./myscript hello
結果中會顯示Quarkus的banner資訊和log資訊
-
去除額外的資訊
修改application.properties,添加以下配置
quarkus.banner.enabled=false #禁用banner
%prod.quarkus.log.level=WARNING # 設定log級别
-
重新執行
./myscript hello,輸出結果就幹淨多了。