命令可用性

由於應用程式的內部狀態,已註冊的命令並不總是合理。例如,可能有一個 download 命令,但它僅在使用者在遠端伺服器上使用 connect 後才有效。現在,如果使用者嘗試使用 download 命令,shell 應說明該命令存在,但目前無法使用。Spring Shell 讓您可以做到這一點,甚至讓您提供命令無法使用的原因的簡短說明。

程式化

使用程式化註冊,您可以使用 availability 方法,該方法接受 Supplier<Availability>

private boolean connected;

@Bean
public CommandRegistration connect(
		CommandRegistration.BuilderSupplier builder) {
	return builder.get()
		.command("connect")
		.withOption()
			.longNames("connected")
			.required()
			.type(boolean.class)
			.and()
		.withTarget()
			.consumer(ctx -> {
				boolean connected = ctx.getOptionValue("connected");
				this.connected = connected;
			})
			.and()
		.build();
}

@Bean
public CommandRegistration download(
		CommandRegistration.BuilderSupplier builder) {
	return builder.get()
		.command("download")
		.availability(() -> {
			return connected
				? Availability.available()
				: Availability.unavailable("you are not connected");
		})
		.withTarget()
			.consumer(ctx -> {
				// do something
			})
			.and()
		.build();
}

註解

對於基於註解的命令,您可以將 @CommandAvailabilityAvailabilityProvider 一起使用。

@Command
class MyCommands {

	private boolean connected;

	@Command(command = "connect")
	public void connect(String user, String password) {
		connected = true;
	}


	@Command(command = "download")
	@CommandAvailability(provider = "downloadAvailability")
	public void download(
	) {
		// do something
	}

	@Bean
	public AvailabilityProvider downloadAvailability() {
		return () -> connected
			? Availability.available()
			: Availability.unavailable("you are not connected");
	}
}

傳統註解

命令可以透過三種可能的方式來指示可用性。它們都使用一個無參數方法,該方法返回 Availability 的實例。考慮以下範例

@ShellComponent
public class MyCommands {

	private boolean connected;

	@ShellMethod("Connect to the server.")
	public void connect(String user, String password) {
		// do something
		connected = true;
	}

	@ShellMethod("Download the nuclear codes.")
	public void download() {
		// do something
	}

	public Availability downloadAvailability() {
		return connected
			? Availability.available()
			: Availability.unavailable("you are not connected");
	}
}

connect 方法用於連接到伺服器(詳細資訊省略),完成後透過 connected 布林值更改命令的狀態。download 命令被標記為不可用,直到使用者連接後才可用,這要歸功於存在一個方法,其名稱與 download 命令方法完全相同,並在其名稱中帶有 Availability 後綴。該方法返回 Availability 的實例,該實例是使用兩種factory方法之一建構的。如果命令不可用,則必須提供解釋。現在,如果使用者嘗試在未連接時調用命令,以下是發生的情況

shell:>download
Command 'download' exists but is not currently available because you are not connected.
Details of the error have been omitted. You can use the stacktrace command to print the full stacktrace.

有關目前不可用命令的資訊也用於整合的說明中。請參閱說明

當命令不可用時,提供的理由應在附加「因為」之後,讀起來通順。

您不應以大寫字母開始句子或添加句點。

如果以命令方法的名稱命名可用性方法不適合您,您可以透過使用 @ShellMethodAvailability 註解來提供明確的名稱

@ShellMethod("Download the nuclear codes.")
@ShellMethodAvailability("availabilityCheck") (1)
public void download() {
}

public Availability availabilityCheck() { (1)
	return connected
		? Availability.available()
		: Availability.unavailable("you are not connected");
}
1 名稱必須匹配

最後,通常情況是,同一類別中的多個命令共享相同的內部狀態,因此,應作為一個群組一起可用或不可用。Spring Shell 不必在所有命令方法上都貼上 @ShellMethodAvailability,而是讓您可以反轉操作,並將 @ShellMethodAvailabilty 註解放在可用性方法上,指定其控制的命令名稱

@ShellMethod("Download the nuclear codes.")
public void download() {
}

@ShellMethod("Disconnect from the server.")
public void disconnect() {
}

@ShellMethodAvailability({"download", "disconnect"})
public Availability availabilityCheck() {
	return connected
		? Availability.available()
		: Availability.unavailable("you are not connected");
}

@ShellMethodAvailability.value() 屬性的預設值為 *。這個特殊的萬用字元符合所有命令名稱。這使得使用單一可用性方法即可輕鬆地開啟或關閉單一類別的所有命令。

@ShellComponent
public class Toggles {

	@ShellMethodAvailability
	public Availability availabilityOnWeekdays() {
		return Calendar.getInstance().get(DAY_OF_WEEK) == SUNDAY
			? Availability.available()
			: Availability.unavailable("today is not Sunday");
	}

	@ShellMethod
	public void foo() {}

	@ShellMethod
	public void bar() {}
}
Spring Shell 對於如何編寫命令以及如何組織類別沒有施加許多限制。但是,通常良好的做法是將相關命令放在同一個類別中,而可用性指示器可以從中受益。