首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >弹簧-集成:外部路由选择

弹簧-集成:外部路由选择
EN

Stack Overflow用户
提问于 2019-02-18 07:14:58
回答 1查看 197关注 0票数 1

我希望允许来电者传递外部选路滑,例如通过张贴:

代码语言:javascript
复制
POST http://localhost:8080/transform?routing-slip=capitalize&routing-slip=lowercase
Content-Type: text/plain

camelCase

应该可以将给定的路由滑移数组用作pojo的外部路由提示:

代码语言:javascript
复制
@Bean
public IntegrationFlow transformerChain(RoutingSlipRouteStrategy routeStrategy) {
    return IntegrationFlows.from(
        Http.inboundGateway("/transform")
            .headerExpression("routingSlipParam", 
                    "#requestParams['routing-slip']")
            .requestPayloadType(String.class))
        .enrichHeaders(spec -> spec.header(
            IntegrationMessageHeaderAccessor.ROUTING_SLIP,
              new RoutingSlipHeaderValueMessageProcessor(
                 "@routePojo.get(request, reply)")
              )
        )
        .logAndReply();
}

pojo可以访问routingSlipParam头,您可能会认为它可以将滑块保持为内部状态,或者至少这是TestRoutingSlipRoutePojo引导我所相信的,所以我构建了它(考虑到只有一个pojo实例):

代码语言:javascript
复制
public class ExternalRoutingSlipRoutePojo {

    private List<String> routingSlip;
    private int i = 0;

    public String get(Message<?> requestMessage, Object reply) {
        if (routingSlip == null) {
            routingSlip = (LinkedList)requestMessage.getHeaders()
                .get("routingSlipParam");
        }
        try {
            return this.routingSlip.get(i++);
        } catch (Exception e) {
            return null;
        }
    }

}

事实证明,这只工作了一次,这一点也就不足为奇了--每次传入的消息都会增加索引,而路由选择从不会被更新。

所以我想,当然,我必须保持所有传入消息的内部状态,并想出了这个RouteStrategy:

代码语言:javascript
复制
public class ExternalRoutingSlipRouteStrategy implements RoutingSlipRouteStrategy {

  private Map<UUID, LinkedList<String>> routingSlips = new WeakHashMap<>();
  private static final LinkedList EMPTY_ROUTINGSLIP = new LinkedList<>();

  @Override
  public Object getNextPath(Message<?> requestMessage,Object reply) {
    MessageHeaders headers = requestMessage.getHeaders();

    UUID id = headers.getId();
    if (!routingSlips.containsKey(id)) {
        @SuppressWarnings("unchecked")
        List<String> routingSlipParam = 
            headers.get("routingSlipParam", List.class);
        if (routingSlipParam != null) {
            routingSlips.put(id, 
                new LinkedList<>(routingSlipParam));
        }
    }
    LinkedList<String> routingSlip = routingSlips.getOrDefault(id,
        EMPTY_ROUTINGSLIP);
    String nextPath = routingSlip.poll();
    if (nextPath == null) {
        routingSlips.remove(id);
    }
    return nextPath;
  }
}

这也不起作用,因为不仅对传入消息调用策略,而且对由动态路由创建的所有新消息也调用策略,动态路由当然具有不同的ID。

但是它只对原始消息调用两次,因此路由选择不会耗尽,并且应用程序将在一个无休止的循环中运行。

如何使弹簧集成使用外部路由选择单?

更新:

正如Gary所建议的,外部路由选择索引和外部路由选择本身都不应该存储在Spring中,而是可以使用消息头来为每个请求分别维护它们:

代码语言:javascript
复制
Http.inboundGateway("/transform")
    .headerExpression("routingSlipParam",
            "#requestParams['routing-slip']")
    .requestPayloadType(String.class))
.enrichHeaders(spec -> spec
    .headerFunction("counter",h -> new AtomicInteger())
    .header(IntegrationMessageHeaderAccessor.ROUTING_SLIP,
        new RoutingSlipHeaderValueMessageProcessor(externalRouteStrategy)
    )
)

externalRouteStrategy是以下类的实例:

代码语言:javascript
复制
public class ExternalRoutingSlipRouteStrategy implements 
        RoutingSlipRouteStrategy {

    @Override
    public Object getNextPath(Message<?> requestMessage, Object reply) {

        List<String> routingSlip = (List<String>) 
            requestMessage.getHeaders().get("routingSlipParam");

        int routingSlipIndex = requestMessage.getHeaders()
            .get("counter", AtomicInteger.class)
            .getAndIncrement();

        String routingSlipEntry;
        if (routingSlip != null 
            && routingSlipIndex < routingSlip.size()) {

            routingSlipEntry = routingSlip.get(routingSlipIndex);
        } else {
            routingSlipEntry = null;
        }
        return routingSlipEntry;
    }
}

作为参考,我已经在Github中发表了这个示例。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-02-18 18:13:49

回到您的第一个版本,并将i存储在标题中的消息头(AtomicInteger)中。

代码语言:javascript
复制
.headerExpression("counter", "new java.util.concurrent.atomic.AtomicInteger()")

然后

代码语言:javascript
复制
int i = requestMessage.getHeaders().get("counter", AtomicInteger.class).getAndIncrement();
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/54742107

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档