【问题标题】:Spring Integration Bridge - Request HeadersSpring Integration Bridge - 请求标头
【发布时间】:2017-04-24 18:23:36
【问题描述】:

我有一个使用 Bridge 桥接某些通道的 SI 应用程序。我希望通过网桥复制请求标头。当我调试应用程序时,我发现 BridgeHandler 有一个方法将 copyRequestHeaders() 设置为 false。 公共类 BridgeHandler 扩展 AbstractReplyProducingMessageHandler {

@Override
public String getComponentType() {
    return "bridge";
}

@Override
protected Object handleRequestMessage(Message<?> requestMessage) {
    return requestMessage;
}

@Override
protected boolean shouldCopyRequestHeaders() {
    return false;
}
}

我想更改它以使其保持真实。我查看了 Bridge 的 XSD,它似乎不支持任何条目来更改它,也没有引用自定义桥处理程序 bean。

我现在有什么选择?任何建议都会有所帮助。

spring-config.xml:

<beans:import resource="classpath*:spring/rabbit.xml" />
<beans:import resource="classpath*:spring/router.xml" />
<beans:import resource="classpath*:spring/file_persister.xml" />
<beans:import resource="classpath*:spring/transformer.xml" />   

<!-- Rabbit to Router -->
<int:bridge id="rabbitBridge" input-channel="rabbitInboundChannel" output-
channel="routerInputChannel" />

rabbit.xml:

<int:channel id="rabbitInboundChannel" />
<rabbit:connection-factory id="amqpConnectionFactoryInbound" 
 host="${rabbit.host}" port="${rabbit.port}"
 username="${rabbit.username}" password="${rabbit.password}" channel-cache-
 size="${rabbit.channelCacheSize}"
 connection-factory="rabbitConnectionFactoryInbound" />

 <beans:bean id="rabbitConnectionFactoryInbound" 
   class="com.rabbitmq.client.ConnectionFactory">
     <beans:property name="requestedHeartbeat" 
             value="${rabbit.requestedHeartBeat}" />
 </beans:bean>

 <!-- Inbound Adapter to AMQP RabbitMq -->
 <int-amqp:inbound-channel-adapter id="rabbitMQInboundChannelAdapter" 
    channel="rabbitInboundChannel" concurrent-
    consumers="${rabbit.concurrentConsumers}" task-executor="rabbit-
    executor" connection-factory="amqpConnectionFactoryInbound"
    message-converter="byteArrayToStringConverter" queue-
    names="${rabbit.queue}" error-channel="errorChannelId"
    prefetch-count="${rabbit.prefetchCount}" />

 <header-enricher input-channel="rabbitInboundChannel" output-
      channel="rabbitLoggingChannel">
             <int:header name="Operation" value="${operation.rabbit}" overwrite="true" />
            **<int:header name="GUID" expression="#{ 'T(java.util.UUID).randomUUID().toString()' }" />**
            <int:header name="operationStartTime" expression="#{ 'T(java.lang.System).currentTimeMillis()' }" />
  </header-enricher>

 <int:channel id="rabbitLoggingChannel">
  <int:interceptors>
    <int:wire-tap channel="loggerChannel" />
  </int:interceptors>
 </int:channel> 

 <task:executor id="rabbit-executor" rejection-policy="CALLER_RUNS" pool-
          size="${rabbit.poolSize}" queue-capacity="${rabbit.queueSize}" />

router.xml:

<int:channel id="routerInputChannel" />
 <int:header-enricher input-channel="routerInputChannel" output-
   channel="routerLoggingChannel">
 <int:header name="Operation" value="${operation.router}" overwrite="true" 
    />
 <int:header name="file_name" expression="headers['GUID'] + '.xml'" />
 <int:header name="operationStartTime" expression="#{ 
       'T(java.lang.System).currentTimeMillis()' }" overwrite="true" />
 <int:error-channel ref="errorChannelId" />
</int:header-enricher>

<int:recipient-list-router id="recipientListRouter" input-
        channel="routerInputChannel">
    <int:recipient channel="filePersistChannel" selector-expression="new 
          String(payload).length()>0" />
    <int:recipient channel="transformerInputChannel" />
</int:recipient-list-router>

<int:channel id="routerLoggingChannel">
    <int:interceptors>
        <int:wire-tap channel="loggerChannel" />
    </int:interceptors>
</int:channel> 

记录 O/P:

2017-04-24 13:26:33,360 [rabbit-executor-4] INFO 
       Operation="RABBIT_INBOUND_ADAPTER" Status="Success" DurationMs="0" 
       GUID="8d5c67c8-a0fb-4a7e-99dc-f545159dde7e"   
2017-04-24 13:26:33,361 [rabbit-executor-4] INFO Operation="ROUTER" 
       Status="Success" DurationMs="0" GUID=" "   
2017-04-24 13:26:33,364 [rabbit-executor-4] INFO Operation="FILE_PERSISTER" 
       Status="Success" DurationMs="3" GUID=" "   
2017-04-24 13:26:33,381 [rabbit-executor-5] INFO 
       Operation="ORDER_EVENT_TRANSFORMER" Status="Success" DurationMs="27" 
       GUID=" "   

如果您注意到,在 rabbit.xml 中设置的 GUID 标头不会传播到 router.xml,因此日志的 GUID 为空。如果没有网桥,则会打印 GUID。

【问题讨论】:

    标签: spring-integration bridge request-headers


    【解决方案1】:

    您不需要这样做。 &lt;bridge&gt; 基于 BridgeHandler 逻辑非常透明:

    @Override
    protected Object handleRequestMessage(Message<?> requestMessage) {
        return requestMessage;
    }
    

    所以,很明显 - 您的请求标头被传输,只是因为整个 requestMessage 传输到 outputMessage

    该方法背后的逻辑是这样的:

    protected Message<?> createOutputMessage(Object output, MessageHeaders requestHeaders) {
        AbstractIntegrationMessageBuilder<?> builder = null;
        if (output instanceof Message<?>) {
            if (!this.shouldCopyRequestHeaders()) {
                return (Message<?>) output;
            }
            builder = this.getMessageBuilderFactory().fromMessage((Message<?>) output);
        }
        else if (output instanceof AbstractIntegrationMessageBuilder) {
            builder = (AbstractIntegrationMessageBuilder<?>) output;
        }
        else {
            builder = this.getMessageBuilderFactory().withPayload(output);
        }
        if (this.shouldCopyRequestHeaders()) {
            builder.copyHeadersIfAbsent(requestHeaders);
        }
        return builder.build();
    }
    

    由于我们的 outputMessage 而我们不是 copyRequestHeaders(),因此没有任何改变,一切都对您有好处。

    我想知道是什么让你带着这样的问题来找我们,因为没有问题。

    困惑

    【讨论】:

    • 我的网桥是从 ChannelA 到 ChannelB。当消息发送到 ChannelA 时,我做了一个 header-enricher 并添加了一个新的 header。当消息通过上述 createOutputMessage() 方法发送到 ChannelB 时,我在请求标头中看不到新标头,我的假设是 shouldCopyRequestHeaders() 没有为我复制它。如果我错了,请纠正我。
    • 好的!分享,请从我们这边玩整个测试用例。这真的是不可能的......你可能还有别的东西
    • 我添加了一些示例代码。如果您有任何问题,请告诉我。在您粘贴的 createOutputMessage() 代码示例中,消息仅按原样发送到输出通道 if (!this.shouldCopyRequestHeaders()) 因为该方法默认返回“false”,new始终构建消息,这会丢失消息标头。这是我的理解。
    • 好吧,因为太多的代码,这不是很有帮助。我看到你有几个订阅rabbitInboundChannel,以及routerInputChannel。由于它们是DirectChannels,因此消息通过round-robin 方式处理给目标订阅者。这可能会让您感到困惑,因为有时消息只是没有发送到正确的组件。我猜你的情况是更丰富的标题。
    • ??? if (!this.shouldCopyRequestHeaders()) { return (Message&lt;?&gt;) output; }我错过了什么?您在该子句中的什么地方看到了新信息?
    猜你喜欢
    • 2018-10-15
    • 2013-11-13
    • 1970-01-01
    • 1970-01-01
    • 2020-02-22
    • 2016-11-24
    • 1970-01-01
    • 1970-01-01
    • 2012-03-03
    相关资源
    最近更新 更多