在Java Spring Integration中,变压器元素可以包含路由器功能吗?

dar*_*ipo 2 java spring spring-integration spring-annotations

我需要一个组件:

  1. 接收消息,对消息的有效负载和报头进行转换(到目前为止,它就像一个转换器).

  2. 然后,基于在标头路由上传递到适当信道的值(像标题路由器一样).

我想在java而不是XML中纯粹使用注释来配置它,但我绝对会采取我在这方面可以获得的内容.如果有人知道XML解决方案,请传递它.

如果它有帮助,我的用例是我希望变换器在消息有效负载上实现的转换依赖于自定义加载的头值.我还希望用于从变换器发送消息的通道依赖于标头值.

我知道涉及多个转换器的解决方案,每个转换类型一个,如标头值中所定义,然后是路由器.我试图避免这种解决方案,并且最多只使用一个路由器和单个变压器.

谢谢您的帮助.

Apo*_*psa 5

在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);
    }


}
Run Code Online (Sandbox Code Playgroud)

网关接口:

package demo;

public interface MyGateway {
    public void send(Object o);
}
Run Code Online (Sandbox Code Playgroud)

要调用的服务:

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);
    }

}
Run Code Online (Sandbox Code Playgroud)

集成配置:

<?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>
Run Code Online (Sandbox Code Playgroud)

最后是一个简单的集成测试:

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
    }

}
Run Code Online (Sandbox Code Playgroud)

输出:

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}]
Run Code Online (Sandbox Code Playgroud)

开发基于消息的系统的主要好处是,您可以使用易于测试,重用和更改的小型,松散耦合的组件来创建应用程序.创建在进程中扮演两个角色的组件会制动该规则.另外,如果您按照上面的方式创建代码,那么您的代码将与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>
Run Code Online (Sandbox Code Playgroud)