領先一步
VMware 提供培訓和認證,助力您快速發展。
瞭解更多它終於來了!Spring Batch 5.0 現已從 Maven Central 全面推出。Spring Batch 5 是兩年工作的結晶,包含了 50 多位貢獻者提供的數十項改進、功能和錯誤修復!我謹代表團隊,感謝所有在這巨大版本釋出中做出貢獻的人!
這篇部落格文章介紹了這個新一代框架的主要亮點。你可以在版本說明中找到所有變更的詳細資訊,並在遷移指南中找到升級說明。
Spring Batch 遵循 Spring Framework 在 Java 版本和第三方依賴方面的基線。在 Spring Batch 5 中,Spring Framework 版本已升級到 Spring Framework 6,這需要 Java 17。因此,Spring Batch 的 Java 版本要求也提高到了 Java 17。
為了繼續與 Spring Batch 使用的第三方庫的受支援版本整合,Spring Batch 5 將所有依賴項更新到以下版本:
此版本還標誌著向以下版本的遷移:
為使用 GraalVM native-image 編譯器將 Spring Batch 應用程式編譯為原生可執行檔案提供支援的工作始於 v4.2,並在 v4.3 中作為實驗性功能釋出。
在此版本中,透過提供必要的提前處理(AOT)和執行時提示,原生支援得到了顯著改進,可以使用 GraalVM 原生編譯 Spring Batch 應用程式。
在這篇部落格文章中,我們想與你分享我們在該領域進行的一些基準測試。以下基準測試基於 Spring Native 示例專案中的 batch 示例。這些基準測試比較了使用常規 JVM 和作為原生可執行檔案執行同一批處理應用程式的啟動時間和總執行時間。

這裡顯示的值是使用以下軟體和硬體配置執行示例 10 次的平均值:
這些基準測試表明,原生 Spring Batch 應用程式的啟動速度快了兩倍,執行時速度快了近十倍!這對雲原生批處理工作負載來說絕對是一個遊戲規則的改變者!
隨著升級到 Micrometer 1.10,除了批處理指標外,你現在還可以獲得批處理跟蹤。Spring Batch 會為每個作業建立一個 Span,併為作業中的每個步驟建立一個 Span。這些跟蹤元資料可以在諸如 Zipkin 之類的儀表板上收集和檢視。
此外,此版本引入了新的指標:
job.launch.count: 這是一個 Counter,報告透過 JobLauncher 啟動了多少個作業。這對於在持續執行的 JVM 中排程和執行批處理作業的環境來說非常方便。step.active: 這個型別為 LongTaskTimer 的指標報告特定作業中當前活動的(即正在執行的)步驟。當一個作業包含多個步驟並且想知道當前正在處理哪個步驟時,這個指標非常有用。除了 Spring Batch 已在執行上下文持久化的執行時資訊(如步驟型別、重啟標誌等)之外,此版本在執行上下文添加了一個重要細節,即用於序列化該上下文的 Spring Batch 版本。
雖然這看似一個細節,但在除錯與執行上下文序列化和反序列化相關的升級問題時,它具有巨大的附加價值。
在此版本中,DefaultExecutionContextSerializer 已更新為將上下文序列化/反序列化為 Base64。
此外,透過 @EnableBatchProcessing 或 DefaultBatchConfiguration 配置的預設 ExecutionContextSerializer 已從 JacksonExecutionContextStringSerializer 更改為 DefaultExecutionContextSerializer。現在對 Jackson 的依賴是可選的。為了使用 JacksonExecutionContextStringSerializer,應將 jackson-core 新增到 classpath 中。
在此版本中,對 SystemCommandTasklet 進行了重新審視,並進行了如下更改:
引入了一個名為 CommandRunner 的新策略介面,以將命令執行與 Tasklet 執行解耦。預設實現是 JvmCommandRunner,它使用 java.lang.Runtime#exec API 執行系統命令。可以實現此介面以使用任何其他 API 執行系統命令。
執行命令的方法現在接受一個表示命令及其引數的 String 陣列。不再需要對命令進行分詞或進行任何預處理。此更改使 API 更加直觀,並且更不容易出錯。
直到版本 4,Spring Batch 僅支援 4 種可用作作業引數的型別,分別是 long、double、String 和 Date。雖然這方便了框架端簡化作業引數處理,但對使用者端來說卻帶來了限制。例如,如果想使用 boolean 或自定義型別作為作業引數怎麼辦?這需要在 Spring Batch 中進行額外的轉換,轉換為受支援的型別之一,這很快就給使用者帶來了不便。
在此版本中,我們添加了支援將任何型別用作作業引數。此改進背後的主要變化如下:
---public class JobParameter implements Serializable {
+++public class JobParameter<T> implements Serializable {
--- private Object parameter;
+++ private T value;
--- private ParameterType parameterType;
+++ private Class<T> type;
}
此更改會影響作業引數在資料庫中的持久化方式。請檢視遷移指南瞭解資料庫 schema 更改。引數型別的完全限定名現在作為 String 持久化,引數值也是如此。字串文字使用標準的 Spring 轉換服務轉換為引數型別。可以透過任何必需的轉換器來豐富標準轉換服務,以將使用者特定型別與字串文字相互轉換。
v4 中作業引數的預設表示法規定如下:
[+|-]parameterName(parameterType)=parameterValue
其中 parameterType 是 [string,long,double,date] 之一。雖然這種表示法很簡潔,但它存在一些限制,因為它與環境變數不太相容,並且對 Spring Boot 不太友好。
在 v5 中,我們將預設表示法更改如下:
parameterName=parameterValue,parameterType,identificationFlag
其中 parameterType 是引數型別的完全限定名。例如,以下鍵/值對:
schedule.date=2022-12-12,java.time.LocalDate
將被轉換為一個標識性作業引數,其型別為 java.time.LocalDate,值為 2022-12-12。注意,標識標誌是可選的,預設為 true。這種新的預設表示法非常適合大多數用例,但當值包含逗號等字元時可能不太方便。因此,我們引入了一種新的“擴充套件”表示法,其靈感來自 Spring Boot 的 Json Application Properties,其規定如下:
parameterName='{"value": "parameterValue", "type":"parameterType", "identifying": "booleanValue"}'
其中 parameterType 是引數型別的完全限定名。Spring Batch 提供了 JsonJobParametersConverter 來支援這種表示法。當然,也可以透過實現策略介面 JobParametersConverter 並在作業倉庫和作業探索器中註冊自定義實現來支援任何其他表示法。
我們認為 Spring Batch 中作業引數處理的這兩項主要更改更加方便、靈活且不容易出錯。
在此版本中,@EnableBatchProcessing 註解引入了新屬性,用於指定應該使用哪些元件和引數來配置批處理基礎設施 Bean。例如,你現在可以指定 Spring Batch 在作業倉庫中應配置哪個資料來源和事務管理器。以下程式碼片段展示了這種配置的新方式:
@Configuration
@EnableBatchProcessing(dataSourceRef = "batchDataSource", transactionManagerRef = "batchTransactionManager")
public class MyJobConfiguration {
@Bean
public Job job(JobRepository jobRepository) {
return new JobBuilder("myJob", jobRepository)
//define job flow as needed
.build();
}
}
在此示例中,注入到 Job Bean 定義中的 JobRepository Bean 是在 DefaultBatchConfiguration 類中定義的。你可以透過覆蓋相應的 getter 來指定自定義引數。例如,以下示例展示瞭如何覆蓋作業倉庫和作業探索器中使用的預設字元編碼:
@Configuration
@EnableBatchProcessing
public class MyJobConfigWithCustomSerializer {
@Bean
public BatchConfigurer batchConfigurer() {
return new DefaultBatchConfigurer() {
@Override
public JobRepository getJobRepository() {
JobRepositoryFactoryBean factory = new JobRepositoryFactoryBean();
factory.setSerializer(createCustomSerializer());
// set other properties on the factory bean
try {
factory.afterPropertiesSet();
return factory.getObject();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
@Override
public JobExplorer getJobExplorer() {
JobExplorerFactoryBean factoryBean = new JobExplorerFactoryBean();
factoryBean.setSerializer(createCustomSerializer());
// set other properties on the factory bean
try {
factoryBean.afterPropertiesSet();
return factoryBean.getObject();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
private ExecutionContextSerializer createCustomSerializer() {
Jackson2ExecutionContextStringSerializer serializer = new Jackson2ExecutionContextStringSerializer();
// customize serializer
return serializer;
}
};
}
}
在 Spring Batch v5 中,你可以按如下方式提供自定義序列化器:
@Configuration
@EnableBatchProcessing(executionContextSerializerRef = "myCustomSerializer")
public class MyJobConfigWithCustomSerializer {
@Bean
public Job job(JobRepository jobRepository) {
return new JobBuilder("myJob", jobRepository)
//define job flow as needed
.build();
}
@Bean
public ExecutionContextSerializer myCustomSerializer() {
Jackson2ExecutionContextStringSerializer serializer = new Jackson2ExecutionContextStringSerializer();
// customize serializer
return serializer;
}
}
我們認為這種新的 Spring Batch 配置方式更加直觀、直接且不容易出錯。
在此版本中,你可以使用一個名為 DefaultBatchConfiguration 的新配置類,作為使用 @EnableBatchProcessing 配置基礎設施 Bean 的替代方案。此類提供了預設配置的基礎設施 Bean,你可以根據需要進行自定義。以下程式碼片段展示了此類的一個典型用法:
@Configuration
class MyJobConfiguration extends DefaultBatchConfiguration {
@Bean
public Job job(JobRepository jobRepository) {
return new JobBuilder("myJob", jobRepository)
//define job flow as needed
.build();
}
}
在此示例中,注入到 Job Bean 定義中的 JobRepository Bean 是在 DefaultBatchConfiguration 類中定義的。你可以透過覆蓋相應的 getter 來指定自定義引數。例如,以下示例展示瞭如何覆蓋作業倉庫和作業探索器中使用的預設字元編碼:
@Configuration
class MyJobConfiguration extends DefaultBatchConfiguration {
@Bean
public Job job(JobRepository jobRepository) {
return new JobBuilder("job", jobRepository)
// define job flow as needed
.build();
}
@Override
protected Charset getCharset() {
return StandardCharsets.ISO_8859_1;
}
}
此版本在透過 JobExplorerFactoryBean 建立的 JobExplorer 中引入了事務支援。現在你可以指定在查詢批處理元資料時使用哪個事務管理器來驅動只讀事務。此外,你現在還可以自定義事務屬性。透過一個新的工廠 Bean,名為 JobOperatorFactoryBean,向 JobOperator 添加了相同的事務支援。
截至版本 4,EnableBatchProcessing 註解提供了啟動 Spring Batch 作業所需的所有基本基礎設施 Bean。但是,它沒有註冊作業操作器 Bean,而作業操作器是停止、重啟和放棄作業執行的主要入口點。
雖然這些工具的使用頻率不如啟動作業高,但在應用程式上下文中自動新增作業操作器有助於避免終端使用者手動配置此類 Bean。
直到版本 4.3,JobLauncherTestUtils 習慣於自動裝配被測作業,以簡化測試設定。但如果在測試上下文中定義了多個作業怎麼辦?如果根本沒有定義 Job Bean 怎麼辦?因此,雖然這種自動裝配在大多數情況下很方便,但在上述情況下卻導致了一些問題。在此版本中,根據社群反饋,我們決定移除 JobLauncherTestUtils 中任何作業的自動裝配。
類似地,JobRepositoryTestUtils 習慣於從應用程式上下文自動裝配 DataSource。同樣,如果在測試上下文中沒有定義資料來源或定義了多個數據源怎麼辦?在此版本中,JobRepositoryTestUtils 已更新為針對 JobRepository 介面工作,而無需處理倉庫的任何實現細節(例如資料來源)。
如果你在測試上下文中手動定義這些工具 Bean,或者透過 @SpringBatchTest 匯入它們,則當測試上下文中定義了這些型別的多個 Bean 時,你需要手動設定被測作業或測試資料來源。
在此版本中,Spring Batch 的整個測試套件已遷移到 JUnit 5。雖然這不會直接影響終端使用者,但它有助於批處理團隊以及社群貢獻者使用下一代 JUnit 編寫更好的測試。
對將 Java Record 作為面向塊的步驟中的項的支援最初是在 v4.3 中引入的,但由於 v4 的基線是 Java 8,該支援受到限制。在 Java 8 中,Record 甚至還沒有進入預覽階段。最初的支援是基於反射技巧來建立 Java Record 並用資料填充它們,當時還無法訪問在 Java 16 中最終確定的 java.lang.Record API。
現在 v5 的基線是 Java 17,我們透過在框架的不同部分利用 java.lang.Record API 來改進了 Spring Batch 中的 Record 支援。例如,FlatFileItemReaderBuilder 現在能夠檢測項型別是 Record 還是常規類,並相應地配置相應的 FieldSetMapper 實現(Record 使用 RecordFieldSetMapper,常規類使用 BeanWrapperFieldSetMapper)。這裡的目標是讓所需的 FieldSetMapper 型別的配置對使用者來說是透明的。在 FlatFileItemWriterBuilder 中也實現了相同的功能,以便根據項型別配置 RecordFieldExtractor 或 BeanWrapperFieldExtractor。
多年來,在框架的不同領域報告了幾個與字元編碼相關的問題,例如基於檔案的 ItemReader 和 ItemWriter 之間的預設編碼不一致、處理執行上下文中的多位元組字元時的序列化/反序列化問題等。
本著與 JEP 400 相同的精神,並遵循 UTF-8 宣言,我們將框架所有領域的預設編碼更改為 UTF-8,並在適當的地方使此預設值可配置。
我們藉此重要版本釋出的機會,利用 Java 8+ 的特性改進了程式碼庫,例如:
@FunctionalInterface(參見 issue 4107)此功能已被多次請求,並最終在此版本中釋出。現在可以使用新新增的 Maven BOM 來匯入 Spring Batch 模組,並保持一致的版本號。
直到 v4.3,Spring Batch 透過將 MariaDB 視為 MySQL 來提供支援。在此版本中,MariaDB 現在被視為一個獨立的資料庫產品,擁有自己的 DDL 指令碼和 DataFieldMaxValueIncrementer。
SAP Hana 現在已正式支援作為 Spring Batch 中的作業倉庫。
在此版本中,文件已更新為使用 Spring Asciidoctor Backend。此後端確保所有專案都遵循相同的文件風格。為了與其他專案保持一致,在此版本中,Spring Batch 的參考文件已更新為使用此後端。您可以在此處檢視參考文件的新版本。
在此主版本中,之前版本中所有已棄用的 API 都已被移除。此外,一些 API 在 v5.0 中已被棄用,並計劃在 v5.2 中移除。最後,出於實際原因,一些 API 被移動或移除而未進行棄用標記。有關所有已棄用 API 的列表,請參閱遷移指南。
SQLFire 已宣佈於 2014 年 11 月 1 日結束生命週期 (EOL)。對 SQLFire 作為作業倉庫的支援在 v4.3 版本中被棄用,並在 v5.0 版本中被移除。
根據停止維護的決定,對 Spring Batch 中 Apache Geode 的支援已被移除。
程式碼已作為社群驅動的工作轉移到 spring-batch-extensions 倉庫。
由於採用率不高,在此版本中已停止維護 JSR-352 的實現。
有些錯誤無法修復,除非引入破壞性變更。我們藉此主版本的機會修復了這些錯誤。有關此版本中修復的 40 多個錯誤的完整列表,請參閱發行說明!
我要感謝所有為此巨大版本做出貢獻的貢獻者們!如果沒有出色的 Spring 社群(特別是 Spring Batch 社群)的幫助,這個版本是不可能實現的。我們很高興聽到您對此主版本的反饋,以及它如何能夠改善您的批處理基礎設施。請在 Github、Twitter 和 StackOverflow 上提交您的反饋意見。
由於我們剛剛釋出了下一代 Spring Batch 的第一個版本,我們仍然有大量正在開發或計劃在下一版本中開發的想法和功能,例如:
我們將在不久的將來與您分享完整的路線圖,並展示如何參與這些新功能的早期開發和測試。敬請關注!