在 Spring Integration 中,通道充当任何其他 bean。您可以使用服务激活器来调用任何 bean 上的方法。该 bean 可以注入所需的通道。您可以使用@Qualifier 注释来选择应该注入哪个通道,或者只是自动装配一个Map<String, MessageChannel>,它将由通道的bean 名称索引。它可以将转换后的消息传递到这些通道。
一个 Spring Boot 应用程序:
package demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ImportResource;
import org.springframework.integration.config.EnableIntegration;
@SpringBootApplication
@EnableIntegration
@ImportResource("classpath:int.xml")
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
网关接口:
package demo;
public interface MyGateway {
public void send(Object o);
}
要调用的服务:
package demo;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.integration.support.MessageBuilder;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageChannel;
import org.springframework.stereotype.Service;
@Service
public class MyService {
private final Map<String, MessageChannel> channels;
@Autowired
public MyService(Map<String, MessageChannel> channels) {
super();
this.channels = channels;
}
public void transformAndRoute(Message<?> in) {
// do your business logic here
Message<?> out = MessageBuilder.fromMessage(in).build();
// if(something)...
channels.get("fooChannel").send(out);
}
}
集成配置:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:int="http://www.springframework.org/schema/integration"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/integration
http://www.springframework.org/schema/integration/spring-integration.xsd">
<int:gateway id="myGateway" service-interface="demo.MyGateway"
default-request-channel="inChannel" />
<int:service-activator input-channel="inChannel"
ref="myService" method="transformAndRoute" />
<int:channel id="inChannel" />
<int:logging-channel-adapter id="fooChannel" level="INFO" log-full-message="true"/>
</beans>
最后是一个简单的集成测试:
package demo;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes=DemoApplication.class)
public class MyGatewayIT {
@Autowired
MyGateway myGateway;
@Test
public void test() {
myGateway.send(new Object());
// do your assertions here
}
}
输出:
14:17:19.733 [main] DEBUG o.s.i.handler.LoggingHandler - org.springframework.integration.handler.LoggingHandler#0 received message: GenericMessage [payload=java.lang.Object@6f2cfcc2, headers={id=6791344c-07b4-d420-0d17-e2344f4bf15b, timestamp=1437826639733}]
但是
开发基于消息的系统的主要好处是您可以使用易于测试、重用和更改的小型松散耦合组件创建应用程序。创建一个在流程中扮演两个角色的组件会破坏该规则。此外,如果您按上述方式创建代码,则您的代码确实与 Spring Integration 相关联。相反,您可以做的是创建几个组件,每个组件都有一个单一的职责,然后将它们配置为链式运行。
您可以做的是创建一个转换器来修改消息的有效负载和标头。该转换器将封装您的业务逻辑并设置一个标头(例如,myRoutingHeader),以后可以在路由中使用。拥有一个用于业务逻辑的转换器和一个用于添加标头的标头丰富器可能会更好。但是让我们假设你在一个班级里做这件事。将该类定义为 bean(比如myTransformer)。然后在你的配置中:
<int:channel id="inChannel/>
<!-- if performance is important consider using a SpEL expression to
invoke your method instead as they can be configured to be compiled -->
<int:transformer ref="myTransformer" input-channel="inChannel"
method="transform" output-channel="routingChannel"/>
<int:channel id="routingChannel/>
<int:header-value-router input-channel="routingChannel" header-name="myRoutingHeader">
<int:mapping value="foo" channel="fooChannel" />
<int:mapping value="bar" channel="barChannel" />
</int:header-value-router>