1. 概述
Spring Boot 以简化 Web 应用开发而闻名,但它的能力远不止于此。它还提供了许多适用于非 Web 场景的工具。
本文将演示如何使用 Kotlin 编写一个基于控制台的 Spring Boot 应用,核心是使用 CommandLineRunner
接口来实现启动后执行逻辑。
2. 依赖配置
要创建一个 Spring Boot 控制台应用,我们只需要引入 spring-boot-starter
即可。以下是使用 Gradle 和 Maven 的配置方式:
Gradle:
implementation("org.springframework.boot:spring-boot-starter")
Maven:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
3. CommandLineRunner 接口
CommandLineRunner
是一个函数式接口,它定义了一个 run
方法,接收原始的 String[]
参数。Spring Boot 在启动完成后会自动调用所有实现了该接口的 Bean 的 run
方法。
@FunctionalInterface
public interface CommandLineRunner {
void run(String... args) throws Exception;
}
接下来我们让主类实现这个接口:
@SpringBootApplication
class SpringBootConsoleApplication : CommandLineRunner {
private val log = LoggerFactory.getLogger(SpringBootConsoleApplication::class.java)
override fun run(vararg args: String?) {
args.forEach { log.info("Application args: $it") }
}
}
fun main(args: Array<String>) {
runApplication<SpringBootConsoleApplication>(*args)
}
运行时传入参数 hello
,控制台会输出:
INFO 61619 --- [main] c.b.c.SpringBootConsoleApplicationKt : Starting SpringBootConsoleApplicationKt
INFO 61619 --- [main] c.b.c.SpringBootConsoleApplicationKt : No active profile set, falling back to 1 default profile: "default"
INFO 61619 --- [main] c.b.c.SpringBootConsoleApplicationKt : Started SpringBootConsoleApplicationKt in 1.153 seconds (JVM running for 1.967)
INFO 61619 --- [main] c.b.c.SpringBootConsoleApplication : Application args: hello
可以看到,run()
方法是在 Spring Boot 启动完成后执行的。
4. 与用户交互(读取输入)
Kotlin 提供了多种方式从控制台读取输入,其中一种简单的方式是使用 readlnOrNull()
方法:
override fun run(vararg args: String?) {
log.info("Please type your name:")
val name = readlnOrNull()
log.info("Hello $name. This is a Spring Boot Console Application")
}
运行后程序会等待用户输入:
INFO 62997 --- [main] c.b.c.SpringBootConsoleApplicationKt : Starting SpringBootConsoleApplicationKt using Java 17.0.4 on Fabios-MacBook-Pro.local with PID 62997 (/Users/fabiomiyasato/dev/git/kotlin-tutorials/spring-boot-kotlin-2/target/classes started by fabiomiyasato in /Users/fabiomiyasato/dev/git/kotlin-tutorials/spring-boot-kotlin-2)
INFO 62997 --- [main] c.b.c.SpringBootConsoleApplicationKt : No active profile set, falling back to 1 default profile: "default"
INFO 62997 --- [main] c.b.c.SpringBootConsoleApplicationKt : Started SpringBootConsoleApplicationKt in 1.217 seconds (JVM running for 1.687)
INFO 62997 --- [main] c.b.c.SpringBootConsoleApplication : Please type your name:
输入后按回车,程序继续执行并结束:
new user
INFO 62997 --- [main] c.b.c.SpringBootConsoleApplication : Hello new user. This is a Spring Boot Console Application
5. 多个 CommandLineRunner 的执行顺序
大多数控制台应用只需要一个 CommandLineRunner
实现。如果需要多个,推荐将它们定义为 @Component
而不是放在主类中。
此时可以使用 Spring 的 @Order
注解来控制执行顺序:
@Component
@Order(0)
class CommandLineFirstComponent : CommandLineRunner {
private val log = LoggerFactory.getLogger(CommandLineFirstComponent::class.java)
override fun run(vararg args: String?) {
log.info(CommandLineFirstComponent::class.simpleName)
}
}
第二个组件:
@Component
@Order(1)
class CommandLineSecondComponent : CommandLineRunner {
private val log = LoggerFactory.getLogger(CommandLineSecondComponent::class.java)
override fun run(vararg args: String?) {
log.info(CommandLineSecondComponent::class.simpleName)
}
}
这两个组件都实现了 CommandLineRunner
接口,并使用了 @Component
注解,以便 Spring 自动注册为 Bean。
运行后输出如下:
INFO 62516 --- [main] c.b.c.SpringBootConsoleApplicationKt : Starting SpringBootConsoleApplicationKt
INFO 62516 --- [main] c.b.c.SpringBootConsoleApplicationKt : Started SpringBootConsoleApplicationKt in 1.182 seconds (JVM running for 1.668)
INFO 62516 --- [main] c.b.c.CommandLineFirstComponent : CommandLineFirstComponent
INFO 62516 --- [main] c.b.c.CommandLineSecondComponent : CommandLineSecondComponent
✅ 可以看到 CommandLineFirstComponent
确实先于 CommandLineSecondComponent
执行。
6. 总结
控制台应用在很多场景下都非常实用。本文介绍了如何使用 Spring Boot 构建 Kotlin 控制台应用,并利用 CommandLineRunner
实现启动逻辑。
虽然 Spring Boot 本身是为 Web 场景设计的,但在非 Web 场景下也能发挥其依赖注入、组件管理等优势。
⚠️ 如果你计划构建一个更复杂的命令行接口(CLI),建议考虑使用 Spring Shell,它提供了更结构化的注解方式来定义命令。
完整的源码可在 GitHub 上找到。