簡體   English   中英

Spring Integration Message Router能夠記錄輸出通道目標名稱

[英]Spring Integration Message Router ability to log output channel Destination name

我們正在使用Spring Integration 4.2.0。 我們有一個使用消息Router的流程,並且希望能夠記錄一條消息路由到的位置(實際Destination名稱,理想情況下是Destination類型以及原始有效負載)。 在我們的例子中,我們的路由器具有以JmsSendingMessageHandler為端點的輸出通道。 我們希望在日志中看到以下內容:

[INFO ] message routed to [amq | queue://QUEUE1] : This is a message!
[INFO ] message routed to [wmq | queue://QUEUE2] : This is also a message!
[INFO ] message routed to [ems | queue://QUEUE3] : This is also a message!
[INFO ] message routed to [wmq | topic://TOPIC1] : This is also a message!

路由器配置與此類似:

<int:router id="messageRouter"
    input-channel="inputChannel"
    resolution-required="false"
    ref="messageRouterServiceImpl"
    method="route"
    default-output-channel="unroutedChannel">
    <int:mapping value="channelAlias1" channel="channel1" />
    <int:mapping value="channelAlias2" channel="channel2" />
    <int:mapping value="channelAlias3" channel="channel3" />  
    <int:mapping value="routerErrorChannel" channel="routerErrorChannel"/>
    <int:mapping value="nullChannel" channel="nullChannel"/>
</int:router>

我有一個解決方案,但是我會承認它有點難看,因為它查詢Spring ApplicationContext然后使用反射來最終獲得Destination的名稱。
或者,我想我可以在路由器輸出到的每個通道的前面放置一個記錄器,但是試圖避免重復記住要為我們使用路由器的每個流執行此操作。

我想知道是否有人建議采用一種更清潔的方法。 如果您願意,我可以分享我的代碼。 也許Spring Integration Java DSL將對此有所幫助?

可以掛接的點之一是<int:wire-tap> -特定通道的全局ChannelInterceptor (通過其名稱的模式)。

WireTap可以將消息發送到<int:logging-channel-adapter>或任何其他自定義服務,以通過所需方式進行日志記錄或執行其他任何操作。

<int:message-history>是另一個適合您的即用型功能。 這樣,您將獲得一條path ,包括路由邏輯,如何將消息傳遞通過您的流程。 您可以在MessageHeaders找到它。

如果我正確理解了您的用例,那么您想要

  • 路由器在成功將消息發送到預期目標后記錄此信息。
  • 您不想放置記錄器,因為它將被強制附加到路由器的每個新流上

我能想到的一種方法是-

1-擴展MethodInvokingRouter用於您的自定義路由器實現。

2-覆蓋AbstractMessageRouter類中的handleMessageInternal方法。

這是代碼段-

public class CustomRouter extends MethodInvokingRouter {

Logger log = Logger.getLogger(CustomRouter.class);

Map<Message<?>,String> m = new ConcurrentHashMap<>();

public CustomRouter(Object object, Method method) {
    super(object, method);
}

public CustomRouter(Object object, String methodName) {
    super(object, methodName);
}

public CustomRouter(Object object) {
    super(object);
}

public String route(Message<?> message) {
    String destinationName = null;
    /*
     * Business logic to get destination name
     */

    destinationName = "DERIVED VALUE AS PER THE ABOVE BUSINESS LOGIC";
    //NOTE:- here also we can log (optimistic way of saying that messages are being routed to...), but at this point of time we are not sure whether the returned string value will get resolved to a message channel and message will be routed to the destination. 

    //Put that name to map so that it can be extracted later on in handleMessageInternal method
    m.put(message, destinationName); // O(1) complexity
    return destinationName;         
} 



@Override
protected void handleMessageInternal(Message<?> message) {
    super.handleMessageInternal(message);
    //At this point we are quit sure that channel has been resolved and message has been sent to destination

    /*
     * get the destination name returned from route method from populated map 
     * 
     * As at this point we know whatever return value was (from route method), there exists a message channel.
     * 
     */
    String key = m.get(message);
    // get the key-value pair for channel mapping
    Map<String,String> mappedChannelMap = super.getChannelMappings();

    // get destination name where message is routed
    String destinationName = mappedChannelMap.get(key);   // O(1) complexity 

    //Now log to a file as per the requirement
    log.info("message routed to "+destinationName+" Message is- "+message.getPayload().toString());

}

}

我沒有嘗試過這段代碼,可能存在一些改進。 你是怎么想的

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM