通过 Spring 批量作业步骤维护作业前对象
Maintain pre-job object through Spring Batch job steps
对于我的批处理应用程序,在执行 Spring 批处理作业之前,我需要执行一些步骤。例如,我需要执行特定查询并将数据存储在 属性 - 具有复杂类型的列表 (List<ComplexType>
) - 以便它可以在整个 Spring 中使用和操作批处理作业(主要在 ItemReader 中)。
我试过在我的列表中自动装配并在步骤中访问它,但我无法那样访问列表中的数据。我在我的列表中得到一个空的 ComplexType,无论在工作之前我的自动装配列表 属性 添加了什么值。
我也试过 passing data using ExecutionContext,但我不认为这应该在 Spring 批处理作业执行之外工作。
我想知道的是,在执行 Spring 批处理作业之前填充项目并在作业的整个生命周期中维护该对象的最佳方法是什么。
如果最好的方法是我之前所做的尝试之一,欢迎提供有关这些方法常见错误的任何指导,谢谢。
你可以这样做:)
尝试在作业参数增量技巧中做到这一点:
<j:job id="Your_job" incrementer="incrementerBean">
和
<bean id="incrementerBean" class="com.whatever.IncrementerClass"/>
递增器class:
class IncrementerClass implements JobParametersIncrementer {
@Override
JobParameters getNext(JobParameters parameters) {
Map<String, JobParameter> map = new HashMap<String, JobParameter>(
parameters.getParameters());
...
//you can put here your list, if it can be :
// Domain representation of a parameter to a batch job. Only the following types
// can be parameters: String, Long, Date, and Double.
//make some query
List<String> listStrings = Query.getYourQuery();
//Join your query into string to have something like this below
map.put("listOfSomething", new JobParameter("abc, abc, abc"));
...
return new JobParameters(map);
}
}
就是这样,
然后您可以在某些处理 bean 中使用此参数:
@Value("#{jobParameters['listOfSomething']}")
private String yourList
您可以从字符串构建列表,仅此而已:)
祝你好运
感谢 Luca Basso Ricci 的 JobExecutionListener
指点。我最终创建了自己的 StepExecutionListener
进行预处理的地方。
我关注了 this example from Mkyong,其中介绍了不同类型的 Spring 批处理监听器。
我在 Java 代码中创建了一个像这样的自定义侦听器:
public class CustomStepListener implements StepExecutionListener {
@Autowired
private CustomObject customObject;
@Override
public void beforeStep(StepExecution stepExecution) {
// initialize customObject and do other pre set setup
}
@Override
public ExitStatus afterStep(StepExecution stepExecution) {
return null;
}
并且我在这里初始化了自动装配 CustomObject
class。 CustomObject
class 是一个自定义对象,仅包含我的 List
类型 ComplexType
。
@Component
public class CustomObject {
private List<ComplexType> customObjectList;
public List<ComplexType> getCustomObjectList() {
return customObjectList;
}
public void setCustomObjectList(List<ComplexType> customObjectList) {
this.customObjectList= customObjectList;
}
}
最后,在我的作业配置中 'batch-job-context.xml' 我添加了我的新侦听器:
<!-- ... -->
<beans:bean id="customStepListener"
class="com.robotsquidward.CustomStepListener"/>
<job id="robotsquidwardJob"
job-repository="jobRepository"
incrementer="runIdIncrementer">
<step id="robotsquidwardStep">
<tasklet task-executor="taskExecutor" throttle-limit="1">
<chunk
reader="robotsquidwardReader"
processor="robotsquidwardProcessor"
writer="robotsquidwardWriter"
commit-interval="1"/>
</tasklet>
<listeners>
<listener ref="customStepListener"/>
</listeners>
</step>
</job>
当我按照这些步骤操作时,我能够在 beforeJob
函数中初始化我的 ComplexObject
List
并访问 ComplexObject
List
的值在我的工作范围内 Reader class:
@Component
@Scope(value = "step")
public class RobotsquidwardReader implements ItemReader<ComplexType> {
@Autowired
private CustomObject customObject;
@Override
public ComplexType read() throws Exception, UnexpectedInputException,
ParseException, NonTransientResourceException {
if(customObject.getCustomObjectList() != null) {
return customObject.getCustomObjectList.remove(0);
} else {
return null;
}
}
}
就这么简单。只需要两个新的 classes、一个配置更改和一个令人头疼的问题:)
对于我的批处理应用程序,在执行 Spring 批处理作业之前,我需要执行一些步骤。例如,我需要执行特定查询并将数据存储在 属性 - 具有复杂类型的列表 (List<ComplexType>
) - 以便它可以在整个 Spring 中使用和操作批处理作业(主要在 ItemReader 中)。
我试过在我的列表中自动装配并在步骤中访问它,但我无法那样访问列表中的数据。我在我的列表中得到一个空的 ComplexType,无论在工作之前我的自动装配列表 属性 添加了什么值。
我也试过 passing data using ExecutionContext,但我不认为这应该在 Spring 批处理作业执行之外工作。
我想知道的是,在执行 Spring 批处理作业之前填充项目并在作业的整个生命周期中维护该对象的最佳方法是什么。
如果最好的方法是我之前所做的尝试之一,欢迎提供有关这些方法常见错误的任何指导,谢谢。
你可以这样做:) 尝试在作业参数增量技巧中做到这一点:
<j:job id="Your_job" incrementer="incrementerBean">
和
<bean id="incrementerBean" class="com.whatever.IncrementerClass"/>
递增器class:
class IncrementerClass implements JobParametersIncrementer {
@Override
JobParameters getNext(JobParameters parameters) {
Map<String, JobParameter> map = new HashMap<String, JobParameter>(
parameters.getParameters());
...
//you can put here your list, if it can be :
// Domain representation of a parameter to a batch job. Only the following types
// can be parameters: String, Long, Date, and Double.
//make some query
List<String> listStrings = Query.getYourQuery();
//Join your query into string to have something like this below
map.put("listOfSomething", new JobParameter("abc, abc, abc"));
...
return new JobParameters(map);
}
}
就是这样, 然后您可以在某些处理 bean 中使用此参数:
@Value("#{jobParameters['listOfSomething']}")
private String yourList
您可以从字符串构建列表,仅此而已:) 祝你好运
感谢 Luca Basso Ricci 的 JobExecutionListener
指点。我最终创建了自己的 StepExecutionListener
进行预处理的地方。
我关注了 this example from Mkyong,其中介绍了不同类型的 Spring 批处理监听器。
我在 Java 代码中创建了一个像这样的自定义侦听器:
public class CustomStepListener implements StepExecutionListener {
@Autowired
private CustomObject customObject;
@Override
public void beforeStep(StepExecution stepExecution) {
// initialize customObject and do other pre set setup
}
@Override
public ExitStatus afterStep(StepExecution stepExecution) {
return null;
}
并且我在这里初始化了自动装配 CustomObject
class。 CustomObject
class 是一个自定义对象,仅包含我的 List
类型 ComplexType
。
@Component
public class CustomObject {
private List<ComplexType> customObjectList;
public List<ComplexType> getCustomObjectList() {
return customObjectList;
}
public void setCustomObjectList(List<ComplexType> customObjectList) {
this.customObjectList= customObjectList;
}
}
最后,在我的作业配置中 'batch-job-context.xml' 我添加了我的新侦听器:
<!-- ... -->
<beans:bean id="customStepListener"
class="com.robotsquidward.CustomStepListener"/>
<job id="robotsquidwardJob"
job-repository="jobRepository"
incrementer="runIdIncrementer">
<step id="robotsquidwardStep">
<tasklet task-executor="taskExecutor" throttle-limit="1">
<chunk
reader="robotsquidwardReader"
processor="robotsquidwardProcessor"
writer="robotsquidwardWriter"
commit-interval="1"/>
</tasklet>
<listeners>
<listener ref="customStepListener"/>
</listeners>
</step>
</job>
当我按照这些步骤操作时,我能够在 beforeJob
函数中初始化我的 ComplexObject
List
并访问 ComplexObject
List
的值在我的工作范围内 Reader class:
@Component
@Scope(value = "step")
public class RobotsquidwardReader implements ItemReader<ComplexType> {
@Autowired
private CustomObject customObject;
@Override
public ComplexType read() throws Exception, UnexpectedInputException,
ParseException, NonTransientResourceException {
if(customObject.getCustomObjectList() != null) {
return customObject.getCustomObjectList.remove(0);
} else {
return null;
}
}
}
就这么简单。只需要两个新的 classes、一个配置更改和一个令人头疼的问题:)