簡體   English   中英

Spring Batch - My Batch 似乎同時執行兩個步驟?

[英]Spring Batch - My Batch seems executing two steps at the same time?

我真的不明白發生了什么。 我正在研究 Spring Batch,由於某些原因,我想一個接一個地執行兩個步驟。

現在請不要介意這些步驟當前在做什么,只要記住我想按順序執行兩個步驟。

這是代碼:

@Configuration
@EnableBatchProcessing
public class JobConfiguration {
    @Autowired
    private JobBuilderFactory jobBuilderFactory;

    @Autowired
    private StepBuilderFactory stepBuilderFactory;
    
    private List<Employee> employeesToSave = new ArrayList<Employee>();


    public JsonItemReader<Employee> jsonReader() {

        
        System.out.println("Try to read JSON");
        
        final ObjectMapper mapper = new ObjectMapper();

        final JacksonJsonObjectReader<Employee> jsonObjectReader = new JacksonJsonObjectReader<>(
                Employee.class);
        jsonObjectReader.setMapper(mapper);

        return new JsonItemReaderBuilder<Employee>().jsonObjectReader(jsonObjectReader)
                .resource(new ClassPathResource("input.json"))
                .name("myReader")
                .build();

    }
    

    public ListItemReader<Employee> listReader() {
        
        System.out.println("Read from list");
        
        return new ListItemReader<Employee>(employeesToSave);

*/
    }
    

    public ItemProcessor<Employee,Employee> filterProcessor() {
        return employee -> {
            
            System.out.println("Processing JSON");
            
            return employee;
        };
    }

    public ItemWriter<Employee> filterWriter() {

        return listEmployee -> {
            
            employeesToSave.addAll(listEmployee);
            System.out.println("Save on list " + listEmployee.toString());
                        
        };

    }

    public ItemWriter<Employee> insertToDBWriter() {

        System.out.println("Try to save on DB");
        return listEmployee -> {

            System.out.println("Save on DB " + listEmployee.toString());
                        
        };

    }

    public Step filterStep() {
        
        StepBuilder stepBuilder = stepBuilderFactory.get("filterStep");
        SimpleStepBuilder<Employee, Employee> simpleStepBuilder = stepBuilder.chunk(5);
        return simpleStepBuilder.reader(jsonReader()).processor(filterProcessor()).writer(filterWriter()).build();
    }

    public Step insertToDBStep() {
        
        StepBuilder stepBuilder = stepBuilderFactory.get("insertToDBStep");
        SimpleStepBuilder<Employee, Employee> simpleStepBuilder = stepBuilder.chunk(5);
        return simpleStepBuilder.reader(listReader()).writer(insertToDBWriter()).build();
    }

    @Bean
    public Job myJob(JobRepository jobRepository, PlatformTransactionManager platformTransactionManager) {

        return jobBuilderFactory.get("myJob").incrementer(new RunIdIncrementer())
                .start(filterStep())
                .next(insertToDBStep())
                .build();
    }
}



為什么 insertToDBStep 不在 filterStep 的末尾開始,實際上看起來過濾器正在同時運行? 為什么它看起來像在初始化 Root WebApplicationContext 之后開始工作?

這是輸出。

2022-05-23 15:40:49.418  INFO 14008 --- [  restartedMain] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 1024 ms
Try to read JSON
Read from list
Try to save on DB
2022-05-23 15:40:49.882  INFO 14008 --- [  restartedMain] o.s.b.d.a.OptionalLiveReloadServer       : LiveReload server is running on port 35729
2022-05-23 15:40:49.917  INFO 14008 --- [  restartedMain] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''
2022-05-23 15:40:49.926  INFO 14008 --- [  restartedMain] c.marco.firstbatch.TestBatchApplication  : Started TestBatchApplication in 1.985 seconds (JVM running for 2.789)
2022-05-23 15:40:49.927  INFO 14008 --- [  restartedMain] o.s.b.a.b.JobLauncherApplicationRunner   : Running default command line with: []
2022-05-23 15:40:49.928  WARN 14008 --- [  restartedMain] o.s.b.c.c.a.DefaultBatchConfigurer       : No datasource was provided...using a Map based JobRepository
2022-05-23 15:40:49.928  WARN 14008 --- [  restartedMain] o.s.b.c.c.a.DefaultBatchConfigurer       : No transaction manager was provided, using a ResourcelessTransactionManager
2022-05-23 15:40:49.943  INFO 14008 --- [  restartedMain] o.s.b.c.l.support.SimpleJobLauncher      : No TaskExecutor has been set, defaulting to synchronous executor.
2022-05-23 15:40:49.972  INFO 14008 --- [  restartedMain] o.s.b.c.l.support.SimpleJobLauncher      : Job: [SimpleJob: [name=myJob]] launched with the following parameters: [{run.id=1}]
2022-05-23 15:40:50.003  INFO 14008 --- [  restartedMain] o.s.batch.core.job.SimpleStepHandler     : Executing step: [filterStep]
Processing JSON
Processing JSON
Processing JSON
Processing JSON
Processing JSON
Save on list [com.marco.firstbatch.Employee@958d6e7, com.marco.firstbatch.Employee@464d17f8, com.marco.firstbatch.Employee@705520ac, com.marco.firstbatch.Employee@1a9f8e93, com.marco.firstbatch.Employee@55bf8cc9]
Processing JSON
Processing JSON
Save on list [com.marco.firstbatch.Employee@55d706c0, com.marco.firstbatch.Employee@1bc46dd4]
2022-05-23 15:40:50.074  INFO 14008 --- [  restartedMain] o.s.batch.core.step.AbstractStep         : Step: [filterStep] executed in 70ms
2022-05-23 15:40:50.081  INFO 14008 --- [  restartedMain] o.s.batch.core.job.SimpleStepHandler     : Executing step: [insertToDBStep]
2022-05-23 15:40:50.084  INFO 14008 --- [  restartedMain] o.s.batch.core.step.AbstractStep         : Step: [insertToDBStep] executed in 3ms
2022-05-23 15:40:50.088  INFO 14008 --- [  restartedMain] o.s.b.c.l.support.SimpleJobLauncher      : Job: [SimpleJob: [name=myJob]] completed with the following parameters: [{run.id=1}] and the following status: [COMPLETED] in 96ms

提前致謝。

這些步驟按順序正確執行。 您將System.out.println語句放在兩個“種類”的地方:

  • 在 Spring Framework 配置應用上下文時執行的 bean 定義方法中
  • 在運行作業時由 Spring Batch 調用的批處理工件(項目處理器、項目編寫器)的代碼中

在您的情況下,Spring Framework 將調用以下 bean 定義方法來定義第一步filterStep()

  • jsonReader() :打印Try to read JSON 此時不讀取文件,只定義了json reader bean。 更准確的日志消息是: json reader bean created
  • listReader() :打印Read from list 同樣在這里,文件讀取還沒有開始。 更准確的日志消息是: list reader bean created
  • filterProcessor() :什么都不打印。 日志語句位於ItemProcessor#process方法中。 這將在運行時由 Spring Batch 調用,而不是在配置時間的這個時間點
  • filterWriter() :這里一樣,打印語句在運行時調用的 write 方法中,而不是在配置時調用

這導致filterStep()的以下輸出:

Try to read JSON
Read from list

現在 Spring Framework 開始定義下一步, insertToDBStep() 為此,它將根據您的步驟定義按順序調用以下方法:

  • listReader() :這個 bean 已經定義了 bean,Spring 將重用相同的實例(默認情況下,Spring bean 是單例)。 因此,此方法沒有輸出。
  • insertToDBWriter() :打印Try to save on DB 同樣在這里,這里沒有實際保存到數據庫。 更准確的日志消息將是insertToDBWriter bean created (或者更准確地說, attempting to create insertToDBWriter bean ,以防后面的代碼拋出異常)。

您現在有以下累積輸出:

Try to read JSON
Read from list
Try to save on DB

至此,Spring Framework 已經完成了配置應用上下文的工作,Spring Batch 接管並啟動了這項工作。 filterStep()的實際處理開始:

  • 閱讀器 ( ListItemReader ) 在read方法中沒有任何輸出。
  • 處理器打印Processing JSON
  • 作者打印Save on list ...

您似乎有兩個塊(第一個有 5 個項目,第二個有 2 個項目),這導致以下輸出:

2022-05-23 15:40:50.003  INFO 14008 --- [  restartedMain] o.s.batch.core.job.SimpleStepHandler     : Executing step: [filterStep]
Processing JSON
Processing JSON
Processing JSON
Processing JSON
Processing JSON
Save on list [com.marco.firstbatch.Employee@958d6e7, com.marco.firstbatch.Employee@464d17f8, com.marco.firstbatch.Employee@705520ac, com.marco.firstbatch.Employee@1a9f8e93, com.marco.firstbatch.Employee@55bf8cc9]
Processing JSON
Processing JSON
Save on list [com.marco.firstbatch.Employee@55d706c0, com.marco.firstbatch.Employee@1bc46dd4]
2022-05-23 15:40:50.074  INFO 14008 --- [  restartedMain] o.s.batch.core.step.AbstractStep         : Step: [filterStep] executed in 70ms

然后,下一步開始執行,您將獲得以下輸出:

2022-05-23 15:40:50.081  INFO 14008 --- [  restartedMain] o.s.batch.core.job.SimpleStepHandler     : Executing step: [insertToDBStep]
2022-05-23 15:40:50.084  INFO 14008 --- [  restartedMain] o.s.batch.core.step.AbstractStep         : Step: [insertToDBStep] executed in 3ms

在這里,您可能會問為什么insertToDBWriter()沒有寫入任何項目(即為什么沒有Save on DB ..日志)。 這是因為listReader()是一個單例 bean,並且您在兩個步驟中都在使用它,所以當第二步調用它的read方法時,它仍然會返回null ,因為使用了相同的實例並且已經用盡了步驟 1 中的項目。因此,此步驟立即結束,因為沒有要處理的項目。 如果要在第二步中重新讀取列表中的項目,可以使用@StepScope注釋 reader 方法。 這將為每個步驟創建一個不同的閱讀器實例。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM