Spring Shell 中文手册 2.0.1 2022最新版官网

Spring Shell

Spring Shell 项目的用户可以通过依赖 Spring Shell jar 并添加他们自己的命令(作为 Spring bean 上的方法)轻松构建功能齐全的 shell(又称命令行)应用程序。创建命令行应用程序可能很有用,例如与项目的 REST API 交互或处理本地文件内容。

特征

Spring Shell 的功能包括

  • 一个简单的、注释驱动的、用于贡献自定义命令的编程模型
  • 使用 Spring Boot 自动配置功能作为命令插件策略的基础
  • 制表符补全、着色和脚本执行
  • 自定义命令提示符、shell 历史文件名、结果和错误处理
  • 基于域特定标准的命令的动态启用
  • 与 bean 验证 API 集成
  • 已经内置命令,如清屏、华丽帮助、退出
  • ASCII 艺术表,具有格式、对齐、花哨的边框等。

春季启动配置

通过添加适当的依赖项来启动您的 Spring Shell 应用程序:

Maven

<dependencies>
    <dependency>
        <groupId>org.springframework.shell</groupId>
        <artifactId>spring-shell-starter</artifactId>
        <version>2.0.0.RELEASE</version>
    </dependency>
</dependencies>复制

Gradle

dependencies {
    compile 'org.springframework.shell:spring-shell-starter:2.0.0.RELEASE'
}复制

然后创建一个可以调用的简单命令

shell:>translate "hello world!" --from en_US --to fr_FR
bonjour monde!复制

假设您可以访问某种与语言环境一起使用的翻译服务:

package foo;

@ShellComponent
public class TranslationCommands {

    private final TranslationService service;

    @Autowired
    public TranslationCommands(TranslationService service) {
      this.service = service;
    }

    @ShellMethod("Translate text from one language to another.")
    public String translate(
      @ShellOption(mandatory = true) String text,
      @ShellOption(mandatory = true, defaultValue = "en_US") Locale from,
      @ShellOption(mandatory = true) Locate to
    ) {
      // invoke service
      return service.translate(text, from, to);
    }
}

Spring Shell 参考文档

埃里克·博塔德

目录

  • 什么是弹簧壳?

  • 使用 Spring Shell

  • 伸展弹簧壳

    • 支持 Spring Shell 1 和 JCommander
    • 发现可以充当命令的方法
    • 解析参数值

版本 2.0.1.RELEASE

© 2017 Pivotal Software, Inc.

本文档的副本可以供您自己使用和分发给其他人,前提是您不对此类副本收取任何费用,并且进一步前提是每份副本都包含本版权声明,无论是印刷版还是电子版。

什么是弹簧壳?

并非所有应用程序都需要精美的 Web 用户界面!有时,使用交互式终端与应用程序交互是完成工作的最合适方式。

Spring Shell 允许人们轻松地创建这样一个可运行的应用程序,用户将在其中输入将执行的文本命令,直到程序终止。Spring Shell 项目提供了创建这样一个 REPL(读取、评估、打印循环)的基础设施,允许开发人员使用熟悉的 Spring 编程模型专注于命令实现。

解析、完成、输出着色、精美的 ascii-art 表格显示、输入转换和验证等高级功能TAB都是免费的,开发人员只需关注核心命令逻辑。

使用 Spring Shell

入门

为了看看 Spring Shell 提供了什么,让我们编写一个简单的 shell 应用程序,它有一个简单的命令来将两个数字相加。

让我们编写一个简单的启动应用程序

从版本 2 开始,Spring Shell 已经从头开始重写,并考虑了各种增强功能,其中之一是与 Spring Boot 的轻松集成,尽管它不是一个强烈的要求。出于本教程的目的,让我们创建一个简单的 Boot 应用程序,例如使用start.spring.io。这个最小的应用程序只依赖spring-boot-starter 和配置spring-boot-maven-plugin,生成一个可执行的 über-jar:

...
<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter</artifactId>
    </dependency>
    ...
在 Spring Shell 上添加依赖项

使用 Spring Shell 的最简单方法是依赖spring-shell-starter工件。这提供了使用 Spring Shell 所需的一切,并且与 Boot 配合得很好,只根据需要配置必要的 bean:

...
<dependency>
    <groupId>org.springframework.shell</groupId>
    <artifactId>spring-shell-starter</artifactId>
    <version>2.0.1.RELEASE</version>
</dependency>
...
鉴于 Spring Shell 将通过存在此依赖关系启动并启动 REPL,您将需要-DskipTests在本教程中构建跳过测试 ( ) 或删除由start.spring.io生成的示例集成测试。如果您不这样做,集成测试将创建 Spring ApplicationContext,并且根据您的构建工具,将停留在 eval 循环中或因 NPE 而崩溃。
你的第一个命令

是时候添加我们的第一个命令了。创建一个新类(根据需要命名)并使用注释@ShellComponent(其变体@Component用于限制扫描候选命令的类集)。

然后,创建一个add接受两个整数(ab)并返回它们的总和的方法。使用注释对其进行注释@ShellMethod并在注释中提供对命令的描述(唯一需要的信息):

package com.example.demo;

import org.springframework.shell.standard.ShellMethod;
import org.springframework.shell.standard.ShellComponent;

@ShellComponent
public class MyCommands {

    @ShellMethod("Add two integers together.")
    public int add(int a, int b) {
        return a + b;
    }
}
让我们试一试吧!

构建应用程序并运行生成的 jar,如下所示;

./mvnw clean install -DskipTests
[...]

java -jar target/demo-0.0.1-SNAPSHOT.jar

您将看到以下屏幕(横幅来自 Spring Boot,并且可以 像往常一样自定义):

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v1.5.6.RELEASE)

shell:>

下面是一个黄色shell:>提示,邀请您输入命令。add 1 2然后输入ENTER并欣赏魔法!

shell:>add 1 2
3

尝试使用 shell(提示:有一个help命令),完成后,键入exit ENTER.

本文档的其余部分深入探讨了整个 Spring Shell 编程模型。

编写自己的命令

Spring Shell 决定将方法转换为实际的 shell 命令的方式是完全可插入的(请参阅扩展 Spring Shell),但从 Spring Shell 2.x 开始,推荐的编写命令的方式是使用本节中描述的新 API(所谓的标准API)。

使用标准API,bean 上的方法将转换为可执行命令,前提是

  • bean 类带有@ShellComponent注释。这用于限制所考虑的 bean 集。
  • 该方法带有@ShellMethod注释。
是一个原型注解,@ShellComponent它本身带有元注解@Component。因此,除了过滤机制之外,它还可以用于声明bean(例如using @ComponentScan)。可以使用value注解的属性自定义创建的 bean 的名称。
一切都与文档有关!

@ShellMethod注释唯一需要的属性是它的value属性,应该用它来写一个简短的一句话,描述命令的作用。这一点很重要,这样您的用户就可以在不离开 shell 的情况下获得有关命令的一致帮助(请参阅使用命令的集成文档help)。

您的命令描述应该简短,只有一两句话。为了更好的一致性,建议以大写字母开头,以点结尾。
自定义命令名称

默认情况下,不需要为您的命令指定键(**即在 shell 中应该用来调用它的单词)。方法的名称将用作命令键,将驼峰命名法的名称转换为虚线、gnu 样式的名称(sayHello()即将变为say-hello)。

但是,可以使用key注释的属性显式设置命令键,如下所示:

        @ShellMethod(value = "Add numbers.", key = "sum")
        public int add(int a, int b) {
                return a + b;
        }
key属性接受多个值。如果您为单个方法设置多个键,则将使用这些不同的别名注册该命令。
命令键可以包含几乎任何字符,包括空格。但是,在提出名称时,请记住用户通常会欣赏一致性(避免将虚线名称与空格名称混合

调用你的命令

按名称位置参数

如上所示,装饰方法@ShellMethod是创建命令的唯一要求。这样做时,用户可以通过两种可能的方式设置所有方法参数的值:

  • 使用参数键(例如 --arg value)。这种方法称为“按名称”参数
  • 或者没有键,只需按照它们出现在方法签名中的相同顺序设置参数值(“位置”参数)。

这两种方法可以混合和匹配,命名参数总是优先(因为它们不太容易产生歧义)。因此,给定以下命令

        @ShellMethod("Display stuff.")
        public String echo(int a, int b, int c) {
                return String.format("You said a=%d, b=%d, c=%d", a, b, c);
        }

那么以下调用都是等效的,如输出所示:

shell:>echo 1 2 3               
You said a=1, b=2, c=3

shell:>echo --a 1 --b 2 --c 3   
You said a=1, b=2, c=3

shell:>echo --b 2 --c 3 --a 1   
You said a=1, b=2, c=3

shell:>echo --a 1 2 3           
You said a=1, b=2, c=3

shell:>echo 1 --c 3 2           
You said a=1, b=2, c=3
这使用位置参数
这是完整的按名称参数的示例
按名称参数可以根据需要重新排序
您可以混合使用这两种方法
非按名称参数按它们出现的顺序解析
自定义命名参数键

如上所示,为命名参数派生密钥的默认策略是使用方法签名的 java 名称并在其前面加上两个破折号 ( --)。这可以通过两种方式进行定制:

  1. 要更改整个方法的默认前缀,请使用注解的prefix()属性 @ShellMethod
  2. 要以每个参数的方式覆盖整个键,请使用注释对参数进行@ShellOption注释。

看看下面的例子:

        @ShellMethod(value = "Display stuff.", prefix="-")
        public String echo(int a, int b, @ShellOption("--third") int c) {
                return String.format("You said a=%d, b=%d, c=%d", a, b, c);
        }

对于这样的设置,可能的参数键将-a-b--third

可以为单个参数指定多个键。如果是这样,这些将是指定相同参数的互斥方式(因此只能使用其中一种)。例如,这里是内置help命令的签名: @ShellMethod("Describe a command.") public String help(@ShellOption({"-C", "--command"}) String command) { ... }
可选参数和默认值

Spring Shell 提供了给参数默认值的能力,这将允许用户省略这些参数:

        @ShellMethod("Say hello.")
        public String greet(@ShellOption(defaultValue="World") String who) {
                return "Hello " + who;
        }

现在,该greet命令仍然可以作为greet Mother(或greet --who Mother)调用,但以下也是可能的:

shell:>greet
Hello World
参数Arity

到目前为止,一直假设每个参数映射到用户输入的单个单词。但是,当参数值应该是多值时,可能会出现情况。这是由注释的arity() 属性驱动的。@ShellOption只需使用集合或数组作为参数类型,并指定需要多少个值:

        @ShellMethod("Add Numbers.")
        public float add(@ShellOption(arity=3) float[] numbers) {
                return numbers[0] + numbers[1] + numbers[2];
        }

然后可以使用以下任何语法调用该命令:

shell:>add 1 2 3.3
6.3
shell:>add --numbers 1 2 3.3
6.3
使用按名称参数方法时,不应重复键。以下不起作用shell:>add --numbers 1 --numbers 2 --numbers 3.3
无限量

将要执行

布尔参数的特殊处理

当涉及到参数数量时,有一种默认情况下会接受特殊处理的参数,这在命令行实用程序中很常见。布尔(即boolean以及java.lang.Boolean)参数的行为就像默认情况下具有arity()of一样0,允许用户使用“标志”方法设置其值。看看以下内容:

        @ShellMethod("Terminate the system.")
        public String shutdown(boolean force) {
                return "You said " + force;
        }

这允许以下调用:

shell:>shutdown
You said false
shell:>shutdown --force
You said true
这种特殊处理与默认值规范配合得很好。尽管布尔参数的默认值是false,但您可以指定其他方式( @ShellOption(defaultValue="true"))并且行为将被反转(即,不指定参数将导致值是true,并且指定标志将导致值是false)
具有这种隐式行为会arity()=0阻止用户指定值(例如 shutdown --force true)。如果您想允许这种行为(并放弃标志方法),请强制1使用注释: @ShellMethod("Terminate the system.") public String shutdown(@ShellOption(arity=1, defaultValue="false") boolean force) { return "You said " + force; }
报价处理

Spring Shell 接受用户输入并将其标记为words,分割空格字符。如果用户想要提供包含空格的参数值,则需要引用该值。支持单 ( ') 和双 ( ") 引号,并且这些引号不会是值的一部分:

        @ShellMethod("Prints what has been entered.")
        public String echo(String what) {
                return "You said " + what;
        }
shell:>echo Hello
You said Hello
shell:>echo 'Hello'
You said Hello
shell:>echo 'Hello World'
You said Hello World
shell:>echo "Hello World"
You said Hello World

同时支持单引号和双引号允许用户轻松地将一种类型的引号嵌入到值中:

shell:>echo "I'm here!"
You said I'm here!
shell:>echo 'He said "Hi!"'
You said He said "Hi!"

如果用户需要嵌入与引用整个参数相同类型的引号,则转义序列使用反斜杠 ( \) 字符:

shell:>echo 'I\'m here!'
You said I'm here!
shell:>echo "He said \"Hi!\""
You said He said "Hi!"
shell:>echo I\'m here!
You said I'm here!

不使用封闭引号时也可以转义空格字符,例如:

shell:>echo This\ is\ a\ single\ value
You said This is a single value
与外壳交互

Spring Shell 项目构建在JLine库之上,因此带来了许多不错的交互功能,本节将详细介绍其中的一些功能。

首先,Spring ShellTAB几乎在所有可能的地方都支持完成。因此,如果有echo命令并且用户按下e, c,TAB则会echo出现。如果有多个以 开头的命令,ec则会提示用户进行选择(使用TAB或 Shift+TAB进行导航和ENTER选择。)

但是完成不会在命令键处停止。如果应用程序开发人员注册了适当的 bean,它也适用于参数键 ( --arg) 甚至参数值(请参阅提供 TAB 完成建议)。

Spring Shell 应用程序的另一个不错的特性是支持行延续。如果命令及其参数太长并且不能很好地显示在屏幕上,用户可以将其分块并用反斜杠 ( \) 字符终止一行,然后点击ENTER并继续下一行。提交整个命令后,这将被解析为好像用户在换行符处输入了一个空格。

shell:>register module --type source --name foo  \ 
> --uri file:///tmp/bar
Successfully registered module 'source:foo'
命令在下一行继续

如果用户打开了引号(请参阅Quotes Handling)并ENTER在引号中点击,则行继续也会自动触发:

shell:>echo "Hello 
dquote> World"
You said Hello World
用户按ENTER这里

最后,Spring Shell 应用程序受益于许多您在使用从 Emacs 借来的常规 OS Shell 时可能已经熟悉的键盘快捷键。值得注意的快捷方式包括Ctrl+r执行反向搜索,Ctrl+a和Ctrl+e分别移动到行首和行尾,或者Esc f一次 Esc b向前(向后)移动一个单词。

提供 TAB 完成提案

待定

验证命令参数

Spring Shell 与Bean Validation API集成以支持对命令参数的自动和自记录约束。

在命令参数上找到的注释以及方法级别的注释将在命令执行之前得到认可并触发验证。给定以下命令:

        @ShellMethod("Change password.")
        public String changePassword(@Size(min = 8, max = 40) String password) {
                return "Password successfully set to " + password;
        }

您将免费获得此行为:

shell:>change-password hello
不满足以下约束:
	--password string : size 必须在 8 到 40 之间(你传递了 'hello')
适用于所有命令实现重要的是要注意,通过使用适配器,bean 验证适用于所有命令实现,无论它们使用“标准”API 还是任何其他 API(请参阅支持其他 API

动态命令可用性

由于应用程序的内部状态,有时注册的命令可能没有意义。例如,可能有一个download命令,但它只有在用户connect在远程服务器上使用后才有效。现在,如果用户尝试使用该download命令,shell 应该优雅地解释该命令确实存在,但当时它不可用。Spring Shell 允许开发人员这样做,甚至提供命令不可用原因的简短解释。

命令可以通过三种可能的方式来指示可用性。它们都利用了一个无参数方法,该方法返回一个Availability. 让我们从一个简单的例子开始:

@ShellComponent
public class MyCommands {

    private boolean connected;

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

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

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

在这里您可以看到该connect方法用于连接到服务器(细节省略),connected完成后通过布尔值更改命令的状态。在用户连接之前,该download命令将被标记为不可用,这要归功于存在与download命令方法完全相同且Availability名称中带有后缀的方法。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.

集成帮助中还利用了有关当前不可用命令的信息。请参阅使用命令的集成文档help

当命令不可用时提供的原因如果附加在“因为……”之后应该很好读最好不要以大写开头,也不要添加最后一个点。

如果由于某种原因在命令方法的名称之后命名可用性方法不适合您,您可以使用 提供一个明确的名称@ShellMethodAvailability,如下所示:

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

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

最后,通常情况下,同一类中的多个命令共享相同的内部状态,因此应该全部可用或不可用。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 并没有对如何编写命令和如何组织类施加太多限制。但是将相关命令放在同一个类中通常是一种很好的做法,可用性指标可以从中受益。

组织命令

当您的 shell 开始提供很多功能时,您可能会遇到很多命令,这可能会让您的用户感到困惑。键入help 他们会看到一个令人生畏的命令列表,按字母顺序排列,这可能并不总是有意义的。

为了缓解这种情况,Spring Shell 提供了将命令组合在一起的能力,并具有合理的默认值。然后相关的命令将在同一个中结束(例如 User Management Commands)并一起显示在帮助屏幕和其他地方。

默认情况下,命令将根据实现它们的类进行分组,将驼峰式类名转换为单独的单词(因此URLRelatedCommands变为URL Related Commands)。这是一个非常明智的默认设置,因为相关命令通常已经在类中,因为它们需要使用相同的协作对象。

但是,如果此行为不适合您,您可以通过以下方式覆盖命令的组,按优先级顺序排列:

  • group()@ShellMethod注释中指定 a
  • 将 a@ShellCommandGroup放在定义命令的类上。这将为该类中定义的所有命令应用组(除非如上所述被覆盖)
  • 将 a@ShellCommandGroup放在定义命令的包(via package-info.java)上。这将适用于包中定义的所有命令(除非如上所述在方法或类级别被覆盖)

这是一个简短的例子:

public class UserCommands {
    @ShellMethod(value = "This command ends up in the 'User Commands' group")
    public void foo() {}

    @ShellMethod(value = "This command ends up in the 'Other Commands' group",
            group = "Other Commands")
    public void bar() {}
}

...

@ShellCommandGroup("Other Commands")
public class SomeCommands {
        @ShellMethod(value = "This one is in 'Other Commands'")
        public void wizz() {}

        @ShellMethod(value = "And this one is 'Yet Another Group'",
                group = "Yet Another Group")
        public void last() {}
}

内置命令

spring-shell-starter使用工件(或更准确地说,依赖项)构建的任何应用程序spring-shell-standard-commands都带有一组内置命令。这些命令可以单独覆盖或禁用(请参阅覆盖或禁用内置命令),但如果不是,本节将描述它们的行为。

help使用命令集成文档

运行 shell 应用程序通常意味着用户处于图形受限的环境中。尽管在手机时代,我们始终保持连接,但访问 Web 浏览器或任何其他丰富的 UI 应用程序(例如 pdf 查看器)可能并不总是可行的。这就是为什么正确地自我记录 shell 命令很重要的原因,这就是help 命令的用武之地。

键入help+ENTER将列出所有已知的 shell 命令(包括不可用的命令)以及它们的作用的简短描述:

shell:>help
AVAILABLE COMMANDS
        add: Add numbers together.
      * authenticate: Authenticate with the system.
      * blow-up: Blow Everything up.
        clear: Clear the shell screen.
        connect: Connect to the system
        disconnect: Disconnect from the system.
        exit, quit: Exit the shell.
        help: Display help about available commands.
        register module: Register a new module.
        script: Read and execute commands from a file.
        stacktrace: Display the full stacktrace of the last error.

Commands marked with (*) are currently unavailable.
Type `help <command>` to learn more.

键入help <command>将显示有关命令的更详细信息,包括可用参数、它们的类型以及它们是否强制等。

这是help应用于自身的命令:

shell:>help help 


NAME 
	help - 显示有关可用命令的帮助。

SYNOPSYS 
	help [[-C] string]

选项
	-C 或 --command string
		获取帮助的命令。[可选,默认 = <无>]
清屏

clear命令执行您所期望的操作并清除屏幕,重置左上角的提示。

退出壳牌

quit命令(也别名为exit)只是请求 shell 退出,优雅地关闭 Spring 应用程序上下文。如果没有被覆盖,JLine Historybean 会将执行的所有命令的历史记录写入磁盘,以便它们在下次启动时再次可用(请参阅与 Shell 交互)。

显示有关错误的详细信息

当命令代码内部发生异常时,它会被 shell 捕获并显示一条简单的单行消息,以免向用户提供过多的信息。在某些情况下,了解究竟发生了什么很重要(特别是如果异常有嵌套原因)。

为此,Spring Shell 会记住最后发生的异常,用户稍后可以使用该stacktrace 命令在控制台上打印所有血腥细节。

运行一批命令

script命令接受一个本地文件作为参数,并将重放在那里找到的命令,一次一个。

从文件中读取的行为与交互式 shell 中的行为完全相同,因此以 开头的//行将被视为注释并被忽略,而以 结尾的\行将触发行继续。

自定义外壳

覆盖或禁用内置命令

Spring Shell 提供了内置命令,以实现许多(如果不是所有)shell 应用程序都需要的日常任务。如果您对它们的行为方式不满意,您可以禁用或覆盖它们,如本节所述。

禁用所有内置命令如果您根本不需要内置命令,那么有一种简单的方法可以“禁用”它们:不要包含它们!要么使用 maven 排除,spring-shell-standard-commands或者,如果您有选择地包含 Spring Shell 依赖项,请不要将其引入!<dependency> <groupId>org.springframework.shell</groupId> <artifactId>spring-shell-starter</artifactId> <version>2.0.1.RELEASE</version> <exclusions> <exclusion> <groupId>org.springframework.shell</groupId> <artifactId>spring-shell-standard-commands</artifactId> </exclusion> </exclusion> </dependency>
禁用特定命令

要禁用单个内置命令,只需在应用程序 中将spring.shell.command.<command>.enabled属性设置为。一种简单的方法是将额外的参数传递给入口点中的 Boot 应用程序:false``Environment``main()

        public static void main(String[] args) throws Exception {
                String[] disabledCommands = {"--spring.shell.command.help.enabled=false"}; 
                String[] fullArgs = StringUtils.concatenateStringArrays(args, disabledCommands);
                SpringApplication.run(MyApp.class, fullArgs);
        }
这将禁用集成help命令
覆盖特定命令

如果您宁愿提供自己的实现而不是禁用命令,那么您可以

  • 禁用上述命令,并使用相同的名称注册您的实现

  • 让您的实现类实现<Command>.Command接口。例如,以下是如何覆盖clear命令:

    public class MyClear implements Clear.Command {
    
        @ShellMethod("Clear the screen, only better.")
        public void clear() {
            // ...
        }
    }
    
请考虑贡献您的更改如果您觉得您的标准命令的实现可能对社区有价值,请考虑在github.com/spring-projects/spring-shell上打开一个拉取请求。或者,在您自己进行任何更改之前,您可以打开项目的问题。随时欢迎反馈!
结果处理程序
提示提供者

每次命令调用后,shell 都会等待用户的新输入,并以黄色显示提示:

shell:>

可以通过注册一个 bean 类型来定制这种行为PromptProvider。这样的 bean 可以使用内部状态来决定向用户显示什么(例如,它可以对应用程序事件做出反应)并且可以使用 JLineAttributedCharSequence来显示花哨的 ANSI 文本。

这是一个虚构的例子:

@Component
public class CustomPromptProvider implements PromptProvider {

        private ConnectionDetails connection;

        @Override
        public AttributedString getPrompt() {
                if (connection != null) {
                        return new AttributedString(connection.getHost() + ":>",
                                AttributedStyle.DEFAULT.foreground(AttributedStyle.YELLOW));
                }
                else {
                        return new AttributedString("server-unknown:>",
                                AttributedStyle.DEFAULT.foreground(AttributedStyle.RED));
                }
        }

        @EventListener
        public void handle(ConnectionUpdatedEvent event) {
                this.connection = event.getConnectionDetails();
        }
}
自定义命令行选项行为

Spring Shell 带有两个默认的 Spring Boot ApplicationRunners

  • InteractiveShellApplicationRunner引导 Shell REPL。它设置 JLine 基础设施并最终调用Shell.run()
  • ScriptShellApplicationRunner查找以 开头的程序参数,假定它们是本地文件名并尝试运行包含在这些文件中的命令(与脚本命令@具有相同的语义),然后退出进程(通过有效禁用,见下文)。InteractiveShellApplicationRunner

如果此行为不适合您,只需提供一个(或多个)类型的 beanApplicationRunner 并可选择禁用标准的 bean。您将希望从以下方面获得灵感ScriptShellApplicationRunner

@Order(InteractiveShellApplicationRunner.PRECEDENCE - 100) // Runs before InteractiveShellApplicationRunner
public class ScriptShellApplicationRunner implements ApplicationRunner {

        @Override
        public void run(ApplicationArguments args) throws Exception {
                List<File> scriptsToRun = args.getNonOptionArgs().stream()
                                .filter(s -> s.startsWith("@"))
                                .map(s -> new File(s.substring(1)))
                                .collect(Collectors.toList());

                boolean batchEnabled = environment.getProperty(SPRING_SHELL_SCRIPT_ENABLED, boolean.class, true);

                if (!scriptsToRun.isEmpty() && batchEnabled) {
                        InteractiveShellApplicationRunner.disable(environment);
                        for (File file : scriptsToRun) {
                                try (Reader reader = new FileReader(file);
                                                FileInputProvider inputProvider = new FileInputProvider(reader, parser)) {
                                        shell.run(inputProvider);
                                }
                        }
                }
        }

...
自定义参数转换

从文本输入到实际方法参数的转换使用标准的 Spring 转换机制。Spring Shell 安装一个新的DefaultConversionService(启用了内置转换器)并向它注册任何类型的 bean Converter<S, T>GenericConverter或者 ConverterFactory<S, T>它在应用程序上下文中找到的任何 bean。

这意味着自定义转换为自定义类型的对象非常容易Foo:只需在上下文中安装一个Converter<String, Foo>bean。

@ShellComponent
class ConversionCommands {

        @ShellMethod("Shows conversion using Spring converter")
        public String conversionExample(DomainObject object) {
                return object.getClass();
        }

}

class DomainObject {
        private final String value;

        DomainObject(String value) {
                this.value = value;
        }

        public String toString() {
                return value;
        }
}

@Component
class CustomDomainConverter implements Converter<String, DomainObject> {

        @Override
        public DomainObject convert(String source) {
                return new DomainObject(source);
        }
}
注意你的字符串表示如上面的示例所示,如果您可以让您的toString()实现返回用于创建对象实例的相反内容,这可能是一个好主意。这是因为当一个值验证失败时,Spring Shell 会打印The following constraints were not met: --arg <type> : <message> (You passed '<value.toString()>')有关详细信息,请参阅验证命令参数
如果你想ConversionService进一步定制,你可以将默认代码注入您的代码并以某种方式对其进行操作用您自己的完全覆盖它(自定义转换器需要手动注册)。Spring Shell 使用的 ConversionService 需要限定"spring-shell".
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值