Spring Batch 小任務(Tasklet)步驟

Chunk-Oriented Processing不是處理 step 的惟一方法。java

考慮下面的一個場景,若是你僅僅須要調用一個存儲過程,你能夠在 ItemReader 中實現這個調用,而後在存儲過程完成調用後返回 null。這種設計看起來不是那麼天然也不是很是優美,由於你的批量設計中甚至都不須要實現 ItemWriter。針對這種狀況,Spring Batch 爲你提供了 TaskletStep 選項。git

TaskletStep 是一個簡單的接口,這個接口只須要實現一個方法execute,這個方法將會被TaskletStep屢次重複的調用,直到這個方法返回 RepeatStatus.FINISHED 或者拋出異常來表示調用失敗。github

Tasklet 的每一次調用都會包含在事務中(Transaction)。Tasklet 的實現(implementors)能夠調用一個存儲過程,一個腳本或者一個簡單的 SQL 更新腳本。spring

針對咱們的實踐中,咱們可使用 Tasklet 來執行一個 FTP 的任務。服務器

將咱們產生的中間文件上傳到不一樣的 FTP 服務器上,你能夠在實現中指定不一樣的服務器配置參數,這樣更加有利於代碼的重用。ui

爲了可以建立一個 TaskletStep,Bean 須要傳遞一個 tasklet 方法到構造器(builder),這個 tasklet 方法須要實現 Tasklet 接口。this

當你構建 TaskletStep 的時候不要調用 chunkspa

下面的示例代碼顯示了一個在 Step build 中構建一個簡單的 tasklet。.net

public Step step1() {
     return this .stepBuilderFactory.get( "step1" )
                 .tasklet(myTasklet())
                 .build();
}

若是你的 tasklet 實現了 StepListener  接口的話,TaskletStep 將會自動將 tasklet 註冊成爲一個 StepListener設計

TaskletAdapter

ItemReader ItemWriter 接口的 adapters同樣。Tasklet  接口包含的實現也容許可以經過已經存在的類使用 TaskletAdapter 來將本身進行註冊。

例如,你但願使用一個已經存在的 DAO 來更新記錄集上的標記的時候,你可使用 TaskletAdapter 來進行實現。

使用 TaskletAdapter  可以讓你的 DAO 能夠被 Spring Batch 的 TaskletStep 調用而不須要讓你的 DAO 都實現 Tasklet 的接口。

以下面的示例代碼:

public MethodInvokingTaskletAdapter myTasklet() {
     MethodInvokingTaskletAdapter adapter = new MethodInvokingTaskletAdapter();
 
     adapter.setTargetObject(fooDao());
     adapter.setTargetMethod( "updateFoo" );
 
     return adapter;
}

Tasklet 實現(Implementation)示例

在主批量做業開始以前,可能須要不少其餘的批量做業必須完成,這樣以便於主批量做業可以得到必要的資源和在完成後釋放資源或者進行清理。

例如咱們遇到下面的使用場景,一個批量做業須要大量的對文件進行交互和使用,一般來講須要在文件被上傳到其餘服務器上後刪除本地產生的臨時文件。

下面的示例就是一個 Tasklet 的實現,這個Tasklet 的實現可以完成上面的交互要求(文件來自 Spring Batch samples project 示例程序)。

public class FileDeletingTasklet implements Tasklet, InitializingBean {
 
     private Resource directory;
 
     public RepeatStatus execute(StepContribution contribution,
                                 ChunkContext chunkContext) throws Exception {
         File dir = directory.getFile();
         Assert.state(dir.isDirectory());
 
         File[] files = dir.listFiles();
         for ( int i = 0 ; i < files.length; i++) {
             boolean deleted = files[i].delete();
             if (!deleted) {
                 throw new UnexpectedJobExecutionException( "Could not delete file " +
                                                           files[i].getPath());
             }
         }
         return RepeatStatus.FINISHED;
     }
 
     public void setDirectoryResource(Resource directory) {
         this .directory = directory;
     }
 
     public void afterPropertiesSet() throws Exception {
         Assert.notNull(directory, "directory must be set" );
     }
}

 

Tasklet 處理程序實現了將給定目錄中的全部文件進行刪除。咱們應該通知 execute  方法,這個 Tasklet 應該只被執行一次。

全部相關執行的操做須要在 Step 中進行設置,請參考下面有關這個 Tasklet 的設置:

Java 配置

public Job taskletJob() {
     return this .jobBuilderFactory.get( "taskletJob" )
                 .start(deleteFilesInDir())
                 .build();
}
 
public Step deleteFilesInDir() {
     return this .stepBuilderFactory.get( "deleteFilesInDir" )
                 .tasklet(fileDeletingTasklet())
                 .build();
}
 
public FileDeletingTasklet fileDeletingTasklet() {
     FileDeletingTasklet tasklet = new FileDeletingTasklet();
 
     tasklet.setDirectoryResource( new FileSystemResource( "target/test-outputs/test-dir" ));
 
     return tasklet;
}

 

https://www.cwiki.us/display/SpringBatchZH/TaskletStep

相關文章
相關標籤/搜索