天天看點

互動式指令行Java程式開發,實作shell腳本一樣的互動程式

作者:下頁程式設計之道

一提到Java程式開發,你腦海中立馬浮現出來的應該是Web服務端和手機程式開發。今天帶你看看Java開發模式的一股清流,基于指令行的應用程式開發。雖然基于指令行的程式對于使用者來說并不友好,但是對于開發人員使用指令行模式也是必不可少的,在某種程度上也是不可避免的,比如之前提到的sdkman、mvn和gradle等指令行程式,這次咱們一起看下使用Quarkus開發指令行程式。

先看一下效果

互動式指令行Java程式開發,實作shell腳本一樣的互動程式

使用效果跟Linux/Mac腳本是一樣的,隻是實作是使用Java實作的。

入門

  1. 通過IDEA建立Quarkus項目,并勾選依賴quarkus-picocli
互動式指令行Java程式開發,實作shell腳本一樣的互動程式
  • 建立成功之後,會有一個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一緻。

案例實作

  1. 代碼
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接口

  1. 建構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鏡像相比,還是相當具有優勢的。

互動式指令行Java程式開發,實作shell腳本一樣的互動程式
  1. 建立執行腳本
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,輸出結果就幹淨多了。