大佬教程收集整理的这篇文章主要介绍了使用模块化作业方法在春季批次中进行主/从作业架构设计,大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。
我希望你做得很好。 我在春季批次中面临设计问题。
让我解释一下:
我有一个模块化的弹簧批处理作业架构, 每个作业都有自己的配置文件和上下文。 我正在设计一个主作业来启动子作业(50 多种子作业)。
X obj 具有其他名称、状态和 blob,其中包含附加到它的 csv 文件。 X obj 处理后会更新。 我遵循获取所有 X obj 然后循环(在 java 流中)调用适当作业的第一种方法。
但是这种方法有很多局限性。
所以我设计了一个带有读取器处理器和写入器的 masterJob。
@H_722_11@masterJob 应该读取 X obj 并调用适当的 subJob 并更新 X obj 的状态。
@H_26_2@masterJobReader 调用自定义服务来获取假设 X obj 的列表。我首先尝试从 masterJob 处理器中启动子作业,但没有成功。
我做了一些研究,我发现 JobStep 可能更适合这种情况。
但我对如何将 masterJobReader 读取的项目传递给 JobStep 有参数感到困惑。
我确实看到了 DefaultJobParameterExtractor 并且我尝试将 Item 设置为读取到 stepExecutionContext 但它不起作用。
我的问题是如何将参数从 MasterJob 传递给 SubJob 使用 JobStep 方法?
如果有更好的方法来解决这个问题,那么我就是你的了!
我使用的是 Java Config 和 Spring Batch 4.3。
编辑以提供示例代码:
@Configuration
public class MasterJob {
@Value("${defaultCompletionPolicy}")
private Integer defaultCompletionPolicy;
@autowired
protected StepBuilderFactory masterStepBuilderFactory;
private Logger logger = LoggerFactory.getLogger(MasterJob.class);
@autowired
protected JobRepository jobRepo;
@autowired
protected PlatformtransactionManager transactionManager;
@autowired
@QualifIEr("JOB_name1")
private Job JOB_name1; // this should change to be dynamic as there are around 50 types of job
@Bean(name = "masterJob")
protected Job masterBatchJob() throws APIException {
return new JobBuilderFactory(jobRepo).get("masterJob")
.incrementer(new RunIDIncrementer())
.start(masterJobStep(masterJobReader(),masterJobWriter()))
.next(jobStepJobStep1(null))
.next(masterupdateStep()) // update the state of objX
.build();
}
@Bean(name = "masterJobStep")
protected Step masterJobStep(@QualifIEr("masterJobReader") MasterJobReader masterReader,@QualifIEr("masterJobWriter") MasterJobWriter masterWriter) throws APIException {
logger.deBUG("insIDe masterJobStep");
return this.masterStepBuilderFactory.get("masterJobStep")
.<Customer,Customer>chunk(defaultCompletionPolicy)
.reader(masterJobReader())
.processor(masterJobProcessor())
.writer(masterJobWriter())
.transactionManager(transactionManager)
.Listener(new MasterJobWriter()) // I set the parameter insIDe this.
.Listener(masterPromotionListener())
.build();
}
@Bean(name = "masterJobWriter",destroymethod = "")
@StepScope
protected MasterJobWriter masterJobWriter() {
return new MasterJobWriter();
}
@Bean(name = "masterJobReader",destroymethod = "")
@StepScope
protected MasterJobReader masterJobReader() throws APIException {
return new MasterJobReader();
}
protected FIEldSetMapper<Customer> mapper() {
return new CustomerMapper();
}
@Bean(name="masterPromotionListener")
public ExecutionContextPromotionListener masterPromotionListener() {
ExecutionContextPromotionListener Listener = new ExecutionContextPromotionListener();
Listener.setKeys(
new String[]
{
"inputfile","outputfile","customerID","comments","customer"
});
//Listener.setStrict(true);
return Listener;
}
@Bean(name = "masterupdateStep")
public Step masterupdateStep() {
return this.masterStepBuilderFactory.get("masterCleanStep").tasklet(new Masterupdatetasklet()).build();
}
@Bean(name = "masterJobProcessor",destroymethod = "")
@StepScope
protected MasterJobProcessor masterJobProcessor() {
return new MasterJobProcessor();
}
@Bean
public Step jobStepJobStep1(JobLauncher jobLauncher) {
return this.masterStepBuilderFactory.get("jobStepJobStep1")
.job(JOB_name1)
.launcher(jobLauncher)
.parametersExtractor(jobParametersExtractor())
.build();
}
@Bean
public DefaultJobParametersExtractor jobParametersExtractor() {
DefaultJobParametersExtractor extractor = new DefaultJobParametersExtractor();
extractor.setKeys(
new String[] { "inputfile","customer" });
return extractor;
}
}
这是我在 @H_511_7@masterJobWriter 中设置参数的方式:
String inputfile = fetchinputfile(customer);
String outputfile = buildOutputfilename(customer);
Comments comments = "comments"; // from business logic
ExecutionContext stepContext = this.stepExecution.getExecutionContext();
stepContext.put("inputfile",inputfilE);
stepContext.put("outputfile",outputfilE);
stepContext.put("customerID",customer.getCustomerID());
stepContext.put("comments",new CustomJobParameter<Comments>(comments));
stepContext.put("customer",new CustomJobParameter<Customer>(customer));
我关注春批的this section of the documentation
我的问题是如何使用 JobStep 方法将参数从 MasterJob 传递到 SubJob?
JobParametersExtractor 正是您要找的。它允许您从主作业中提取参数并将它们传递给子作业。您可以找到示例 here。
编辑:根据评论添加建议
我在数据库中有一个 X obj 列表。 X obj 包含其他字段、id、类型(工作)、名称、状态和 blob,其中包含附加到它的 csv 文件。包含 csv 文件的 blob 字段取决于类型字段,因此它不是一种模式 csv 文件。我需要处理每个 X obj 并将 csv 文件的内容保存在数据库中,并生成一个 csv 结果文件,其中包含原始数据和结果 csv 文件中的注释字段,并使用附加到 X 的结果 csv 字段更新 X obj 状态obj 等字段。
如您所见,对于单个 X 对象,该过程已经很复杂。因此,尝试在同一作业中处理所有 X 对象太复杂了恕我直言。 So much complexity in software comes from trying to make one thing do two things..
如果有更好的方法来解决这个问题,那么我就是你的了!
既然您愿意接受建议,我将推荐两个选项:
选项 1:
如果由我决定,我会为每个 X obj 创建一个作业实例。这样,我可以 1) 并行化事情,2) 在失败的情况下,只重启失败的工作。这两个特性(可扩展性和可重启性)对于工作的工作方法几乎是不可能的。即使你有很多 X 对象,这也不是问题。您可以使用 Spring Batch 提供的一种扩展技术来并行处理事物。
选项 2:
如果你真的不能或不想使用不同的作业实例,你可以使用一个单一的作业和一个面向块的步骤,迭代 X 对象列表。处理逻辑似乎独立于一条记录到另一条记录,因此这一步应该很容易通过多个线程进行扩展。
以上是大佬教程为你收集整理的使用模块化作业方法在春季批次中进行主/从作业架构设计全部内容,希望文章能够帮你解决使用模块化作业方法在春季批次中进行主/从作业架构设计所遇到的程序开发问题。
如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。
本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。