【问题标题】:Import job configurations into common job configuration class (Annotation config)将作业配置导入通用作业配置类(Annotation config)
【发布时间】:2021-04-07 13:34:55
【问题描述】:

我正在重构一个旧的基于 Spring Batch XML 的应用程序以改用注释配置。我想了解如何将以下 XML 文件转换为基于注释的配置并保持相同的关注点分离。

为了便于讨论,这里举一个简单的例子。

job-config-1.xml

<job id="job1" xmlns="http://www.springframework.org/schema/batch">
               <batch:step id="step1">
                    <batch:tasklet throttle-limit="20" task-executor="taskExecutor">
                        <batch:chunk reader="reader1"
                            writer="writer1" commit-interval="500" />
                    </batch:tasklet>
                </batch:step>
</job>

job-config-2.xml

<job id="job2" xmlns="http://www.springframework.org/schema/batch">
                   <batch:step id="step2">
                        <batch:tasklet throttle-limit="20" task-executor="taskExecutor">
                            <batch:chunk reader="reader2"
                                writer="writer2" commit-interval="500" />
                        </batch:tasklet>
                    </batch:step>
</job>

job-config-3.xml

<import
        resource="classpath*:/spring/jobs/job-config-1.xml" />
<import
        resource="classpath*:/spring/jobs/job-config-2.xml" />
<batch:job id="jobFlow">

            
    <batch:step id="step1" next="step2">
        <job ref="job1" job-launcher="jobLauncher" />
    </batch:step>

    <batch:step id="step2">
        <job ref="job2" job-launcher="jobLauncher" />
    </batch:step>
    
</batch:job>

我想从 XML 配置转移到 Java 配置。我想为每个 XML 创建 3 个作业配置类。比如说 JobConfig1.java、JobConfig2.java 和 JobConfig3.java。

JobConfig3.java 将导入 JobConfig1.java 和 JobConfig2.java;但是,我无法在文档中找到这种结构的示例。我该怎么做?

注意:我不打算使用 Spring Boot。只需通过注解配置进行常规 Spring Batch。

【问题讨论】:

  • @Atmas 抱歉,但这并不能回答我的问题。请阅读我的问题以了解我不是在问如何将 XML 转换为注释配置。我在问如何创建一个模块化作业,以便将两个作业插入在一起以创建第三个作业。
  • @Atmas :是的,我在问别的问题。想象一下两个 Spring 批处理作业 Job1 和 Job2,每个都有 10 个步骤。并且每个都有自己的 Spring Configuration 类。现在想象一下将 Job1 和 Job2 组合成一个合并作业的 Job3。 Job3 会有它自己的 Spring Configuration 类。如果不清楚,请参阅我的 XML 示例。我想将每个 XML 文件转换成它自己的配置类。我想我已经说得很清楚了。
  • @Atmas 我知道什么是流。我在问如何将两个不同配置类中定义的两个作业插入到第三个配置类中定义的第三个作业中。我的问题更多是关于 Job bean 导入等,而不是关于 Spring Batch 流 API。如果此评论仍未澄清我的问题,并且您的回答仍然是“使用流程”,那么我想您和我之间的讨论到此结束,因为显然您想回答一个不同的问题。我要问多个工作配置的问题。谢谢你,祝你有美好的一天。
  • 我已删除我的贡献,因为与您的帖子无关。
  • @Ping 我添加了一个答案,我相信它会用一个完整的例子回答你的问题。如果有帮助,请采纳:stackoverflow.com/help/someone-answers。否则,让我知道缺少什么来接受它。谢谢。

标签: java spring-batch


【解决方案1】:

相当于您的 XML 配置是在其自己的配置类中定义每个作业,然后在主作业的配置中导入这些类。这是一个简单的例子:

import org.springframework.batch.core.Job;
import org.springframework.batch.core.JobParameters;
import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;
import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
import org.springframework.batch.core.launch.JobLauncher;
import org.springframework.batch.repeat.RepeatStatus;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;

@Configuration
// @Import({Job1Config.class, Job2Config.class}) // use this if the classes where you define sub jobs are not nested
@EnableBatchProcessing
public class MainJobConfig {

    @Bean
    public Job mainJob(JobBuilderFactory jobs, StepBuilderFactory steps, Job job1, Job job2, JobLauncher jobLauncher) {
        return jobs.get("mainJob")
                .start(steps.get("subJob1").job(job1).launcher(jobLauncher).build())
                .next(steps.get("subJob2").job(job2).launcher(jobLauncher).build())
                .build();
    }
    
    @Configuration
    static class Job1Config {
        // define job 1 artefacts (reader, writer, steps, etc)
        // for simplicity, the step is inlined in the job definition
        @Bean
        public Job job1(JobBuilderFactory jobs, StepBuilderFactory steps) {
            return jobs.get("job1")
                    .start(steps.get("job1Step1").tasklet((contribution, chunkContext) -> {
                        System.out.println("job1");
                        return RepeatStatus.FINISHED;
                    }).build())
                    .build();
        }
    }

    @Configuration
    static class Job2Config {
        // define job 2 artefacts (reader, writer, steps, etc)
        // for simplicity, the step is inlined in the job definition
        @Bean
        public Job job2(JobBuilderFactory jobs, StepBuilderFactory steps) {
            return jobs.get("job2")
                    .start(steps.get("job2Step1").tasklet((contribution, chunkContext) -> {
                        System.out.println("job2");
                        return RepeatStatus.FINISHED;
                    }).build())
                    .build();
        }
    }

    public static void main(String[] args) throws Exception {
        ApplicationContext context = new AnnotationConfigApplicationContext(MainJobConfig.class);
        JobLauncher jobLauncher = context.getBean(JobLauncher.class);
        Job job = context.getBean("mainJob", Job.class);
        jobLauncher.run(job, new JobParameters());
    }

}

【讨论】:

    【解决方案2】:

    您可以使用JobStep 来定义您的步骤,例如在您的Job3step1 应该如下所示:

    @Autowired
    ApplicationContext context;
    
    public Step step1() {
        return stepBuilderFactory.get("step1").job(context.getBean("job1", Job.class))
                .parametersExtractor(new DefaultJobParametersExtractor()).build();
    }
    

    从此,您可以像任何其他步骤一样运行step1,但是当job3 对此步骤提出上诉时,job1 的所有步骤都将被执行。 job1 是您的负责人job3 的子工作。

    对于job1,他的定义应该是这样的:(同JobConfig2)

    @Configuration
    class JobConfig1 {
    
        @Autowired
        private JobBuilderFactory jobBuilderFactory;
    
        @Autowired
        private StepBuilderFactory stepBuilderFactory;
    
        @Bean
        public Job job1() {
            return jobBuilderFactory.get("job1").incrementer(new RunIdIncrementer()).start(step1()).build();
        }
    
        // definition of steps
        public Step step1() {
            return null;
        }
    }
    

    【讨论】:

    • 为我的无知道歉,但我不确定这也如何回答这个问题。一个稍微完整的例子会对我和其他读者有所帮助。
    • 即使进行了编辑,仍有未解决的问题。例如,如果您有 JobConfig1.java 和 JobConfig2.java,是否在它们上方添加 EnableBatchProcessing 注解? JobConfig3.java 呢,它应该也有 EnableBatchProcessing。更完整的答案将显示 JobConfig1.java、JobConfig2.java 和最后 JobConfig3.java 组装作业......
    • 您只有一个EnableBatchProcessing,它允许您的批处理bean 像JobRepository 一样注册,并且对于您的工作(JobConfig3.java...),它们中的每一个都应该用@Configuration 进行注释因为它定义了将在 spring 容器中注册的 bean。
    • 明白了,我会把这个 EnableBatchProcessing 放在哪里?在我的主课上还是在 JobConfig3.java 上?另外,我不能在 JobConfig3.java 中自动装配 Job 实例,而不是使用 applicationContext?
    • 是的,您可以在 JobConfig3 中自动连接您的作业,但在您的示例中,job1 和 job2 是 job3 的子作业。对于 EnableBatchProcessing 你把它放在你的主类中
    猜你喜欢
    • 2019-02-15
    • 1970-01-01
    • 2016-06-06
    • 2013-11-24
    • 1970-01-01
    • 1970-01-01
    • 2014-05-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多