Spring Boot 整合——使用Spring Shell开发java命令行工具

关于版本

依赖版本
springboot2.0.8.RELEASE
spring-shell-starter2.0.0.RELEASE

关于项目

本内容也是我尝试整理工作中接触过各种工具在springboot中使用的方法。下面介绍的所有方法都已经提供了测试用例。因为每个例子涉及代码较多,所以文章中只贴出了部分代码。全部的代码在这里gitee代码仓库

spring shell

Spring-shell是Spring提供的一个组件,此组件可以将Java中的代码逻辑封装为shell命令。通过启动服务器上的shell服务来通过命令方式执行java代码逻辑

简单的demo

依赖

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

声明shell命令

将java逻辑转换为命令需要@ShellComponent指定类为命令行组件、以及使用@ShellMethod指定方法为命令方法

/**
 * 基础命令
 */
@ShellComponent
public class BaseCommands {

    /**
     * 基础的命令
     * @param a
     * @param b
     * 输入:add 2 3
     * 输出:5
     * @return
     */
    @ShellMethod("输入两个整数,获取相加结果")
    public int add(int a, int b) {
        return a + b;
    }

}

启动服务并执行命令

服务启动后界面会出现shell:>,默认情况下方法名称即使命令名称,针对大小写的名称比如(getName)会将大写字母进行处理为:get-name

自定义命令名称

spring-shell默认使用方法名称作为命令的名称,我们可以在方法的注解中声明key属性来重命名其命令名称

    /**
     * 指定命令名称,此时不能通过add2访问命令
     * 默认情况下,方法名称即使命令名称,但是通过指定key值来表示命令的名称
     * 输入:sum 3 5
     * 输出:8
     * @return
     */
    @ShellMethod(value = "输入两个整数,获取相加结果", key = "sum")
    public int add2(int a, int b) {
        return a + b;
    }

创建不同参数的命令

spring-shell支持数字、字符串、数组类型的参数

@ShellComponent
public class ArgCommands {

    /**
     * 多参数 可以使用 --arg value 指定参数名称
     * 输入:echo-int --b 1 --a 2 --c 3
     * 输出:You said a=2, b=1, c=c
     *
     * 输入:echo-int 1 2 3
     * 输出:You said a=1, b=2, c=3
     * @return
     */
    @ShellMethod("通过明明参数名称,来指定输入的数据对应的参数名称")
    public String echoInt(int a, int b, int c) {
        return String.format("You said a=%d, b=%d, c=%d", a, b, c);
    }


    /**
     *
     * 输入:echo-int2 1 2  3
     * 输出:You said a=1, b=2, c=3
     *
     * 输入:echo-int2 -b 2 -a 3 --third 4
     * 输出:You said a=3, b=2, c=4
     * @return
     */
    @ShellMethod(value = "通过明明参数名称,强制的指定输入的数据对应的参数名称", prefix="-")
    public String echoInt2(int a, int b, @ShellOption("--third") int c) {
        return String.format("You said a=%d, b=%d, c=%d", a, b, c);
    }

    /**
     * 设置默认值
     * 输入:echo-string --who ' string is "name"'
     * 输出:input: string is "name"
     * @return
     */
    @ShellMethod("输入字符串")
    public String echoString(@ShellOption(defaultValue="World") String who) {
        return "input:" + who;
    }

    /**
     * 数组类参数
     * 输入:echo-array 2 3 4
     * 输出:input:2.0,3.0,4.0
     * @return
     */
    @ShellMethod("输入数组")
    public String echoArray(@ShellOption(arity=3) float[] numbers) {
        return "input:" + numbers[0] + "," + numbers[1] + "," + numbers[2];
    }

    /**
     * boolean类型参数,boolean 类型参数当你设置了参数会返回true
     * 输入:echo-boolean --force
     * 输出:input:true
     *
     * 输入:echo-boolean
     * 输出:input:false
     * @return
     */
    @ShellMethod("Terminate the system.")
    public String echoBoolean(boolean force) {
        return "input:" + force;
    }

}

针对参数的使用,spring-shell遵循shell参数输入的格式。

多参数命令的使用

对于多参数的方法,我们可以使用参数顺序来和参数进行一一对应也可以使用--argname来对应命令中对具体参数名称。

比如在echoInt2方法中使用下面两种输入方法都是可以转型的

echo-int2 1 2  3
You said a=1, b=2, c=3

echo-int2 -b 2 -a 3 --third 4
You said a=3, b=2, c=4

匹配参数的--前缀并非是固定的,可以通过在注解中添加prefix="-"来调整前缀内容。

进行校验的命令

关于命令的校验,主要有两种

针对参数的校验

spring-shell提供了对命令中输入的值内容的校验,下面例子中对输入的值就有了长度的要求。

    @ShellMethod("只能输入长度为8至40的内容")
    public String changePassword(@Size(min = 8, max = 40) String password) {
        return "Password successfully set to " + password;
    }

spring-shell使用javax.validation.constraints包中的注解进行校验。具体可以查看此包中的内容来尝试对命令内容进行限制。

针对整体状态的校验

spring-shell使用Availability提供了另外一种校验。

在调用某些命令的时候我们需要保证系统环境中有些状态是符合要求的,否则这个命令是禁止调用的,当然可以在方法中通过if来进行手动判断,但是spring-shell提供了另外一个方式

    private boolean connected;

    @ShellMethod("设置链接状态为true")
    public void connect() {
        connected = true;
    }

    /**
     * 输入:download
     * 输出:
     * Command 'download' exists but is not currently available because 没有进行链接
     * Details of the error have been omitted. You can use the stacktrace command to print the full stacktrace.
     *
     * 第二次输入
     * 输入:>connect
     * 输出:>download
     */
    @ShellMethod("必须链接后才能执行的方法")
    public void download() {
    }

    public Availability downloadAvailability() {
        return connected
                ? Availability.available()
                : Availability.unavailable("没有进行链接");
    }

connected没有连接的时候调用download命令是不合法的。所以在每次调用download命令时会执行命令名称+Availability的方法,在这个方法中可以根据执行结果输出对应的错误信息。

自定义校验方法

除了使用默认的规则匹配方法,我们还可以主动去指定校验方法,使用ShellMethodAvailability注解我们可以指定此命令的校验方法

    /**
     * 为命令指定校验方法
     */
    @ShellMethod("必须链接2链接后才能执行的方法")
    @ShellMethodAvailability("availabilityCheck")
    public void disconnect2() {
    }

为校验指定需要限制的命令

除了为命令指定校验、也可以为校验指定需要限制的命令。当有多个命令需要接受同一种限制的时候,无需在所有方法中都添加相关注解,而是可以直接在校验方法中补充注解关联命令

    /**
     * 为校验方法指定需要校验的命令
     * @return
     */
    @ShellMethodAvailability({"download2", "disconnect2"})
    public Availability availabilityCheck() {
        return connected2
                ? Availability.available()
                : Availability.unavailable("没有进行链接");
    }

为命令提供分组

help是spring-shell的一个内置命令,使用此命令可以查看spring-shell中所有存在的命令。如果我们的命令比较多的时候此时列出来的会是一个长长的清单,这个时候可以使用注释中的group属性对命令进行分组

/**
 * 为命令分组
 */
@ShellComponent
@ShellCommandGroup("分组的命令")
public class GroupCommands {

    @ShellMethod("命令1")
    public void download1() {
    }

    @ShellMethod("命令2")
    public void download2() {
    }

    @ShellMethod("命令3")
    public void download3() {
    }


    @ShellMethod(value = "命令4",group = "其他组")
    public void download4() {
    }

}

使用help查看的内容为:

其他组
        download4: 命令4

分组的命令
        download1: 命令1
        download2: 命令2
        download3: 命令3

自定义命令行颜色和链接信息

通过修改PromptProvider中的内容,可以修改shell等待时的内容和颜色.下面内容中通过设置名称和颜色来调整shell等待时的内容。

@Component
public class CustomPromptProvider implements PromptProvider {

    @Override
    public AttributedString getPrompt() {
        return new AttributedString("my-shell:>",
                AttributedStyle.DEFAULT.foreground(AttributedStyle.RED));
    }

}

内置命令

通过help可以查看spring-shell所有内置命令

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.

help:主要是查看spring-shell所有命令

clear:将清除屏幕

quit:(也别名为exit)会退出spring-shell并关闭关闭Spring应用程序上下文

script:允许指定一个本地文件来进行批命令处理

实现更多的功能

使用spirng-shell我们可以将一些java中的逻辑封装为shell命令。当然有些操作我们可以编写shell脚本来实现,但是使用spring-shell提供了这些需求的另外一种可能

查看当前时间

    @ShellMethod("查询当前时间")
    public String date() {
        LocalDateTime dateTime = LocalDateTime.now();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        return dateTime.format(formatter);
    }

克隆git代码

    @ShellMethod("获取指定仓库的分支")
    public String getBranch(String url){
        StringBuffer stringBuffer = new StringBuffer();
        try {
            Collection<Ref> refList = Git.lsRemoteRepository().setRemote(url).call();
            List<String> branchnameList = new ArrayList<>(4);
            for (Ref ref : refList) {
                String refName = ref.getName();
                if (refName.startsWith("refs/heads/")) {                       //须要进行筛选
                    String branchName = refName.replace("refs/heads/", "");
                    branchnameList.add(branchName);
                }
            }
            stringBuffer.append("共有分支" + branchnameList.size() + "个。");
            for (String item : branchnameList) {
                stringBuffer.append("[").append(item).append("]");
            }
        } catch (Exception e) {
            return "error";
        }
        return stringBuffer.toString();
    }

输出内容

shell:>get-branch https://gitee.com/daifyutils/springboot-samples.git 
共有分支1个。[master]

查看指定文件

    @ShellMethod("读取指定文件夹内容")
    public String cloneGit(String url){
        //克隆代码库命令
        CloneCommand cloneCommand = Git.cloneRepository();

        Git git= null;
        try {
            git = cloneCommand.setURI(url) //设置远程URI
                    .setBranch("master") //设置clone下来的分支
                    .setDirectory(new File("D:\\shell-git")) //设置下载存放路径
                    .call();
        } catch (GitAPIException e) {
            return "error";
        }
        return "finish";
    }

个人水平有限,上面的内容可能存在没有描述清楚或者错误的地方,假如开发同学发现了,请及时告知,我会第一时间修改相关内容。假如我的这篇内容对你有任何帮助的话,麻烦给我点一个赞。你的点赞就是我前进的动力。

  • 5
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
xterm.js是一个基于JavaScript的插件,用于在Web应用程序中实现终端效果。Spring Boot是一个Java框架,用于快速构建Web应用程序。可以结合xterm.js、Spring Boot和HTML来实现Shell终端效果。 要实现这个效果,首先需要在HTML页面中引入xterm.js的库文件和必要的样式表。可以通过CDN或者将相关文件下载到本地进行引入。 然后,在Spring Boot的后端代码中,可以使用WebSocket技术来与前端建立实时通信。可以使用Spring Boot提供的`@Controller`注解来处理WebSocket连接请求,并在连接建立之后与xterm.js进行交互。 在后端代码中,可以编写一个`ShellController`类来处理WebSocket连接和命令执行。在这个类中,可以使用`@OnOpen`注解来处理WebSocket连接建立事件,并在这个事件中创建一个新的`DefaultShell`对象,用于执行命令和返回结果。 `DefaultShell`类可以封装底层的Shell命令执行器,例如使用Java的`ProcessBuilder`类来执行Shell命令,并将结果返回给前端。在`DefaultShell`类中,可以定义一个`executeCommand`方法,用于执行命令,并通过WebSocket将结果发送给前端。 在前端代码中,可以使用xterm.js提供的API来创建一个终端对象,并通过WebSocket与后端进行通信。在页面加载完成时,可以调用xterm.js的`Terminal`构造函数来创建一个新的终端对象,并将其附加到页面上的指定元素上。 然后,在页面的JavaScript代码中,可以使用WebSocket对象与后端进行通信。当用户在终端中输入命令时,可以将命令传递给后端的WebSocket连接,并在收到结果后更新终端的显示。 总结来说,通过使用xterm.js、Spring Boot和HTML,可以实现一个具有终端效果的Shell界面。前端使用xterm.js提供的API创建终端对象,在页面的JavaScript代码中与后端通过WebSocket进行通信。后端使用Spring Boot来处理WebSocket连接请求,并通过Java的执行命令和返回结果。这样就可以在Web应用程序中实现一个类似于Shell终端的交互界面。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大·风

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值