【问题标题】:Using @JmsListener with multiple payload types for the same destination?将@JmsListener 与多个有效负载类型一起用于同一目的地?
【发布时间】:2017-07-28 03:30:55
【问题描述】:

我可以将多种类型的实例写入给定的目的地,例如:

JmsTemplate template = ...
Alpha alpha = new Alpha(...);
Beta beta = new Beta(...);

template.convertAndSend("my-destination", alpha);
template.convertAndSend("my-destination", beta);

我想我可以提供多个 @JmsListener 带注释的方法来接收不同的消息负载 - 就像这样:

@JmsListener(destination = "my-destination")
public void receiveAlpha(Alpha alpha) { ... }

@JmsListener(destination = "my-destination")
public void receiveBeta(Beta beta) { ... }

但如果我尝试这样做,我会在 PayloadArgumentResolver.resolveArgument 中遇到异常,因为它无法区分应该将 Beta 值发送到一个方法和将 Alpha 值发送到另一个方法。

我应该如何处理这个问题?当我将有效负载类型编码为消息属性时,我可以指定一个选择器来让事情像这样工作:

@JmsListener(destination = "my-destination", selector = "_type = 'Alpha'")
public void receiveAlpha(Alpha alpha) { ... }

@JmsListener(destination = "my-destination", selector = "_type = 'Beta'")
public void receiveBeta(Beta beta) { ... }

但由于 Spring 在幕后做了各种聪明的事,我很惊讶我必须像这样明确地帮助它。

有没有更隐含/更好的方法来做到这一点?

【问题讨论】:

    标签: java spring jms spring-jms


    【解决方案1】:

    JmsListener 不支持方法路由 - 每个带注释的方法都有自己的侦听器容器。

    唯一的另一种选择是使用...(Object object) 并让自己失望。

    【讨论】:

      【解决方案2】:

      尝试在消息后处理器中设置选择器属性。在消费者方法中使用与选择器相同的属性。检查这个JMSListener selector not working

      发送到队列:

          template.convertAndSend("my-destination", alpha, m -> {
              m.setStringProperty("classType", "alpha");
              return m;
          });
      



      从队列中获取消息:

          @JmsListener(destination = "my-destination", selector = "classType = 'alpha'")<br/>
          public void receiveAlpha(Alpha alpha) { ... }
      

      【讨论】:

        【解决方案3】:

        您可以设置 JmsTemplate 的消息转换器,将消息的 Java 类型设置为消息的“type”属性,然后在 JmsListener 中配置选择器以仅接收所需的消息类型。

        下面是Kotlin的例子,Java应该也是这样

        默认消息转换,将消息类型注解为“type”属性:

        @Bean // Serialize message content to json using TextMessage
        fun jacksonJmsMessageConverter(): MessageConverter {
            val converter = MappingJackson2MessageConverter()
        
            converter.setTargetType(MessageType.TEXT)
            converter.setTypeIdPropertyName("type")
            return converter
        }
        

        使用注释消息转换器,JMS 监听器可以在选择器中指定消息类型:

        // Uses default JmsListenerContainerFactory
        @JmsListener(destination = "mailbox", containerFactory = "myFactory", selector="type='com.garnetsoft.sf.service.queue.CopyFolderJob'")
        fun receiveMessage(job: CopyFolderJob) {
            println("Received copy job <$job>")
        }
        
        @JmsListener(destination = "mailbox", containerFactory = "myFactory", selector="type='com.garnetsoft.sf.service.queue.CutFolderJob'")
        fun receiveMessage(job: CutFolderJob) {
            println("Received cut job <$job>")
        }
        

        希望这会有所帮助。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-01-25
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多