2016-12-12 71 views
2

我一直在試圖解決這個問題幾天,我無法做到。我對Spring 4很新,所以也許有經驗的人可以告訴我如何去做。使Spring 4批處理服務可重複執行計劃執行

我想了解如何使用最新版本的框架編寫Spring Batch。我按照入門教程: https://spring.io/guides/gs/batch-processing/

一旦作業執行,我想讓它定期執行。因此,我去了一個計劃任務: https://spring.io/guides/gs/scheduling-tasks/

看起來很容易把兩個想法放在一起。實際上,這是不可能的。 我讀了一點,我添加了一些代碼,使jobExecution每次都是唯一的。儘管如此,編碼步驟一旦完成,就再也不會執行了。

我調查了一下,我已經閱讀了有關RepeatTemplate,但我沒有看清楚如何使它適合我的代碼。在這裏你有3個相關的執行方法:

@Scheduled(cron="0 0/2 * * * ?") 
public void run() throws Exception { 
    System.out.println("Job Started at :" + new Date()); 

    JobParameters param = new JobParametersBuilder().addString("newsSyncJob", 
      String.valueOf(System.currentTimeMillis())).toJobParameters(); 

    NewsJobCompletionListener listener = new NewsJobCompletionListener(); 
    JobExecution execution = jobLauncher.run(newsSyncJob(listener), param); 

    System.out.println("Job finished with status :" + execution.getStatus()); 
} 


/** 
* Execution of the job 
* @param listener 
* @return 
*/ 
@Bean 
public Job newsSyncJob(NewsJobCompletionListener listener) { 
    log.debug("newsSyncJob execution started"); 
    this.init(); 
    return jobBuilderFactory.get("newsSyncJob") 
      .incrementer(new RunIdIncrementer()) 
      .listener(listener) 
      .flow(step1()) 
      .end() 
      .build(); 
} 

@Bean 
protected Step step1() { 
    return stepBuilderFactory.get("step1") 
      .<NewsSync, NewsSync> chunk(4) 
      .reader(filesReader()). 
      processor(newsProcessor()). 
      writer(stateWriter()). 
      build(); 
} 

任何想法如何使步驟重新執行成功? 提前謝謝!

+0

對於初學者,您的設置存在缺陷。每次你想執行它時,你都不應該創建一個新的Job實例。另外你的意思是不重新執行?我也懷疑你需要/想'流',但你應該有'開始',而不是。 –

+0

感謝@ M.Deinum給你評論。我按照你的建議替換了Job的設置 - 'start(...)'而不是'flow(...)',我不得不擺脫'end()'。 不過,作業只執行一次。 這意味着run()方法每2分鐘執行一次(如cron表達式所示)。這裏都很好。問題來到...... 'jobLauncher.run(newsSyncJob(listener),param)' ...因爲'newsSyncJob(...)'不再被調用。這是正常的嗎? 對於'newsSyncJob()','step1()'或任何itemReader,處理器或寫入器,不會有斷點停止。 –

回答

0

在M.Deinum的評論後,我做了一些調查,我可以自己解決。以下是一步一步的說明:

配置錯誤,因爲newsSyncJob()應該只執行一次。它建立了Job,並且bean保持單獨創建。一個可以多次執行的單例。 與step bean相同。只有一次調用step1()才能創建單例bean。作爲作業的一部分,它可以在作業執行時執行... 直至它被正確配置。目前,這兩種方法是這樣的:

@Bean 
public Job newsSyncJob() { 
    log.debug("Building batch newsSyncJob..."); 
    this.init(); 
    return jobBuilderFactory.get("newsSyncJob") 
      .incrementer(new RunIdIncrementer()) 
      .start(step1()) 
      .build(); 
} 

@Bean 
protected Step step1() { 
    return stepBuilderFactory.get("step1") 
      .<NewsSync, NewsSync> chunk(4) 
      .reader(filesReader()). 
      processor(newsProcessor()). 
      writer(stateWriter()). 
      build(); 
} 

現在,使步執行我們每次運行作業時間,需要改變其範圍。該步驟由itemReader + itemProcessor + itemWriter組成。默認情況下,它們的範圍是原型。這意味着它保持前一次執行的狀態,並且不會再次運行。要重新運行,範圍需要更改爲步驟範圍。該代碼將是這樣的:

@Bean 
@StepScope 
ItemReader<NewsSync> filesReader() { 
    return new NewsSyncReader(srcPath); 
} 

@Bean 
@StepScope 
ItemProcessor<NewsSync, NewsSync> newsProcessor() { 
    return new NewsSyncProcessor(jdbcTemplate, newsRepository); 
} 

@Bean 
@StepScope 
ItemWriter<NewsSync> stateWriter() { 
    return new NewsSyncWriter(jdbcTemplate); 
} 

現在到結束,排定呼叫將在不同的類使用前面類創建的豆的依賴注入配置。這樣的事情:

@EnableScheduling 
@Service 
public class BatchScheduled { 

    private static final Logger log = LoggerFactory.getLogger(BatchScheduled.class); 

    @Autowired 
    private JobLauncher jobLauncher; 

    @Autowired 
    @Qualifier("newsSyncJob") 
    private Job newsJobSync; 

    /** 
    * Scheduled run of the batch 
    * @throws Exception 
    */ 
    @Scheduled(cron="0 0/2 * * * ?") 
    public void run() throws Exception { 
     log.info("newsJobSync started"); 
     System.out.println("Job Started at :" + new Date()); 

     JobParameters param = new JobParametersBuilder().addString("newsSyncJob", 
       String.valueOf(System.currentTimeMillis())).toJobParameters(); 

     JobExecution execution = jobLauncher.run(newsJobSync, param); 

     log.info("newsJobSync finished with status " + execution.getExitStatus()); 
    } 
} 

我們終於有一個彈簧批處理計劃的表達式執行。