Spring Batch 5作业无法自动启动问题求助(Spring Boot 3升级)
问题描述
将作业从Spring Boot 2升级到Spring Boot 3,同步升级Spring Batch至5版本后,作业不再自动启动。该作业以jar包形式运行(非定时/异步作业),此前Spring Boot 2版本使用以下命令可正常启动:
java -jar MyJobApp.jar --batch.input-file="/path/to/file/filename.xml" --spring.config.additional-location=file:/path/to/config/externalPropertyFile.yml
核心需求
- 自定义数据库表记录作业状态,不需要Spring Batch默认元数据表,希望将Batch元数据存入内存数据库,通过
JobListener持久化自定义数据。 - 已尝试
@EnableBatchProcessing声明式配置、继承DefaultBatchConfigurer重写getDataSource和getTransactionManager,也知道可以用CommandLineRunner结合JobLauncher手动启动,但认为这不是正确方式。 - 集成测试中通过
JobLauncherTestUtils使用SimpleJobLauncher可正常运行作业。
当前配置
- 主应用类:
@EnableConfigurationProperties(BatchProps::class, WebClientProps::class) @SpringBootApplication class MyJobApp fun main(args: Array<String>) { exitProcess(SpringApplication.exit(runApplication<MyJobApp>(*args))) }
application.yml配置:
spring: main: web-application-type: none application: name: MyJobApp batch: job: enabled: true
- Batch配置类:
@Configuration @EnableBatchProcessing(dataSourceRef = "batchDataSource", transactionManagerRef = "batchTransactionManager") class BatchConfig( private val reader: PackageDataReader, private val processor: PackageDataProcessor, private val writer: OrderWriter, ) { @Bean fun job(listener: JobNotificationListener, jobRepository: JobRepository, transactionManager: PlatformTransactionManager, ioStep: Step): Job = JobBuilder(JOB_NAME, jobRepository) .listener(listener) .flow(ioStep) .end() .build() @Bean fun ioStep(jobRepository: JobRepository, transactionManager: PlatformTransactionManager): Step = StepBuilder(STEP_NAME, jobRepository) .chunk<PackageData, List<OrderType>>(1, transactionManager) .reader(reader) .processor(processor) .writer(writer) .build() // 避免Spring Batch元数据表写入业务DB,使用内存H2存储 @Bean fun batchDataSource(): DataSource { return EmbeddedDatabaseBuilder().setType(EmbeddedDatabaseType.H2) .addScript("/org/springframework/batch/core/schema-h2.sql") .generateUniqueName(true).build() } @Bean fun batchTransactionManager(): JdbcTransactionManager? { return JdbcTransactionManager(batchDataSource()) } }
作业运行日志
2023-03-03T11:17:05.041+01:00 DEBUG 20592 --- [ main] MyJobApp : Running with Spring Boot v3.0.2, Spring v6.0.4 2023-03-03T11:17:05.041+01:00 INFO 20592 --- [ main] MyJobApp : The following 1 profile is active: "dev" 2023-03-03T11:17:05.611+01:00 INFO 20592 --- [ main] o.s.b.c.c.annotation.BatchRegistrar : Finished Spring Batch infrastructure beans configuration in 6 ms. 2023-03-03T11:17:07.133+01:00 INFO 20592 --- [ main] o.s.j.d.e.EmbeddedDatabaseFactory : Starting embedded database: url='jdbc:h2:mem:3df4e81c-eff0-45fc-a9f2-9b97f721b113;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=false', username='sa' 2023-03-03T11:17:07.433+01:00 INFO 20592 --- [ main] o.s.b.c.r.s.JobRepositoryFactoryBean : No database type set, using meta data indicating: H2 2023-03-03T11:17:07.499+01:00 INFO 20592 --- [ main] .c.a.BatchObservabilityBeanPostProcessor : No Micrometer observation registry found, defaulting to ObservationRegistry.NOOP 2023-03-03T11:17:07.513+01:00 INFO 20592 --- [ main] .c.a.BatchObservabilityBeanPostProcessor : No Micrometer observation registry found, defaulting to ObservationRegistry.NOOP 2023-03-03T11:17:07.519+01:00 INFO 20592 --- [ main] o.s.b.c.l.support.SimpleJobLauncher : No TaskExecutor has been set, defaulting to synchronous executor. 2023-03-03T11:17:07.743+01:00 INFO 20592 --- [ main] MyJobbApp : Started MyJobApp in 3.28 seconds (process running for 4.247) 2023-03-03T11:17:07.755+01:00 INFO 20592 --- [ main] o.s.j.d.e.EmbeddedDatabaseFactory : Shutting down embedded database: url='jdbc:h2:mem:3df4e81c-eff0-45fc-a9f2-9b97f721b113;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=false' Process finished with exit code 0
解决方案
核心原因
Spring Batch 5中,当使用@EnableBatchProcessing或继承DefaultBatchConfiguration时,Spring Boot的Batch自动配置会完全后退,不再自动触发作业启动逻辑。这就是作业不自动运行的根本原因。
解决步骤
方式一:保留@EnableBatchProcessing,手动恢复自动启动逻辑
如果需要自定义JobRepository的数据源(内存H2),同时希望保留自动启动行为,可以添加JobLauncherApplicationRunner Bean,它是Spring Boot原生的Batch作业自动启动组件:
在BatchConfig中添加以下代码:
@Bean fun jobLauncherApplicationRunner(jobLauncher: JobLauncher, job: Job, args: Array<String>): JobLauncherApplicationRunner { val runner = JobLauncherApplicationRunner(jobLauncher, job) // 解析命令行参数构建JobParameters val params = JobParametersBuilder() args.forEach { arg -> if (arg.startsWith("--batch.input-file=")) { val filePath = arg.substringAfter("--batch.input-file=") params.addString("inputFile", filePath) } // 可添加其他需要的参数 } runner.setJobParameters(params.toJobParameters()) return runner }
方式二:移除@EnableBatchProcessing,利用自动配置扩展自定义数据源
这种方式更贴合Spring Boot的自动配置理念,不需要手动处理作业启动逻辑,推荐使用:
- 移除
BatchConfig上的@EnableBatchProcessing注解 - 将Batch专属的数据源和事务管理器Bean名称改为
springBatchDataSource和springBatchTransactionManager——Spring Boot自动配置会自动识别这两个名称的Bean作为Batch的专属资源:
@Configuration class BatchConfig( private val reader: PackageDataReader, private val processor: PackageDataProcessor, private val writer: OrderWriter, ) { // 原job和ioStep Bean保留不变 @Bean fun springBatchDataSource(): DataSource { return EmbeddedDatabaseBuilder().setType(EmbeddedDatabaseType.H2) .addScript("/org/springframework/batch/core/schema-h2.sql") .generateUniqueName(true).build() } @Bean fun springBatchTransactionManager(): JdbcTransactionManager { return JdbcTransactionManager(springBatchDataSource()) } }
修改后,spring.batch.job.enabled=true的配置会正常生效,作业会自动启动,同时元数据会存入你定义的内存H2数据库。
验证说明
- 两种方式都能确保Batch元数据不会写入业务数据库
- 集成测试中
JobLauncherTestUtils的使用不受配置变更影响 - 方式二无需额外编写启动逻辑,维护成本更低
内容的提问来源于stack exchange,提问作者StackCanary
相关产品推荐
相关产品推荐

