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策略。代碼如下:

 1package com.wanggc.springbatch.sample;
2
3import org.springframework.batch.core.step.skip.SkipLimitExceededException;
4import org.springframework.batch.core.step.skip.SkipPolicy;
5
6/**
7 * 自定義Skip策略類。
8 * @author Wanggc
9*/
10publicclass MySkipPolicy implements SkipPolicy {
11
12 @Override
13publicboolean shouldSkip(Throwable t, int skipCount)
14throws SkipLimitExceededException {
15// TODO Auto-generated method stub
16returnfalse;
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
8class="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機制的討論就到這裏了,接下來會討論其他一些高級屬性。

 


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章