我有一个定义的块,其commit-interval为10,skip-limit为10.处理器类通过应用一些算术运算来操作一个字段。在处理器类中,其中一条记录发生异常(例如第6条记录)。在此之后,再次处理从1到5的记录,跳过第6个,处理7-10个并写入XML(自定义XML编写器类)。由于处理器处理1-5次记录两次,因此预期的字段值是错误的,因为它被计算两次。您能否建议一个解决方案让处理器只处理一次记录,只跳过失败的记录并将处理过的记录写入XML?
使用onSkipInProcess(),onSkipInRead(),onSkipInWrite()实现了SkipListener。但输出仍然相同。
jobconfig.xml
<batch:job id="job">
<batch:step id="step">
<batch:tasklet>
<batch:chunk reader="itemReader" writer="itemWriter"
processor="itemProcessor" commit-interval="10" skip-limit="5" retry-limit="0" >
<batch:skippable-exception-classes>
<batch:include class="java.lang.Exception"/>
</batch:skippable-exception-classes>
<batch:listeners>
<batch:listener ref="skipListener" />
</batch:listeners>
</batch:chunk>
</batch:tasklet>
</batch:step>
</batch:job>
<bean id="itemWriter" class="a.b.XWriter" scope="step"/>
<bean id="skipListener" class="a.b.SkipListener"/>
<bean id="itemProcessor" class="a.b.XProcessor" scope="step"/>
<bean id="itemReader" class="a.b.XReader"/>
ItemReader类:
public class XReader implements ItemReader {
@Autowired
private XRepository classDao;
private List lst = new ArrayList();
private int index= 0;
public Object read() throws Exception, UnexpectedInputException, ParseException, NonTransientResourceException {
if (lst.isEmpty()) {
lst = classDao.findAll();
}
if (index < lst.size()) {
return lst.get(index++);
} else return null;
}
}
ItemProcessor类:
public class XProcessor<T> implements ItemProcessor<T, T> {
public Object process(Object item) throws Exception {
// logic here
}
ItemWriter类:
public class XWriter <T> implements ItemWriter<T> {
public void write(List<? extends T> items) throws Exception {
// logic here to write to XML
}}
SkipListener类:
public class SkipListener<T,S> implements org.springframework.batch.core.SkipListener<T, S> {
public void onSkipInProcess(T arg0, Throwable arg1) {
}
public void onSkipInRead(Throwable arg0) {
}
public void onSkipInWrite(S arg0, Throwable arg1) {
}
}
答案 0 :(得分:2)
在容错步骤中使用ItemProcessor
时,它们应该是幂等的,因为存在多次调用它们的风险(如示例所示)。您可以在此处文档的第6.3.3节中详细了解这一点:http://docs.spring.io/spring-batch/reference/html/readersAndWriters.html
答案 1 :(得分:0)
您需要具有如下所示的侦听器实现。每当发生一些异常时,它会调用相应的方法,如果需要,您可以处理,否则只需将方法保留为空。所以它不会失败。
它也不会两次调用处理器。
xml配置:
<batch:listeners>
<batch:listener ref="recordSkipListener"/>
</batch:listeners>
听众课程:
public class RecordSkipListener implements SkipListener<Model> {
@Override
public void onSkipInRead(Throwable t) {
}
@Override
public void onSkipInWrite(Model item, Throwable t) {
}
@Override
public void onSkipInProcess(Model item, Throwable t) {
}
}