当前位置: 首页 > 知识库问答 >
问题:

Spring批处理-在步骤中配置Tasklet,是否具有读写器?

林鹏鹍
2023-03-14

我使用Spring Batch引导示例。在这个例子中,我希望将基于XML的应用程序转换为基于注释的应用程序。然而,我正在努力配置使用@Bean在步骤创建确切的配置。

    <batch:step id="step1">
        <batch:tasklet>
            <batch:chunk reader="paymentDataReader" writer="paymentDataWriter" commit-interval="100000">
                <batch:listeners>
                    <batch:listener ref="paymentingStepExecutionListener" />
                </batch:listeners>
            </batch:chunk>
        </batch:tasklet>
        <batch:next on="COMPLETED" to="sendpaymentingBatchFiles" />
    </batch:step>

作业配置。JAVA

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

        @Autowired
        private StepBuilderFactory stepBuilderFactory;

        @Autowired
        private DataSource dataSource;

        @Bean
        @StepScope
        public PaymentContextTasklet paymentContextTasklet() {
            return new PaymentContextTasklet();
        }

        // Either execute for "Payment" or "Order"
        @Bean
        public ContextDecider contextDecider() {
            return new ContextDecider();
        }

        @Bean
        public JdbcPagingItemReader<Payment> pagingItemReader(){
            JdbcPagingItemReader<Payment> reader = new JdbcPagingItemReader<>();
            reader.setDataSource(this.dataSource);
            reader.setFetchSize(10);
            reader.setRowMapper(new PaymentRowMapper());

            MySqlPagingQueryProvider queryProvider = new MySqlPagingQueryProvider();
            queryProvider.setSelectClause("select paymentId, amount, customerId, paymentDate");
            queryProvider.setFromClause("from payment");

            reader.setQueryProvider(queryProvider);
            return reader;
        }

        @Bean
        public ItemWriter<Payment> paymentItemWriter(){
            return items -> {
                for(Payment c : items) {
                    System.out.println(c.toString());
                }
            };
        }

        @Bean
        public PaymentStepExecutionListener paymentStepExecutionListener() {
            return new PaymentStepExecutionListener();
        }

        @Bean
        public Step step1() {
            return stepBuilderFactory.get("step1")
                    .<Payment, Payment>chunk(10)
                    .reader(pagingItemReader())
                    .writer(paymentItemWriter())
                    .tasklet(paymentStepExecutionListener())
                    .rea
                    .build();
        }

        @Bean
        @StepScope
        public PaymentDataTasklet paymentDataTasklet() {
            return new PaymentDataTasklet();
        }

        @Bean
        public Step paymentContextStep() {
            return stepBuilderFactory.get("paymentContextStep")
                    .tasklet(paymentContextTasklet())
                    .build();
        }

        @Bean
        public Step paymentDataStep() {
            return stepBuilderFactory.get("paymentDataStep")
                    .tasklet(paymentDataTasklet())
                    .build();
        }

        @Bean
        public Step endStep() {
            return stepBuilderFactory.get("endStep")
                    .tasklet(null)
                    .build();
        }

        @Bean
        public Job paymentDataBatchJob() {
            return jobBuilderFactory.get("paymentDataBatchJob")
                    .start(paymentContextStep())
                    .next(contextDecider())
                        .on("Payment").to(paymentDataStep()).on("COMPLETED").to(endStep)
                    .from(contextDecider())
                        .on("Order").to(endStep()).end()
                    .build();
        }
    }

共有2个答案

雍嘉勋
2023-03-14

感谢@Mahmoud Ben Hassine。我意识到我应该在listener而不是在Tasklet中使用paymentStepExecttionListener

还有一件事是StepExecutionListener只在scope=“step”中定义的bean中工作 所以我应该使用

//您只能在//scope=“step”中定义的bean中访问stepExecutionContext。

@Bean
@StepScope
public PaymentStepExecutionListener paymentStepExecutionListener() {
    return new PaymentStepExecutionListener();
}

现在情况很好。

程承恩
2023-03-14

然而,我正在努力配置使用@Bean在步骤创建确切的配置。

与Java配置中的XML代码片段类似的内容如下:

   @Bean
    public Step step1() {
        return stepBuilderFactory.get("step1")
                .<Payment, Payment>chunk(100000)
                .reader(paymentDataReader())
                .writer(paymentDataWriter())
                .listener(paymentingStepExecutionListener())
                .build();
    }

    @Bean
    public Job paymentDataBatchJob() {
        return jobBuilderFactory.get("paymentDataBatchJob")
                .start(step1())
                .next(sendpaymentingBatchFiles())
                .build();
    }
 类似资料:
  • 第2步。根据在步骤1中创建的对象列表中有多少项创建步骤列表。 第三步。尝试执行步骤2中创建的步骤列表中的步骤。 下面在executeDynamicStepsTasklet()中执行x个步骤。虽然代码运行时没有任何错误,但它似乎没有做任何事情。我在那个方法中的内容看起来正确吗?

  • 根据已接受的答案代码,对该代码的以下调整对我起作用: 我已经将这个问题更新到了一个可以正确循环的版本,但是由于应用程序将扩展,能够处理并行是很重要的,我仍然不知道如何在运行时用javaconfig动态地做到这一点... 基于查询列表(HQL查询),我希望每个查询都有一个读取器-处理器-写入器。我当前的配置如下所示: 工单 处理机 作家 目前,该过程对于单个查询来说工作得很好。然而,我实际上有一个查

  • 给定一个使用分区的Spring批处理作业,是否可能有多个分区步骤? 例如: 在上述示例中,是否可以将另一个添加到(最好不需要为每个分区步骤提供分区器)?如果没有,是否有其他方法来配置多个步骤,这些步骤将针对每个分区逐个执行?

  • 我需要避免在Spring批处理项目中两次处理同一个文件。因此,我需要将文件名作为作业参数。然而,我只在步骤1中知道文件名,在作业执行之前不知道。因此,在启动作业时,我无法将文件名作为作业参数传递。我的问题是,在知道文件名后,是否有其他方法在步骤1中传递作业参数?

  • 我的Spring Batch配置有5个步骤,除了阅读器之外,所有步骤都是相同的。有没有一种方法可以把步骤的所有其他部分抽象成“父”步骤,这样我就不需要重复所有的事情?我知道这可以用XML完成,但是我不知道java的等价物。 以下是其中一个步骤: 以下是其中一位读者的定义:

  • 我目前正在构建一个spring批处理应用程序,其中执行了几个步骤。除了一个,所有的步骤都是简单的tasklet(没有读取器或写入器),它们负责各种任务,如复制文件、发送请求、启动批处理(*.bat)文件等。 大多数步骤应该是串行执行的。在一个特定的步骤中,我希望启动X文件,这些文件最多可以有Y个实例。 null 如果:)我想我必须使用taskExecutor,下面我有一个示例,在这里我开始第一步(