如何在Spring Integration DSL Tcp中使用消息头进行路由

问题描述 投票:0回答:1

我有2个服务器端服务,我想使用消息头将消息路由到它们,远程客户端将服务标识放入字段type

从服务器端配置的代码片段是正确的方法吗?它抛出强制转换异常,表明route()只看到有效负载,而不是消息头。此外,Spring Integration手册中的所有示例仅显示基于有效负载的决策。

@Bean
public IntegrationFlow serverFlow( // common flow for all my services, currently 2
        TcpNetServerConnectionFactory serverConnectionFactory,
        HeartbeatServer heartbeatServer,
        FeedServer feedServer) {
    return IntegrationFlows
            .from(Tcp.inboundGateway(serverConnectionFactory))
            .<Message<?>, String>route((m) -> m.getHeaders().get("type", String.class),
                (routeSpec) -> routeSpec
                .subFlowMapping("hearbeat", subflow -> subflow.handle(heartbeatServer::processRequest))
                .subFlowMapping("feed", subflow -> subflow.handle(feedServer::consumeFeed)))
            .get();
}

客户端配置:

@Bean
public IntegrationFlow heartbeatClientFlow(
        TcpNetClientConnectionFactory clientConnectionFactory,
        HeartbeatClient heartbeatClient) {
    return IntegrationFlows.from(heartbeatClient::send,  e -> e.poller(Pollers.fixedDelay(Duration.ofSeconds(5))))
            .enrichHeaders(c -> c.header("type", "heartbeat"))
            .log()
            .handle(outboundGateway(clientConnectionFactory))
            .handle(heartbeatClient::receive)
            .get();
}

@Bean
public IntegrationFlow feedClientFlow(
        TcpNetClientConnectionFactory clientConnectionFactory) {
    return IntegrationFlows.from(FeedClient.MessageGateway.class)
            .enrichHeaders(c -> c.header("type", "feed"))
            .log()
            .handle(outboundGateway(clientConnectionFactory))
            .get();
}

像往常一样,这里有完整的演示版project codeClientConfigServerConfig

spring-integration spring-integration-dsl spring-integration-ip
1个回答
1
投票

没有标准的方法来通过原始TCP发送标头。您需要以某种方式将它们编码到有效负载中(并在服务器端提取它们)。

该框架提供了一种为您执行此操作的机制,但它需要额外的配置。

the documentation

特别...

MapJsonSerializer使用Jackson ObjectMapper在Map和JSON之间进行转换。您可以将此序列化程序与MessageConvertingTcpMessageMapperMapMessageConverter结合使用,以JSON格式传输选定的标头和有效负载。

我会尝试找一些时间来创建一个如何使用它的例子。

但是,当然,您可以自己编码/解码。

编辑

以下是使用JSON通过TCP传递邮件头的示例配置...

@SpringBootApplication
public class TcpWithHeadersApplication {

    public static void main(String[] args) {
        SpringApplication.run(TcpWithHeadersApplication.class, args);
    }

    // Client side

    public interface TcpExchanger {

        public String exchange(String data, @Header("type") String type);

    }

    @Bean
    public IntegrationFlow client(@Value("${tcp.port:1234}") int port) {
        return IntegrationFlows.from(TcpExchanger.class)
                .handle(Tcp.outboundGateway(Tcp.netClient("localhost", port)
                        .deserializer(jsonMapping())
                        .serializer(jsonMapping())
                        .mapper(mapper())))
                .get();
    }

    // Server side

    @Bean
    public IntegrationFlow server(@Value("${tcp.port:1234}") int port) {
        return IntegrationFlows.from(Tcp.inboundGateway(Tcp.netServer(port)
                        .deserializer(jsonMapping())
                        .serializer(jsonMapping())
                        .mapper(mapper())))
                .log(Level.INFO, "exampleLogger", "'Received type header:' + headers['type']")
                .route("headers['type']", r -> r
                        .subFlowMapping("upper",
                                subFlow -> subFlow.transform(String.class, p -> p.toUpperCase()))
                        .subFlowMapping("lower",
                                subFlow -> subFlow.transform(String.class, p -> p.toLowerCase())))
                .get();
    }

    // Common

    @Bean
    public MessageConvertingTcpMessageMapper mapper() {
        MapMessageConverter converter = new MapMessageConverter();
        converter.setHeaderNames("type");
        return new MessageConvertingTcpMessageMapper(converter);
    }

    @Bean
    public MapJsonSerializer jsonMapping() {
        return new MapJsonSerializer();
    }

    // Console

    @Bean
    @DependsOn("client")
    public ApplicationRunner runner(TcpExchanger exchanger,
            ConfigurableApplicationContext context) {

        return args -> {
            System.out.println("Enter some text; if it starts with a lower case character,\n"
                    + "it will be uppercased by the server; otherwise it will be lowercased;\n"
                    + "enter 'quit' to end");
            Scanner scanner = new Scanner(System.in);
            String request = scanner.nextLine();
            while (!"quit".equals(request.toLowerCase())) {
                if (StringUtils.hasText(request)) {
                    String result = exchanger.exchange(request,
                            Character.isLowerCase(request.charAt(0)) ? "upper" : "lower");
                    System.out.println(result);
                }
                request = scanner.nextLine();
            }
            scanner.close();
            context.close();
        };
    }

}
© www.soinside.com 2019 - 2024. All rights reserved.