Spring Shell 4.0.3 与 3.4.3 发布:动手写一个可交互的命令行应用

2026-06-11 27 预计阅读时间: 1 分钟
来源: spring.io AI 摘要 Original link

Disclaimer: This article is an AI-assisted summary. Read it together with the original source when precision matters. The summary may omit context, version differences, or edge cases and is not official documentation.

预计阅读时间:7 分钟

Spring Shell 项目近日同时推送了两个维护版本——4.0.3 和 3.4.3,分别对应 Spring Shell 4.x(基于 Spring Boot 3.x)和 3.x(兼容 Spring Boot 2.x)两条线。对于已经在用 Spring Shell 的项目,这意味着常规的缺陷修复与依赖对齐;而对于还没接触过它的人,这恰好是个好时机:写一个交互式 CLI 工具,远比你想的简单。

Spring Shell 解决什么问题

Java 生态里做命令行工具,传统路径是 args4jpicocliJCommander 这类解析库——它们能处理参数,但不会帮你做交互循环、命令注册、补全提示、输出格式化这些"壳"的事情。Spring Shell 把这些全包了:

  • 自动发现 @ShellComponent 并注册为可用命令
  • 内置 REPL 循环,用户敲完一条命令后继续等待下一条
  • TAB 补全、命令历史、彩色输出
  • 与 Spring 生态无缝整合(依赖注入、配置绑定、条件装配)

本质上,它让你用写 REST Controller 的方式写 CLI 命令。

快速起步:一个能跑的项目

下面用 Spring Shell 4.x(Spring Boot 3.x)搭一个最小可运行项目。如果你还在 Spring Boot 2.x,把依赖版本换成 3.4.3 即可,代码本身无差别。

项目依赖

Maven pom.xml 关键部分:

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>3.4.1</version>
</parent>

<dependencies>
    <!-- Spring Shell 核心 -->
    <dependency>
        <groupId>org.springframework.shell</groupId>
        <artifactId>spring-shell-starter</artifactId>
        <version>4.0.3</version>
    </dependency>
</dependencies>

Gradle 用户对应写法:

dependencies {
    implementation 'org.springframework.shell:spring-shell-starter:4.0.3'
}

注意spring-shell-starter 已经包含了 Spring Boot 自动配置和内置的 REPL 引擎,不需要额外加 spring-boot-starter

写两个命令

package com.example.cli;

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

@ShellComponent
public class GreetCommands {

    @ShellMethod(value = "向某人打招呼", key = "hello")
    public String hello(
            @ShellOption(defaultValue = "World") String name,
            @ShellOption(help = "重复次数", defaultValue = "1") int count) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < count; i++) {
            sb.append("Hello, ").append(name).append("!\n");
        }
        return sb.toString();
    }

    @ShellMethod(value = "计算两数之和", key = "add")
    public int add(int a, int b) {
        return a + b;
    }
}

启动类

package com.example.cli;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class CliApplication {
    public static void main(String[] args) {
        SpringApplication.run(CliApplication.class, args);
    }
}

运行

mvn spring-boot:run

启动后你会进入交互式 shell:

shell:>hello --name Alice --count 3
Hello, Alice!
Hello, Alice!
Hello, Alice!

shell:>add 7 15
22

shell:>help
AVAILABLE COMMANDS

add: 计算两数之和
hello: 向某人打招呼
help: 显示帮助
...

TAB 补全也直接可用——输入 he 再按 TAB,自动补全为 hello;输入 --n 按 TAB,补全为 --name

进阶:让命令真正有用

上面是最小骨架。真实项目里,你通常需要注入 Service、读取配置、处理异常。Spring Shell 的命令类就是普通的 Spring Bean,一切注入规则照旧:

@ShellComponent
public class DbCommands {

    private final UserRepository userRepo;

    public DbCommands(UserRepository userRepo) {
        this.userRepo = userRepo;
    }

    @ShellMethod(value = "按邮箱查找用户", key = "find-user")
    public String findByEmail(@ShellOption String email) {
        return userRepo.findByEmail(email)
                .map(u -> u.getName() + " | " + u.getRole())
                .orElse("未找到: " + email);
    }

    @ShellMethod(value = "列出所有用户", key = "list-users")
    public String listUsers() {
        List<User> users = userRepo.findAll();
        if (users.isEmpty()) {
            return "暂无用户数据";
        }
        return users.stream()
                .map(u -> String.format("%-20s %-10s %s", u.getName(), u.getRole(), u.getEmail()))
                .collect(Collectors.joining("\n"));
    }
}

不需要额外配置——只要 UserRepository 是 Spring Bean,自动注入就生效。

3.x 与 4.x 的选择

这次双线发布,核心区别在于底层 Spring Boot 版本:

维度 Spring Shell 3.4.3 Spring Shell 4.0.3
Spring Boot 2.x 3.x
Java 最低版本 8+ 17+
Jakarta / Javax javax jakarta
长期维护 收窄,仅修复 主线,持续演进

选择建议

  • 新项目直接用 4.0.3 + Spring Boot 3.x,没有理由走旧线。
  • 已有 Spring Boot 2.x 项目:如果只是内部运维工具、短期不改,留在 3.4.3 即可;如果计划整体迁移到 Boot 3.x,顺手升到 4.0.3。
  • 两条线的命令编写方式完全一致,迁移成本几乎为零——换依赖版本、改 javaxjakarta(如果用了),其余代码不动。

上手检查清单

把 Spring Shell 引入项目前,过一遍这几项:

  1. Java 版本对齐——4.x 要求 17+,3.x 要求 8+,和你的 Boot 版本一致。
  2. 排除 Web 依赖——CLI 项目通常不需要 spring-boot-starter-web,同时引入会导致端口冲突或启动两个上下文。如果确实需要两者共存,用 @Profile 或条件装配隔离。
  3. 非交互模式——加 -- 参数可以直接执行单条命令后退出,适合 CI 脚本:java -jar app.jar -- add 3 5
  4. 自定义退出命令——默认用 exit,可以通过 ShellCustomizer 改成 quit 或其他关键词。
  5. 输出美化——返回 String 是最简单的;需要表格、进度条等富输出,可用 Terminal 对象直接操作 ANSI 序列。

Spring Shell 把"写一个命令行工具"的门槛压到了和"写一个 REST 接口"同一水平。4.0.3 和 3.4.3 的发布本身是常规维护,但它们提醒你:这条线在持续走,你的运维脚本、数据诊断工具、内部 CLI,值得用更规范的方式来做。


相关推荐