你们好,java向导们,
我在进入 Spring 批处理时遇到了很多麻烦。现在直奔主题。我需要处理所有文件(xmls),然后他们将它们写回,有一个小的补充。问题是我想保留输入文件名。我对此的解决方案是一个MultiResourceItemReader,它委托给一个自定义ItemReader,该ItemReader又调用StaxEventItemReader并返回一个保存编组的XML和文件名。
- 问题**:在无限循环中只读取同一个文件,还有一件奇怪的事情,每次都有10次重试。我知道一个解决方案是读取器在读取文件后返回null,但这意味着我需要保留一个已处理文件的列表?
我想我现在就这么做,但我真的想要更聪明的东西。
作业配置:
<batch:job id="job1">
<batch:step id="step1" >
<batch:tasklet transaction-manager="transactionManager" start-limit="100" >
<batch:chunk reader="reader" writer="writer" commit-interval="10" />
</batch:tasklet>
</batch:step>
</batch:job>
<bean id="reader" class="org.springframework.batch.item.file.MultiResourceItemReader">
<property name="resources" value="files/*.xml" />
<property name="delegate" ref="myItemReader" />
</bean>
我的项目读取方法,基本上:
public class MyItemReader implements ResourceAwareItemReaderItemStream<MyItem>, ApplicationContextAware {
public MyItem read() throws Exception, UnexpectedInputException,
ParseException, NonTransientResourceException {
StaxEventItemReader<JAXBElement<RootObject>> reader = new StaxEventItemReader<JAXBElement<RootObject>>();
reader.setResource(currentResource);
reader.setFragmentRootElementName("RootObject");
// ... create jaxb unmarshaller
reader.setUnmarshaller(unmarshaller);
reader.setSaveState(true);
reader.afterPropertiesSet();
reader.open(executionContext);
JAXBElement<RootObject> jaxbElem = reader.read();
MyItem item = new MyItem();
item.setFilename(currentResource.getFile().getName());
item.setJaxbElement(jaxbElem);
return item;
}
}
有人能帮我解释一下吗?
- 解决方案**所以最后我只保留了一个读取文件的列表,如果已经被读取,则返回null。至于一次读取10个文件,嗯,这是块的大小,所以它是有意义的。
3条答案
按热度按时间hs1ihplo1#
我不认为你想在你的自定义阅读器中创建一个新的阅读器。我不知道这是否导致了你的问题,但这似乎不对(而且你在阅读后没有关闭它)。
您可以使用Spring初始化JAXB Context,然后将其注入到自定义读取器中:
http://static.springsource.org/spring-ws/site/reference/html/oxm.html
示例:
然后,在您的阅读器的
read()
方法中,只需使用解组器...好的,我认为问题出在
read()
方法上。根据ItemReader的Javadoc,当读取器中的所有项都用尽时,read()
方法应该返回null ......我不认为你这样做了,所以它是在无限期地读取。我认为找到一种扩展
FlatFileItemReader
或StaxEventItemReader
的方法是更好的方法...像这样的东西会不起作用吗?读者:
xj3cbfub2#
有必要让spring知道你什么时候已经完全读完了这个文件,为此你需要返回null。
保留一个布尔标记来指示文件是否已经处理。如果处理返回null。并再次将标记设置为false。
xienkqul3#
尝试覆盖doOpen()方法:
多资源项目读取器:
钉仓事件项目读取器:
否则(不好的做法),使用反射读取父类的“resource”属性