Spring Shell
有时候,为了方便开发和测试服务器,并不需要一个漂亮的用户界面,使用一个简单的命令窗口即可。如下所示:
交互式命令窗口
这里介绍一个快速,方便,易用,简单的交互式命令窗口开发组件-Spring Shell
没错,又是spring 生态中的。
源码地址
https://gitee.com/wgslucky/spring-shell-demo
创建项目
本项目是使用Eclipse作为开发的IDE,同样,直接导入到Idea之中也可以使用。使用的JDK需要是1.8或更高的版本,我测试过在JDK11上也可以使用。
在eclipse中创建maven项目:spring-shell-demo,然后在pom.xml中添加如下依赖:
<parent>
<!-- 添加spring boot 父pom依赖,这个不能少,spring shell官方的文档中没有写 -->
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.6.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.shell</groupId>
<artifactId>spring-shell-starter</artifactId>
<version>2.0.0.RELEASE</version>
</dependency>
</dependencies>
添加启动类
@SpringBootApplication
public class SpringShellDemo {
public static void main(String[] args) {
SpringApplication app = new SpringApplication(SpringShellDemo.class);
app.setBannerMode(Mode.OFF);
app.setWebApplicationType(WebApplicationType.NONE);
app.run(args);
}
}
到此,项目创建完成。下面就是见证奇迹的时候了。
快速添加一条命令
创建一个命令类,类名可以自定义:
@ShellComponent
public class MyCommand {
@ShellMethod("连接服务器,格式:connect ip port")
public String connect(String ip,int port) {
return String.format("连接服务成功:%s:%s", ip,port);
}
}
然后,运行项目的启动类main方法,在控制台就可以输入命令了:
输入命令
就是这么简单!!!,只需要两步:
- 在命令类上面添加注解:@ShellComponent
- 在方法上面添加注解:@ShellMethod
项目打包和运行
在项目的pom.xml所在的目录上执行
mvn clean package
然后在target的目录下面生成了运行包:spring-shell-demo-0.0.1-SNAPSHOT.jar
使用下面的命令可以直接运行此包:
java -jar spring-shell-demo-0.0.1-SNAPSHOT.jar
这样就可以在IDE外面随时使用了。
使用小技巧
现在已经可以轻松的添加自己想要的交互命令了,交互命令的最重要的职责就是接收用户输入的参数,剩下如何执行命令就是自己的业务逻辑了。下面介绍一些使用小技巧。
内置命令
Spring Shell内容了一些常用的命令,可以直接使用,可以在运行的命令窗口中输入help,快速查看这些命令:
shell:>help
AVAILABLE COMMANDS
Built-In Commands
clear: Clear the shell screen. (清屏)
exit, quit: Exit the shell. (退出)
help: Display help about available commands. (帮忙,查看支持的所有命令)
script: Read and execute commands from a file. (从文件中读取命令并执行)
stacktrace: Display the full stacktrace of the last error.
(显示异常栈,一般遇到错误时,使用它快速查看异常栈)
添加命令描述
可以在@ShellMethod注解中添加对此命令的描述,这样在使用help命令时,就可以看到这些描述,明白命令如何使用,如上面的第一个命令的例子,在命令窗口中输入help可以看到:
My Command
connect: 连接服务器,格式:connect ip port
自定义命令的名字
默认情况下是不需要自定义命令的名字的,它会使用执行这个命令的方法名转化相应的窗口命令名字,如果是多个单词,使用-分开。比如connect方法,它的命令名字就是connect,如果方法名是sayHello,那么它的命令名字就是:say-hello
如果想要自定义命令名字,可以在@ShellMethod注解中添加:
@ShellMethod(value = "登陆服务器,格式:login-server playerId",key = "login-server")
public String login(String playerId) {
return "登陆成功:" + playerId;
}
修改提示符
在spring shell运行时,默认的命令提示符是:shell:> 有时候,看着别扭,如果能修改为自定义的提示符就好。这个可以修改,需要添加一个新的类:
@Service
public class CustomPromptProvider implements PromptProvider{
@Override
public AttributedString getPrompt() {
return new AttributedString("xinyues-client:>");
}
}
这样重新打包运行,输入的命令提示符就变成了 xinyues-client:>
了
带参数名输入命令参数
在输入命令时,如果不使用命令参数名字,那么参数的顺序必须和方法中定义的参数顺序一致。如果想使顺序不同,可以添加参数名称,如下所示:
xinyues-client:>connect --port 8888 --ip localhost
连接服务成功:localhost:8888
xinyues-client:>
参数需要两个横扛(--)。
添加默认参数值
有时候,一些命令可以简化一下,如果不输入参数的话,就使用参数的默认值。如下所示:
@ShellMethod("连接服务器,格式:connect ip port")
public String connectDefault(@ShellOption(defaultValue =
"localhost")String ip,@ShellOption(defaultValue = "8080")int port) {
return String.format("连接服务成功:%s:%s", ip,port);
}
在参数上面使用了一个新的注解:@ShellOption
使用命令时可以直接输入命令名,而不需要输入参数:
xinyues-client:>connect-default
连接服务成功:localhost:8080
xinyues-client:>
使用数组参数
有时候,为了输入方便,不想定义太多的参数变量,或者参数是一个数组数据时,可以使用下面这种方式:
@ShellMethod("Add Numbers.")
public float add(@ShellOption(arity=3) float[] numbers) {
return numbers[0] + numbers[1] + numbers[2];
}
输入的参数带空格时
默认情况下,spring shell是以空格区分多个参数的,如果一个参数是多个单词,且有空格,就不能直接输入了,可以使用双引号或单引号,比如下面这个命令:
@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!"
命令自动补全功能
可以使用tab键,自动补命令名字,和使用linux命令类似,也可以使用tab自动补全参数名字。
命令换行输入
有时候,命令参数太多,一行可能输入不完,可以在一行的末尾添加 \ ,然后另起一行输入命令:
shell:>register module --type source --name foo \
> --uri file:///tmp/bar
Successfully registered module 'source:foo'
快捷键使用
- ctrl + r 搜索输入过历史执行过的命令。减少重复的输入,提高操作效率。
- ctrl + a 跳转到行头输入
- ctrl + e 跳转到行尾输入
- 上下箭头 输入完命令名字之后,按上下箭头可以查阅之前输入过的参数命令。
参数限制
可以使用注解,对参数进入限制,防止用户输入错误,如下所示:
@ShellMethod("Change password.")
public String changePassword(@Size(min = 8, max = 40) String password) {
return "Password successfully set to " + password;
}
如果输入的不符合要求,会有提示:
shell:>change-password hello
The following constraints were not met:
--password string : size must be between 8 and 40 (You passed 'hello')
更多可以使用的注解,请参阅:https://beanvalidation.org/2.0/spec/#builtinconstraints
命令有效性检测
有时候,多个命令之间可能有某种依赖性,比如这样一个场景,客户端有一个下载download命令,但是在使用下载命令的时候,必须先connect成功。可以这样检测download命令是否可用:
@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() {
[...]
}
// 注意,这里方法的命名是命令名 + Availability
public Availability downloadAvailability() {
return connected
? Availability.available()
: Availability.unavailable("you are not connected");
}
}
这样,如果用户没有使用connect命令,而直接使用download命令,就会提示:
xinyues-client:>download
�[31mCommand 'download' exists but is not currently available because you are not connected�[0m
�[31mDetails of the error have been omitted. You can use the �[1mstacktrace�[22m command to print the full stacktrace.�[0m
xinyues-client:>
上面这个检测方法是命名是有规则的必须是命令名 + Availability;另一种方式是使用注解指定检测的方法名:
@ShellMethod("Download the nuclear codes.")
@ShellMethodAvailability("availabilityCheck")
public void download() {
[...]
}
public Availability availabilityCheck() {
return connected
? Availability.available()
: Availability.unavailable("you are not connected");
}
网友评论