Spring Batch 之 skip講解(九)


      前面的文章跟大家一起討論了Spring Batch的概念,處理流程,以及SpringBatch處理文件、DB的一些簡單實例。接下來的討論,主要是關於Spring Batch的一些高級應用處理和實際開發中需要注意的一些問題。

      今天主要和大家討論SpringBatch關於skip容錯機制的一些處理。

      一、skip的介紹

      在實際的項目開發中,我們常常要將幾十萬甚至上百萬的數據從文件導入到DB中,如果其中某條數據導入時發生例外,我們並不想整個Job以失敗而結束,而是希望能將錯誤的數據經過處理后保存起來,其余正確的數據繼續做導入處理。如果遇到這樣的場景,SpringBatch的skip機制就可以派上用場了。顧名思義,skip的作用就是跳過某些數據(例如錯誤數據)。 

      二、配置skip信息

      配置skip的示例代碼如下:

 1 <job id="csvJob">
2 <step id="csvStep">
3 <tasklet transaction-manager="transactionManager">
4 <chunk reader="itemReaders" writer="itemWriter" processor="itemProcessor"
5 commit-interval="1" skip-limit="1000">
6 <skippable-exception-classes>
7 <include class="org.springframework.batch.item.file.FlatFileParseException" />
8 </skippable-exception-classes>
9 </chunk>
10 </tasklet>
11 </step>
12 </job>

      代碼第5行chunk的skip-limit屬性是指允許跳過記錄的行數,6-8行是指允許發生的例外,也就是說在發生FlatFileParseException(及其子類)的時候,job是不會被終止的,而是跳過當前的記錄,去執行下面那條記錄。 上面的代碼也會有另外一個問題,就是發生FlatFileParseException以外例外的時候,Job也會失敗。這也滿足不了我們上面說的那種場景,當然,6-8行還有另外一種配置方式,如下:

1 <skippable-exception-classes>
2   <include class="java.lang.Exception"/>
3 <exclude class="java.io.FileNotFoundException"/>
4 </skippable-exception-classes>

      include是允許跳過的錯,exclude是不允許跳過的錯。如果像上訴代碼那樣配置的話,所有Exception及其子類(FileNotFoundException除外)發生時,Job都不會被終止;但是當FileNotFoundException發生時,雖然它也是Exception的子類,但Job會被終止,因為FileNotFoundException屬於exclude屬性的class。

      三、skip深入講解

      是誰在決定當前的記錄跳過與否呢?其實,當Reader、Processor和Writer拋出例外的時候,SpringBatch會調用skip機制,來判斷當前例外發生時,正在被處理的記錄是否被跳過。當在上面的代碼中配置skippable-exception-classes屬性的時候,SpringBatch會默認的調用LimitCheckingItemSkipPolicy類。如果簡單的配置skip-limit和skippable-exception-classes不能滿足需求時,也可以定義自己的skip策略。代碼如下:

 1 package com.wanggc.springbatch.sample;
2
3 import org.springframework.batch.core.step.skip.SkipLimitExceededException;
4 import org.springframework.batch.core.step.skip.SkipPolicy;
5
6 /**
7 * 自定義Skip策略類。
8 * @author Wanggc
9 */
10 public class MySkipPolicy implements SkipPolicy {
11
12 @Override
13 public boolean shouldSkip(Throwable t, int skipCount)
14 throws SkipLimitExceededException {
15 // TODO Auto-generated method stub
16 return false;
17 }
18 }

      如示例代碼所示,要實現SkipPolicy接口,在shouldSkip方法中定義自己的skip策略。返回false時,說明當前例外不能被跳過,否則可以被跳過。當然,定義了自己的skip策略還不夠,還要告訴框架要使用自己定義的skip策略,而不是框架默認的。這就需要添加chunk的另外一個屬性skip-policy。代碼如下:

 1 <job id="csvJob">
2 <step id="csvStep">
3 <tasklet transaction-manager="transactionManager">
4 <chunk reader="itemReaders" writer="itemWriter" processor="itemProcessor"
5 commit-interval="1" skip-limit="1000" skip-policy="mySkipPolicy">
6 <skippable-exception-classes>
7 <include
8 class="org.springframework.batch.item.file.FlatFileParseException" />
9 </skippable-exception-classes>
10 </chunk>
11 </tasklet>
12 </step>
13 </job>
14 <bean:bean id="mySkipPolicy" class="com.wanggc.springbatch.sample.MySkipPolicy"/>

      添加了skip-policy屬性后,skip-limit和skippable-exception-classes默認策略將不再起作用。當然,可以將其刪除,示例中屬於垃圾代碼。

      當Reader、Processor和Writer拋出例外的時候,SpringBatch處理skip策略的方式是不同的。當Reader發生可以被skip的例外時,SpringBatch會接着去讀下面一條記錄,並不會回滾事務。當Processor發生可以被skip的例外時,SpringBatch會回滾當前chunk的事務,並將除了引發例外以外的數據傳給Writer。當Writer發生可以被skip的例外的時,SpringBatch首先回滾事務,因為傳給Writer的是一個list,所以Writer不知道是list中那條記錄造成了例外的發生。Writer會將list拆開,一條條的處理,正確的數據提交,錯誤的數據回滾。

      對SpringBatch的skip機制的討論就到這里了,接下來會討論其他一些高級屬性。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM