我是Spring Integration的新手,拥有一个接受文件作为输入的应用程序,并根据每个文件的内容对这些文件进行一些特定的处理。
当文件进来时,我有一个路由器决定是否输入“A”,“B”或“ZIP”文件并将其路由到适当的频道。在ZIP文件的情况下,我有一个拆分器,它解压缩zip文件并将结果发送回路由器,以确定zip中的文件类型是A,B还是嵌套的ZIP文件。
还指定了一个处理文件解析错误的错误通道。
XML的相关部分如下所示:
<?xml version="1.0" encoding="UTF-8"?>
...
...
<int:channel id="checkFile" />
<int:channel id="A" />
<int:channel id="B" />
<int:channel id="ZIP" />
<!-- Route the file to the appropriate parser - A, B, or ZIP -->
<int:router input-channel="checkFile" ref="fileTypeIdentifier" method="identifyType" />
<!-- If we have a ZIP file, extract the contents and process each one individually -->
<int:splitter input-channel="ZIP" output-channel="checkFile" ref="extractor" />
<!-- Parse file type A -->
<int:chain input-channel="A" output-channel="Done">
...
...
</int:chain>
<!-- Parse file type B -->
<int:chain input-channel="B" output-channel="Done">
...
...
</int:chain>
...
...
如果我的输入文件是包含file1.txt和file2.txt的myfile.zip,则路由器正确地将myfile.zip路由到拆分器,该拆分器成功提取file1.txt和file2.txt(并返回这2个文件)。 / p>
如果我在解析file1.txt时出错,我仍然想尝试解析file2.txt。所以在阅读Spring Integration: Splitter exception causes subsequent messages to abort之后,我尝试将我的“checkFile”频道设为队列频道,现在发生的是我传入myfile.zip,它被路由到“ZIP”频道,成功返回“file1.txt”和“ file2.txt“,然后路由器继续用”myfile.zip“无限循环调用。
使用执行程序通道而不是队列通道会导致类似的问题。
如何让我的流程解压缩文件并单独处理其内容,同时允许zip中的一个或多个文件失败而不会使整个作业失败?
答案 0 :(得分:0)
这里可能会占用很多位置,但无论如何我都会试着发布它:
<bean id="fileTypeIdentifier" class="org.springframework.integration.splitter.So43527224Tests$FileTypeIdentifier"/>
<bean id="fileParser" class="org.springframework.integration.splitter.So43527224Tests$FileParser"/>
<int:channel id="checkFile">
<int:queue/>
</int:channel>
<!-- Route the file to the appropriate parser - A, B, or ZIP -->
<int:router input-channel="checkFile" ref="fileTypeIdentifier" method="identifyType">
<int:poller fixed-delay="1000"/>
</int:router>
<!-- If we have a ZIP file, extract the contents and process each one individually -->
<int:splitter input-channel="ZIP" output-channel="checkFile"/>
<!-- Parse file type A -->
<int:service-activator input-channel="A" output-channel="nullChannel"
ref="fileParser" method="parseFileA"/>
<!-- Parse file type B -->
<int:service-activator input-channel="B" output-channel="nullChannel"
ref="fileParser" method="parseFileB"/>
测试班:
@RunWith(SpringRunner.class)
@DirtiesContext
public class So43527224Tests {
@Autowired
private MessageChannel checkFile;
@Test
public void testSo43527224() throws InterruptedException {
this.checkFile.send(new GenericMessage<>(2));
this.checkFile.send(new GenericMessage<>(3));
this.checkFile.send(new GenericMessage<>(Collections.singletonList(4)));
this.checkFile.send(new GenericMessage<>(Collections.singletonList(5)));
List<Object> zip = new ArrayList<>();
zip.add(6);
zip.add(7);
List<Integer> nestedZip = new ArrayList<>();
nestedZip.add(9);
nestedZip.add(8);
zip.add(nestedZip);
this.checkFile.send(new GenericMessage<>(zip));
Thread.sleep(10000);
}
private static class FileTypeIdentifier {
public String identifyType(Object payload) {
if (payload instanceof List) {
System.out.println("ZIP: " + payload);
return "ZIP";
}
else if (Integer.class.cast(payload) % 2 == 0) {
return "A";
}
else {
return "B";
}
}
}
private static class FileParser {
public String parseFileA(Object payload) {
throw new RuntimeException("intentional: A is always bad: " + payload);
}
public void parseFileB(Object payload) {
System.out.println("Good file B: " + payload);
}
}
}
日志看起来像这样(没有堆栈跟踪):
Caused by: java.lang.RuntimeException: intentional: A is always bad: 2
Good file B: 3
ZIP: [4]
ZIP: [5]
ZIP: [6, 7, [9, 8]]
Caused by: java.lang.RuntimeException: intentional: A is always bad: 4
Good file B: 5
Caused by: java.lang.RuntimeException: intentional: A is always bad: 6
Good file B: 7
ZIP: [9, 8]
Good file B: 9
Caused by: java.lang.RuntimeException: intentional: A is always bad: 8
所以,正如我之前所说:这里还有其他东西没有显示,以确定循环的原因。
您始终可以为DEBUG
类别启用org.springframework.integration
来分析您的消息在流程中的传输方式。