美文网首页
使用Spring Shell 快速开发自己的命令交互窗口 - 草

使用Spring Shell 快速开发自己的命令交互窗口 - 草

作者: 王广帅 | 来源:发表于2022-04-17 15:53 被阅读0次

    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方法,在控制台就可以输入命令了:


    输入命令

    就是这么简单!!!,只需要两步:

    1. 在命令类上面添加注解:@ShellComponent
    2. 在方法上面添加注解:@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'
    

    快捷键使用

    1. ctrl + r 搜索输入过历史执行过的命令。减少重复的输入,提高操作效率。
    2. ctrl + a 跳转到行头输入
    3. ctrl + e 跳转到行尾输入
    4. 上下箭头 输入完命令名字之后,按上下箭头可以查阅之前输入过的参数命令。

    参数限制

    可以使用注解,对参数进入限制,防止用户输入错误,如下所示:

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

    相关文章

      网友评论

          本文标题:使用Spring Shell 快速开发自己的命令交互窗口 - 草

          本文链接:https://www.haomeiwen.com/subject/rzdlertx.html