領先一步
VMware 提供培訓和認證,助您加速前進。
瞭解更多我們一直在努力為 Spring Batch 準備 Spring 產品組合 2.5 釋出列車,我認為現在是向大家更新情況的好時機。在本文中,我將稍微擴充套件一下領域建模,以及我們提升一些核心領域物件的地位並增加其職責的決定。我還會預覽一下在接下來的幾個版本中,直到 1.0 版本之前會推出的一些內容,以便大家有機會發表評論。
先道個歉:自從我上次撰寫關於 Spring Batch 的部落格以來,其內部發生了一些相當重要的變化,所以我感覺自己疏忽了。在本文中,我認為無法涵蓋所有變化,但我保證將來會努力更及時地更新,並且隨著 1.0 版本臨近,我一定會讓大家瞭解最新情況。(注意:Spring 產品組合 2.5 釋出列車包含 Spring Batch 1.0。)
由於自 1.0.0-m3 以來我們已經修復了 70 多個問題,我們覺得是時候釋出一個新版本了。我們上週制定的計劃是明天(2 月 5 日)釋出 1.0.0-m4,範圍比原計劃略窄(例如,推遲 XML 名稱空間的實現)。然後大約 10-14 天后釋出 1.0.0-m5,並在 3 月 20 日最終釋出 1.0.0 之前至少有一個釋出候選版本的時間。
Spring Batch 核心是一個相當緊湊的 API。實際上,它幾乎不包含我們期望批處理應用程式開發人員必須實現或擴充套件的內容,因此它實際上是一個內部 API。然而,它對 Spring Batch 使用者產生了相當深遠的影響,因為它塑造了我們思考批處理作業及其執行方式,以及(對使用者更重要的)其實現、配置和部署方式。
直到 1.0.0-m3,我們的 API 與批處理的通用語言之間存在經典的失配。我們不得不一直解釋說一個JobConfiguration是大多數人認為的“Job”(同樣適用於StepConfiguration和“Step”)。“Job”是您配置每天執行的東西,但每次執行時,它都有一個新的身份。這清楚地表明“Job”是領域概念的名稱,那我們為什麼稱它為“JobConfiguration”呢?問得好。所以現在(在 1.0.0-m4 中),使用者配置的東西是一個Job,當它執行時,我們建立一個新的JobInstance。同樣適用於Step和StepInstance。因此,實體(Entity)原型由*Instance物件來實現 - 它們具有 ID 和資料庫中的主鍵。例如,可以是 [JobInstance2008 年 2 月 2 日生效],對於 ["end-of-day"(日終)Job].
] JobInstance。其他實體原型是JobExecution和StepExecution和。自 m3 以來,這些原型名稱或職責沒有改變。當一個JobInstanceJobInstance 執行時,我們建立一個JobExecutionJobExecution(首先確保該例項尚未執行)。此時,[JobExecutionJobExecution 在 2 月 2 日晚上 10 點],屬於 [JobInstanceJobInstance 在 2008 年 2 月 2 日生效],用於 ["end-of-day"(日終)Job] Job,啟動。但是如果它失敗了,並且第二天重新啟動,那麼我們需要一個新的 [JobExecutionJobExecution 在 2 月 3 日晚上 10:12],用於同一個JobInstance(即 [JobInstanceJobInstance 在 2008 年 2 月 2 日生效],用於 ["end-of-day"(日終)JobJobInstance])。因此JobJobInstance 與JobInstanceJobExecution 是一對多關係,而 JobExecution 又與JobExecutionStepExecution 是一對多關係。同樣適用於Step*.
我們還對 API 關於Job和StepStep 在 1.0.0-m4 中的執行方式進行了更改。直到 1.0.0-m3,我們對每種執行都有單獨的介面 -JobExecutor執行JobJobConfiguration,而StepExecutor執行Step執行 StepConfiguration。正如我們在設計時所想的那樣,這具有封裝的好處 - 我們設想了多個StepExecutorJobExecutor 實現,都能夠執行同一個StepJob。然而,在實踐中,隨著我們對實現輪廓瞭解得更多,我們發現這是一個人為的區分。有趣的是,這個跡象是我們在 Java 中的StepExecutorExecutor 實現中進行了過多的“instanceof”檢查 - 它們總是需要針對不同的StepStep 實現做特殊處理。最終很明顯,每個StepStep 都必須知道如何執行自己。就像所有這樣的領悟一樣,一旦看到了就顯而易見,但在此之前卻完全不是。感謝 Eric Evans。
所以,例如,StepStep 領域的核心介面是
public interface Step {
// ... properties that the Job needs to know here ...
void execute(StepExecution stepExecution)
throws StepInterruptedException, BatchCriticalException;
}
StepStepStep 介面不需要從其execute方法返回任何內容,因為傳遞進來的StepExecutionStepExecution 在步驟執行過程中會被更新。它由呼叫者傳入,並且在需要時可以用來監控執行的進度。它還可以用來停止執行,如果呼叫者需要中斷作業(因此有了StepInterruptedException),只需設定一個標誌setTerminateOnly()。這是有人問過我的事情,所以可能值得在這裡提一下:該StepStep 實現負責在可行的情況下檢查該標誌的值,因此框架中內建了一種機制來指示作業提前終止。設定該標誌的效果取決於StepStep,但我們提供了一個SimpleStep,它會在處理每個專案後檢查該標誌,並在必要時中止。它還接受一個StepInterruptPolicy策略,可用於檢查其他異常情況(例如,Thread.isInterrupted()).
Spring Batch 名稱空間Spring Batch 幾乎是 Spring XML 名稱空間可以幫助應用程式開發人員簡化事情的完美例子。我們尚未實現NamespaceHandler,但它計劃在下一個里程碑 1.0.0-m5 中實現,所以現在是您看看示例感覺如何的好時機。
座右銘是“讓配置看起來像領域模型”,本著這種精神,看看這個例子,看看它是否有意義。這是新名稱空間的草案,它模仿了現有的固定長度匯入示例作業,所以熟悉該示例的讀者會看到相似之處。如果您需要找到現有示例,只需訪問 Spring Batch 主頁下載版本(固定長度示例配置也可以在此處瀏覽)。
<batch>
<job id="fixedLengthImportJob" volatile="false">
<simple-step id="step1" chunk-size="50" save-restart-data="false"
allow-start-if-complete="true" reader-ref="fileInputTemplate">
<processor>
<beans:bean
class="org.springframework.batch.sample.item.processor.TradeProcessor">
<property name="writer" ref="tradeDao" />
</beans:bean>
</processor>
<simple-completion-policy skipLimit="5" />
</simple-step>
<simple-step id="step2" chunk-size="200">
<jdbc-cursor-reader data-source-ref="dataSource">
<query><![CDATA[SELECT ID FROM T_TRADE ORDER BY ID WHERE PROCESSED='N']]></query>
</jdbc-cursor-reader>
<processor>
<beans:bean
class="org.springframework.batch.sample.item.processor.TradeUpdater">
<property name="dao" ref="tradeDao" />
</beans:bean>
</processor>
</simple-step>
<tasklet-step id="step3" chunk-size="1">
<tasklet>
<beans:bean
class="org.springframework.batch.sample.sproc.TradeSummarizer"
p:dataSource-ref="dataSource" />
</tasklet>
</tasklet-step>
</job>
<!-- INFRASTRUCTURE SETUP -->
<flat-file-reader id="fileInputTemplate"
resource="data/fixedLengthImportJob/input/20070122.teststream.ImportTradeDataStep.txt"
field-set-mapper-ref="fieldSetMapper"
validator-ref="fixedValidator">
<fixed-length-tokenizer>
<columns>
ISIN=1-12 Quantity=13-15 Price=16-20 Customer=21-29
</columns>
</fixed-length-tokenizer>
</flat-file-reader>
<beans:bean id="fixedValidator"
class="org.springframework.batch.item.validator.SpringValidator">
<property name="validator">
<bean id="tradeValidator"
class="org.springmodules.validation.valang.ValangValidator">
<property name="valang">
<value>
<![CDATA[
{ isin : length(?) < 13 : 'ISIN too long' : 'isin_length' : 12}
]]>
</value>
</property>
</bean>
</property>
</beans:bean>
<beans:bean id="tradeDao"
class="org.springframework.batch.sample.dao.JdbcTradeWriter">
<property name="jdbcTemplate" ref="jdbcTemplate" />
<property name="incrementer">
<bean parent="incrementerParent">
<property name="incrementerName" value="TRADE_SEQ" />
</bean>
</property>
</beans:bean>
<beans:bean id="fieldSetMapper"
class="org.springframework.batch.sample.mapping.TradeFieldSetMapper" />
</batch>
請注意,Job和StepStep 實現細節是如何隱藏的 -<simple-step/>與<tasklet-step/>之間存在差異,但唯一可見的差異是使用者需要了解的那些。使用者無需知道該Step介面有不同的實現來支援此配置,但存在面向專案(item-oriented)和麵向任務(task-oriented)的步驟方法的差異並未隱藏。這正是我們認為對使用者重要的。當我們起草這些 XML 示例時,我們從現有的 Spring Batch 示例中選取了幾個,並進行修改,直到包含相同的配置資訊,但在大多數情況下,檔案總大小下降了 50% 或更多。這一定意味著我們走在正確的軌道上。
這是一個快速但深入的 Spring Batch 及其最近一些變化的探討。關於我們使用和實現該框架的經驗,還有很多有趣的細節可以與您分享。我的JavaOne演講已被接受,這意味著您可以期待在五月份在舊金山學習更多內容,並聽到更多真實的批處理示例。此外,隨著 2.5 釋出列車啟動其旅程(從使用者的角度來看是這樣!),請關注本部落格的更多內容。
最後,我需要向 Lucas Ward 和 Ben Hale 致敬,他們在 Spring Batch 開發過程中發揮了重要作用。我還要歡迎 Robert Kasanicky 成為我們最新的提交者(committer)—— Robert 為 Spring Batch 貢獻了一些高質量的程式碼,我相信在我們完成 1.0 版本並開始下一個主要版本的工作時,他會繼續這樣做。如果還有其他人有興趣貢獻,Robert 遵循了正常流程,在論壇和 JIRA 上活躍,貢獻想法和(關鍵的)補丁。我提名了他,我們進行了投票,現在他正式成為團隊的一員。
如果文章中有任何需要澄清的地方,請隨時在此處評論。關於 Spring Batch 的一般討論,請使用論壇。Spring Batch 的主頁在此處,或者可以很容易地從Spring 主網站找到