SpringShell之使用简介

mac2026-09-22  12

一、什么是Spring Shell ?

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

诸如解析,TAB完成,输出着色,精美的ascii-art表显示,输入转换和验证之类的高级功能都是免费提供的,而开发人员仅需专注于核心命令逻辑即可。

二、使用Spring Shell

2.1. 引入依赖
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.2.0.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.mly.shell</groupId> <artifactId>mly-shell</artifactId> <version>1.0.0</version> <name>mly-shell</name> <description>自定义的Spring Shell</description> <properties> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <!-- Spring Shell 依赖 --> <dependency> <groupId>org.springframework.shell</groupId> <artifactId>spring-shell-starter</artifactId> <version>2.0.1.RELEASE</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-configuration-processor</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> <exclusions> <exclusion> <groupId>org.junit.vintage</groupId> <artifactId>junit-vintage-engine</artifactId> </exclusion> </exclusions> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
2.2. 第一个小例子
import org.springframework.shell.standard.ShellComponent; import org.springframework.shell.standard.ShellMethod; /** * @author 墨龙吟 * @version 1.0.0 * @ClassName CommandsOne.java * @Email 2354713722@qq.com * @Description 第一条命令 * @createTime 2019年10月31日 - 13:22 */ @ShellComponent public class CommandsOne { @ShellMethod("Add two integers together.") public int add (int a, int b) { return a + b; } }

运行输出:(输入exit退出命令行)

. ____ _ __ _ _ /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ \\/ ___)| |_)| | | | | || (_| | ) ) ) ) ' |____| .__|_| |_|_| |_\__, | / / / / =========|_|==============|___/=/_/_/_/ :: Spring Boot :: (v2.2.0.RELEASE) shell:>add 1 3 4 shell:>exit Process finished with exit code 0

构建jar包运行

E:\owner_app\mly-shell>mvn install -DskipTests [INFO] Scanning for projects... [INFO] [INFO] ----------------------< com.mly.shell:mly-shell >----------------------- [INFO] Building mly-shell 1.0.0 [INFO] --------------------------------[ jar ]--------------------------------- [INFO] [INFO] --- maven-resources-plugin:3.1.0:resources (default-resources) @ mly-shell --- [INFO] Using 'UTF-8' encoding to copy filtered resources. [INFO] Copying 1 resource [INFO] Copying 0 resource [INFO] [INFO] --- maven-compiler-plugin:3.8.1:compile (default-compile) @ mly-shell --- [INFO] Changes detected - recompiling the module! [INFO] Compiling 2 source files to E:\owner_app\mly-shell\target\classes [INFO] [INFO] --- maven-resources-plugin:3.1.0:testResources (default-testResources) @ mly-shell --- [INFO] Using 'UTF-8' encoding to copy filtered resources. [INFO] skip non existing resourceDirectory E:\owner_app\mly-shell\src\test\resources [INFO] [INFO] --- maven-compiler-plugin:3.8.1:testCompile (default-testCompile) @ mly-shell --- [INFO] Changes detected - recompiling the module! [INFO] Compiling 1 source file to E:\owner_app\mly-shell\target\test-classes [INFO] [INFO] --- maven-surefire-plugin:2.22.2:test (default-test) @ mly-shell --- [INFO] Tests are skipped. [INFO] [INFO] --- maven-jar-plugin:3.1.2:jar (default-jar) @ mly-shell --- [INFO] Building jar: E:\owner_app\mly-shell\target\mly-shell-1.0.0.jar [INFO] [INFO] --- spring-boot-maven-plugin:2.2.0.RELEASE:repackage (repackage) @ mly-shell --- [INFO] Replacing main artifact with repackaged archive [INFO] [INFO] --- maven-install-plugin:2.5.2:install (default-install) @ mly-shell --- [INFO] Installing E:\owner_app\mly-shell\target\mly-shell-1.0.0.jar to D:\DevelopSoftware\apache-maven-3.6.1\repository\com\mly\shell\mly-shell\1.0.0\mly-shell-1.0.0.jar [INFO] Installing E:\owner_app\mly-shell\pom.xml to D:\DevelopSoftware\apache-maven-3.6.1\repository\com\mly\shell\mly-shell\1.0.0\mly-shell-1.0.0.pom [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 5.268 s [INFO] Finished at: 2019-10-31T13:35:11+08:00 [INFO] ------------------------------------------------------------------------ E:\owner_app\mly-shell>cd target E:\owner_app\mly-shell>java -jar mly-shell-1.0.0.jar # 执行命令
2.3. 自定义命令名称的方法

2.3.1. 默认为方法名为命令名:

@ShellMethod("Add two integers together.") public int add (int a, int b) { return a + b; } // shell:>add 1 3 #返回结果 4

这样子上面的命令名:add 1 2 , 将会返回3

2.3.2 如果方法名是由驼峰单词组成,命令名将会变以横杠分割多个单词:

@ShellMethod(value = "add sum") public int sumAdd(int a, int b) { return a + b; } // shell:>sum-add 1 2 #返回结果 3

2.3.3. 如果是命令是以下划线分割的,将还以原型式作为命令名

@ShellMethod(value = "add sumasas") public int sum_add(int a, int b) { return a + b; } // shell:>sum_adds 1 3 # 返回结果 4

2.3.4 命令也可以有别名

@ShellMethod(value = "add sumasas", key = {"sum0", "sum1", "sum2"}) public int adds(int a, int b) { return a + b; } // shell:>sum0 1 4 # 返回结果 5 // shell:>sum1 1 3 # 返回结果 4 // shell:>sum2 1 3 # 返回结果 4
2.4. 参数的使用

命令参数使用方法:

@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 --c 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
2.5. 自定义参数键
@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); }

参数使用:

shell:>echo -a 1 -b 2 --third 3 You said a = 1, b = 2, c = 3 shell:>echo 1 2 3 You said a = 1, b = 2, c = 3 shell:>echo 1 2 --third 3 You said a = 1, b = 2, c = 3
2.6. 可选参数和默认参数
@ShellMethod("两数相加:") public int add (@ShellOption(defaultValue = "3") int a, int b) { return a + b; }

参数使用

shell:>add 3 # 这样使用是不对的哦! Parameter '--b int' should be specified Details of the error have been omitted. You can use the stacktrace command to print the full stacktrace. shell:>add --b 3 # 默认 a 参数, 需要指定参数 b 6 shell:>add 1 2 # 正常的使用 3
2.7. 多个参数可以使用Arity

上面情况每个参数都映射到用户输入单个参数,当对应多个参数时需要用到Arity对应一个数组或者是一个集合来承接参数。

@ShellMethod("多个数字相加:") public float add1 (@ShellOption(arity = 3) float[] numbers) { return numbers[0] + numbers[1] + numbers[2]; } // ====================输出======================= shell:>add1 2 3.5 6.7 12.2
2.8 对于布尔参数的特殊处理

当涉及参数Arity时,默认情况下,有一种参数会接受特殊处理:布尔值(即boolean和java.lang.Boolean)参数的行为类似于默认情况下的arity()of 0,允许用户使用“标志”方法设置其值。

参数使用展示:

@ShellMethod("Terminate the system.") public String shutdown(boolean force) { return "You said " + force; } // ====================错误输出======================= shell:>shutdown true Too many arguments: the following could not be mapped to parameters: 'true' Details of the error have been omitted. You can use the stacktrace command to print the full stacktrace. // ====================正确输出======================= shell:>shutdown You said false shell:>shutdown --force You said true

以上得出结论:布尔参数默认为false。

2.9. 多字符串操作:

Spring Shell接受用户输入并将其用 单词 标记化,并按空格分隔。如果用户想提供一个包含空格的参数值,则该值必须用引号引起来。单引号(')和双"引号()都受支持,并且这些引号将不属于值的一部分。

@ShellMethod("接受多个值:") public String echo(String what) { return "You said " + what; } // ====================正确输出======================= shell:>echo "Java python" You said Java python shell:>echo 'java Python' You said java Python shell:>echo "I'm tom" You said I'm tom
2.10. 参数验证

Spring Shell与Bean Validation API集成在一起,以支持对命令参数的验证。

@ShellMethod("修改密码:") public String changePassword(@Size(min = 8, max = 16, message = "密码长度必须在8到16之间") String password) { return "密码修改成功:" + password; } // ====================正确输出======================= shell:>change-password 12345 The following constraints were not met: --password string : 密码长度必须在8到16之间 (You passed '12345') shell:>change-password 1234567889 密码修改成功:1234567889
2.11. 内置命令
shell:>help AVAILABLE COMMANDS Built-In Commands clear: 清除屏幕. exit, quit: 退出shell. help: 显示有关可用命令的帮助. history: 显示以前的命令 script: 读和执行命令从一个文件. stacktrace: 显示上一个错误的完整堆栈跟踪. wxz Commands One connect: Connect to the server. download: Download the nuclear codes.
2.12. 命令分组

方法一:在ShellMethod中添加group

@ShellComponent(value = "自定义的命令") public class UserCommands { @ShellMethod(value = "命令一", group = "分组一") public void command1() {} @ShellMethod(value = "命令二", group = "分组二") public void command2() {} @ShellMethod(value = "命令三", group = "分组三") public void command3() {} }

当输入help命令时显示:

shell:>help AVAILABLE COMMANDS Built-In Commands clear: Clear the shell screen. exit, quit: Exit the shell. help: Display help about available commands. history: Display or save the history of previously run commands script: Read and execute commands from a file. stacktrace: Display the full stacktrace of the last error. 分组一 command1: 命令一 分组三 command3: 命令三 分组二 command2: 命令二

使用ShellCommandGroup注解

@ShellComponent(value = "自定义的命令") @ShellCommandGroup(value = "分组666") public class UserCommands { @ShellMethod(value = "命令一") public void command1() {} @ShellMethod(value = "命令二") public void command2() {} @ShellMethod(value = "命令三") public void command3() {} }

当输入help命令时显示:

shell:>help AVAILABLE COMMANDS Built-In Commands clear: Clear the shell screen. exit, quit: Exit the shell. help: Display help about available commands. history: Display or save the history of previously run commands script: Read and execute commands from a file. stacktrace: Display the full stacktrace of the last error. 分组666 command1: 命令一 command2: 命令二 command3: 命令三 shell:>
2.13. 覆盖和禁止内置命令

禁止所有内置命令:在依赖中剔除

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

禁止某一个特定命令:例如禁止help命令

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); }

覆盖内置命令:

public class MyClear implements Clear.Command { @ShellMethod("Clear the screen, only better.") public void clear() { // ... } }
2.14. 自定义命令提示,默认的是shell:>
@Component public class MyCommandShell implements PromptProvider { @Override public AttributedString getPrompt() { return new AttributedString("long : >", AttributedStyle.DEFAULT.foreground(AttributedStyle.RED)); } }

这样将会把shell:>替换为long:>。

欢迎关注一波微型公众号

最新回复(0)