入门指南
如果你刚刚开始使用 Spring Cloud Task,你应该阅读本节。在这里,我们将回答基本的“是什么?”、“怎么做?”和“为什么?”问题。我们首先对 Spring Cloud Task 进行一个温和的介绍。然后,我们将构建一个 Spring Cloud Task 应用程序,并在此过程中讨论一些核心原则。
介绍 Spring Cloud Task
Spring Cloud Task 使得创建短生命周期的微服务变得简单。它提供了让短生命周期的 JVM 进程在生产环境中按需执行的能力。
系统要求
你需要安装 Java(Java 17 或更高版本)。
数据库需求
Spring Cloud Task 使用关系型数据库来存储已执行任务的结果。虽然你可以在没有数据库的情况下开始开发任务(任务的状态会作为任务仓库更新的一部分进行记录),但在生产环境中,你希望使用受支持的数据库。Spring Cloud Task 目前支持以下数据库:
-
DB2
-
H2
-
HSQLDB
-
MySql
-
Oracle
-
Postgres
-
SqlServer
开发你的第一个 Spring Cloud Task 应用程序
一个很好的起点是从一个简单的“Hello, World!”应用程序开始,因此我们创建了Spring Cloud Task的等价物,以突出该框架的特性。大多数IDE对Apache Maven都有良好的支持,因此我们将其作为该项目的构建工具。
spring.io 网站包含许多使用 Spring Boot 的“入门指南”。如果你需要解决特定问题,请先查看这些指南。你可以通过访问 Spring Initializr 并创建一个新项目来简化以下步骤。这样做会自动生成一个新的项目结构,让你可以立即开始编码。我们建议你尝试使用 Spring Initializr,以便熟悉它。
使用 Spring Initializr 创建 Spring Task 项目
现在我们可以创建并测试一个应用程序,它将 Hello, World!
打印到控制台。
为此:
-
访问 Spring Initialzr 网站。
-
创建一个新的 Maven 项目,Group 名称为
io.spring.demo
,Artifact 名称为helloworld
。 -
在 Dependencies 文本框中,输入
task
,然后选择带有Spring Cloud
标签的Task
依赖项。 -
在 Dependencies 文本框中,输入
h2
,然后选择带有SQL
标签的H2
依赖项。 -
点击 Generate Project 按钮。
-
-
解压
helloworld.zip
文件,并将项目导入到你喜欢的 IDE 中。
编写代码
为了完成我们的应用程序,我们需要用以下内容更新生成的 HelloworldApplication
,以便它启动一个任务。
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.task.configuration.EnableTask;
import org.springframework.context.annotation.Bean;
@SpringBootApplication
@EnableTask
public class HelloworldApplication {
@Bean
public ApplicationRunner applicationRunner() {
return new HelloWorldApplicationRunner();
}
public static void main(String[] args) {
SpringApplication.run(HelloworldApplication.class, args);
}
public static class HelloWorldApplicationRunner implements ApplicationRunner {
@Override
public void run(ApplicationArguments args) throws Exception {
System.out.println("Hello, World!");
}
}
}
虽然看起来很小,但实际上发生了很多事情。有关 Spring Boot 的具体内容,请参阅 Spring Boot 参考文档。
现在我们可以打开 src/main/resources
目录下的 application.properties
文件。我们需要在 application.properties
文件中配置两个属性:
-
application.name
:用于设置应用程序名称(该名称会转换为任务名称) -
logging.level
:用于将 Spring Cloud Task 的日志级别设置为DEBUG
,以便查看当前的运行情况。
以下示例展示了如何同时进行这两项操作:
logging.level.org.springframework.cloud.task=DEBUG
spring.application.name=helloWorld
任务自动配置
当包含 Spring Cloud Task Starter 依赖项时,Task 会自动配置所有所需的 bean 以启动其功能。此配置的一部分会注册 TaskRepository
及其使用所需的基础设施。
在我们的演示中,TaskRepository
使用了一个嵌入式 H2 数据库来记录任务的结果。这个 H2 嵌入式数据库并不是生产环境中的实际解决方案,因为一旦任务结束,H2 数据库就会消失。然而,为了快速入门,我们可以在示例中使用它,并在日志中回显该存储库中更新的内容。在配置部分(本文档后面部分),我们介绍了如何自定义 Spring Cloud Task 提供的组件的配置。
当我们的示例应用程序运行时,Spring Boot 会启动我们的 HelloWorldApplicationRunner
并将“Hello, World!”消息输出到标准输出。TaskLifecycleListener
会在存储库中记录任务的开始和结束。
主方法
main
方法是任何 Java 应用程序的入口点。我们的 main
方法委托给 Spring Boot 的 SpringApplication 类。
ApplicationRunner 应用启动器
Spring 提供了多种方式来引导应用程序的逻辑。Spring Boot 通过其 *Runner
接口(CommandLineRunner
或 ApplicationRunner
)提供了一种有组织且便捷的方法来实现这一点。一个行为良好的任务可以通过使用这两个 runner 中的任意一个来引导任何逻辑。
任务的生命周期从 *Runner#run
方法执行之前开始,到所有方法执行完毕结束。Spring Boot 允许应用程序使用多个 *Runner
实现,Spring Cloud Task 也是如此。
任何不是通过 CommandLineRunner
或 ApplicationRunner
启动的处理(例如使用 InitializingBean#afterPropertiesSet
)都不会被 Spring Cloud Task 记录。
运行示例
此时,我们的应用程序应该可以正常运行。由于这是一个基于 Spring Boot 的应用程序,我们可以从命令行运行它。只需在应用程序的根目录下使用 $ ./mvnw spring-boot:run
命令即可,如下例所示(包括其输出):
$ mvn clean spring-boot:run
....... . . .
....... . . . (Maven log output here)
....... . . .
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v3.2.1)
2024-01-04T10:07:01.102-06:00 INFO 18248 --- [helloWorld] [ main] i.s.d.helloworld.HelloworldApplication : Starting HelloworldApplication using Java 21.0.1 with PID 18248 (/Users/dashaun/fun/dashaun/spring-cloud-task/helloworld/target/classes started by dashaun in /Users/dashaun/fun/dashaun/spring-cloud-task/helloworld)
2024-01-04T10:07:01.103-06:00 INFO 18248 --- [helloWorld] [ main] i.s.d.helloworld.HelloworldApplication : No active profile set, falling back to 1 default profile: "default"
2024-01-04T10:07:01.526-06:00 INFO 18248 --- [helloWorld] [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Starting...
2024-01-04T10:07:01.626-06:00 INFO 18248 --- [helloWorld] [ main] com.zaxxer.hikari.pool.HikariPool : HikariPool-1 - Added connection conn0: url=jdbc:h2:mem:3ad913f8-59ce-4785-bf8e-d6335dff6856 user=SA
2024-01-04T10:07:01.627-06:00 INFO 18248 --- [helloWorld] [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Start completed.
2024-01-04T10:07:01.633-06:00 DEBUG 18248 --- [helloWorld] [ main] o.s.c.t.c.SimpleTaskAutoConfiguration : Using org.springframework.cloud.task.configuration.DefaultTaskConfigurer TaskConfigurer
2024-01-04T10:07:01.633-06:00 DEBUG 18248 --- [helloWorld] [ main] o.s.c.t.c.DefaultTaskConfigurer : No EntityManager was found, using DataSourceTransactionManager
2024-01-04T10:07:01.639-06:00 DEBUG 18248 --- [helloWorld] [ main] o.s.c.t.r.s.TaskRepositoryInitializer : Initializing task schema for h2 database
2024-01-04T10:07:01.772-06:00 DEBUG 18248 --- [helloWorld] [ main] o.s.c.t.r.support.SimpleTaskRepository : Creating: TaskExecution{executionId=0, parentExecutionId=null, exitCode=null, taskName='helloWorld', startTime=2024-01-04T10:07:01.757268, endTime=null, exitMessage='null', externalExecutionId='null', errorMessage='null', arguments=[]}
2024-01-04T10:07:01.785-06:00 INFO 18248 --- [helloWorld] [ main] i.s.d.helloworld.HelloworldApplication : Started HelloworldApplication in 0.853 seconds (process running for 1.029)
Hello, World!
2024-01-04T10:07:01.794-06:00 DEBUG 18248 --- [helloWorld] [ main] o.s.c.t.r.support.SimpleTaskRepository : Updating: TaskExecution with executionId=1 with the following {exitCode=0, endTime=2024-01-04T10:07:01.787112, exitMessage='null', errorMessage='null'}
2024-01-04T10:07:01.799-06:00 INFO 18248 --- [helloWorld] [ionShutdownHook] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Shutdown initiated...
2024-01-04T10:07:01.806-06:00 INFO 18248 --- [helloWorld] [ionShutdownHook] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Shutdown completed.
....... . . .
....... . . . (Maven log output here)
....... . . .
前面的输出中有三行是我们感兴趣的:
-
SimpleTaskRepository
记录了在TaskRepository
中创建条目的日志。 -
我们的
ApplicationRunner
的执行,通过输出 “Hello, World!” 来演示。 -
SimpleTaskRepository
记录了任务在TaskRepository
中完成的日志。
一个简单的任务应用程序可以在 Spring Cloud Task 项目的示例模块中找到,点击这里 查看。