跳到主要内容

命令可用性

ChatGPT-4o-mini 中英对照 Command Availability

注册的命令并不总是有意义,这取决于应用程序的内部状态。例如,可能有一个 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();
}
java

注释

通过基于注解的命令,您可以将 @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");
}
}
java

传统注释

有三种可能的方法可以让命令指示可用性。它们都使用一个无参数的方法,该方法返回一个 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");
}
}
java

connect 方法用于连接到服务器(详细信息省略),在完成时通过 connected 布尔值改变命令的状态。由于存在一个名称完全与 download 命令方法相同并带有 Availability 后缀的方法,因此 download 命令在用户未连接之前被标记为不可用。该方法返回一个 Availability 的实例,该实例是通过两个工厂方法之一构造的。如果命令不可用,则必须提供解释。现在,如果用户在未连接的情况下尝试调用命令,以下情况将发生:

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.
none

有关当前不可用命令的信息也用于集成帮助。请参见 Help

提示

当命令不可用时提供的原因应该在“因为”之后附加时读起来顺畅。

你不应该以大写字母开头或添加句号

如果根据命令方法的名称命名可用性方法不适合您,您可以通过使用 @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");
}
java
  • 名称必须匹配

最后,通常情况下,同一类中的多个命令共享相同的内部状态,因此,它们应该作为一个整体一起可用或不可用。Spring Shell 允许你反转这一点,将 @ShellMethodAvailability 注解放在可用性方法上,指定它所控制的命令名称,而不是必须将 @ShellMethodAvailability 贴在所有命令方法上:

@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");
}
java
提示

@ShellMethodAvailability.value() 属性的默认值是 *。这个特殊的通配符匹配所有命令名称。这使得通过一个可用性方法轻松地打开或关闭单个类的所有命令变得简单:

@ShellComponent
public class Toggles {

@ShellMethodAvailability
public Availability availabilityOnWeekdays() {
return Calendar.getInstance().get(DAY_OF_WEEK) == SUNDAY
? Availability.available()
: Availability.unavailable("今天不是星期天");
}

@ShellMethod
public void foo() {}

@ShellMethod
public void bar() {}
}
java
提示

Spring Shell 对于如何编写命令和如何组织类并没有太多限制。然而,将相关命令放在同一个类中通常是一个好的实践,并且可用性指示器可以从中受益。