我使用Spring Integration解析XML文件,我需要为每个标记创建一个线程(每个线程都有不同的速率)。
现在(在许多用户的帮助下:) :)我能够按标签拆分XML,然后将其路由到合适的service-activator
。
这很有效,但是我无法重定向到创建"线程"然后执行操作。现在我有以下配置,在我的脑海里(我不知道它是否正确......)
Split tag -> Route to the appropiate channel -> Start a thread(from tag configuration) -> Execute the operation
这是我拆分标签并重定向到频道的实际配置。 路由器应该不直接重定向到某个频道,而是安排它们。
在第一个实例中,它应该在固定速率的池中重定向它,然后我将使用XPATH来获取属性,然后替换它" fixed"使用正确的价值率。
我已经尝试了许多解决方案来创建此流程,但每个解决方案都失败或无法编译:(
<context:component-scan base-package="it.mypkg" />
<si:channel id="rootChannel" />
<si-xml:xpath-splitter id="mySplitter" input-channel="rootChannel" output-channel="routerChannel" create-documents="true">
<si-xml:xpath-expression expression="//service" />
</si-xml:xpath-splitter>
<si-xml:xpath-router id="router" input-channel="routerChannel" evaluate-as-string="true">
<si-xml:xpath-expression expression="concat(name(./node()), 'Channel')" />
</si-xml:xpath-router>
<si:service-activator input-channel="serviceChannel" output-channel="endChannel">
<bean class="it.mypkg.Service" />
</si:service-activator>
更新
对service
使用此配置,这应该每10秒运行一次任务(id=service1
),另外5秒运行一次任务(id=service2
)。以同样的方式,我可以有另一个标记,由另一个类处理(因为这将有另一个行为)
<root>
<service id="service1" interval="10000" />
<service id="service2" interval="5000" />
<activity id="activity1" interval="50000" />
<root>
我将有一个classe(Service
),它是处理服务标签的一般方法,这完成了一些操作然后&#34;返回我&#34;这个值可以重定向到另一个频道。
public class Service {
public int execute() {
// Execute the task and return the value to continue the "chain"
}
}
答案 0 :(得分:0)
一点也不清楚你的意思;你拆分了一个标签;路线,但希望&#34;安排&#34;它在XML中的速度。它并不清楚你的意思是什么?&#34; schedule&#34;这里 - 通常每个消息按时间表处理一次不会多次。
正如我所说,我不明白你需要做什么,但smart poller可能是合适的。
另一种可能性是delayer,其中可以从消息中推导出延迟量。
修改强>
由于您的服务&#34;似乎不接受任何输入数据,看起来您只需要为每个服务配置/启动<inbound-channel-adapter/>
,然后根据XML中的参数启动它。
<int:inbound-channel-adapter id="service1" channel="foo"
auto-startup="false"
ref="service1Bean" method="execute">
<poller fixed-delay="1000" />
</int:inbound-channel-adapter/>
注意auto-startup="false"
。
现在,在接收拆分的代码中
@Autowired
SourcePollingChannelAdapter service1;
...
public void startService1(Node node) {
...
service1.setTrigger(new PeridicTrigger(...));
service1.start();
...
}
答案 1 :(得分:0)
我不知道这是否是实现流程的正确方法,但我已经编写了以下代码:
的applicationContext.xml
<context:component-scan base-package="it.mypkg" />
<!-- Expression to extract interval from XML tag -->
<si-xml:xpath-expression id="selectIntervalXpath" expression="//*/@interval" />
<si:channel id="rootChannel" />
<!-- Split each tag to redirect on router -->
<si-xml:xpath-splitter id="mySplitter" input-channel="rootChannel" output-channel="routerChannel" create-documents="true">
<si-xml:xpath-expression expression="//service|//activity" />
</si-xml:xpath-splitter>
<!-- Route each tag to the appropiate channel -->
<si-xml:xpath-router id="router" input-channel="routerChannel" evaluate-as-string="true">
<si-xml:xpath-expression expression="concat(name(./node()), 'Channel')" />
</si-xml:xpath-router>
<!-- Activator for Service Tag -->
<si:service-activator input-channel="serviceChannel" method="schedule">
<bean class="it.mypkg.Service" />
</si:service-activator>
<!-- Activator for Activity Tag -->
<si:service-activator input-channel="activityChannel" method="schedule">
<bean class="it.mypkg.Activity" />
</si:service-activator>
<!-- Task scheduler -->
<task:scheduler id="taskScheduler" pool-size="10"/>
每个标记都将扩展一个Operation类(以避免bean注入时的代码重复)
Operation.java
public abstract class Operation {
protected TaskScheduler taskScheduler;
protected XPathExpression selectIntervalXpath;
abstract public void schedule(Node document);
@Autowired
public void setTaskScheduler(TaskScheduler taskScheduler) {
this.taskScheduler= taskScheduler;
}
public TaskScheduler getTaskScheduler() {
return this.taskScheduler;
}
@Autowired
public void setSelectIntervalXpath(XPathExpression selectIntervalXpath) {
this.selectIntervalXpath = selectIntervalXpath;
}
public XPathExpression getSelectIntervalXPath() {
return this.selectIntervalXpath;
}
}
Service类的一个示例(处理.xml上提供的所有标记service
)
public class Service extends Operation {
private static final Logger log = Logger.getLogger(Service.class);
@Override
public void schedule(Node document) {
log.debug("Scheduling Service");
long interval = Long.parseLong(this.selectIntervalXpath.evaluateAsString(document));
this.taskScheduler.scheduleAtFixedRate(new ServiceRunner(), interval);
}
private class ServiceRunner implements Runnable {
public void run() {
log.debug("Running...");
}
}
}
现在继续我的流程我将需要找到一种方法将每个作业的输出重定向到Spring Integration(applicationContext.xml)。