如何在Spring 4中使用@JmsListener作为主题

时间:2016-10-15 16:29:20

标签: java spring activemq messaging spring-jms

我正在使用Spring 4.3.3,我正在尝试收听目标类型为主题的消息。

我可以用xml实现它:

<jms:listener-container connection-factory="connectionFactory"
                        destination-type="topic"
                        message-converter="jackson2MessageConverter">
    <jms:listener destination="test.topic" ref="jmsTopicMessageListener1" method="receiveMessage"/>
    <jms:listener destination="test.topic" ref="jmsTopicMessageListener2" method="receiveMessage"/>
</jms:listener-container>

但我想使用@JmsListener。目前它只适用于队列目的地:

@JmsListener(destination = "mailbox", containerFactory = "jmsListenerContainerFactory")
public void receiveMessage(DataObject dataObject) {
    System.out.println("Received <" + dataObject.getName() + ">");
}

如何使用此注释@JmsListener收听主题?

提前致谢。

更新

我在配置中试过这个:

<bean id="topicJmsListenerContainerFactory"
      class="org.springframework.jms.config.DefaultJmsListenerContainerFactory">
    <property name="connectionFactory" ref="cachingConnectionFactory"/>
    <property name="destinationResolver" ref="jmsDestResolver"/>
    <property name="concurrency" value="3-10"/>
    <property name="messageConverter" ref="jackson2MessageConverter"/>
    <property name="pubSubDomain" value="true"/>
</bean>

然后这个:

@JmsListener(destination = "test.topic", containerFactory = "topicJmsListenerContainerFactory")
public void receiveMessage(DataObject dataObject) {
    System.out.println("Received <" + dataObject.getName() + ">" + 1);
}

我现在可以获得值,但我得到重复。

1 个答案:

答案 0 :(得分:3)

由于您已修复配置(您正在接收消息),因此唯一需要解决的问题是您收到重复消息。这是由于你的配置这个部分:

<property name="concurrency" value="3-10"/>

如果你检查DefaultMessageListenerContainer的javadoc(JmsListenerContainerFactory扩展了),你会发现:

  

...对于某个主题,您通常会使用默认数字1   消费者,否则您将多次收到相同的消息   同一节点。

这是由于主题本身的架构,多个消费者将被视为需要接收已发送的每条消息的多个订阅者

在解决方案方面:

您可能需要稍微修改一下代码。但大多数从Topic变为VirtualTopic的案例都可以胜任。 使用VirtualTopics,您可以获得&#34;类似队列&#34;消费者方面的行为,这意味着消息将被消费者消费,因此多个消费者不能两次看到相同的消息。

另一种选择当然是将并行处理工作负载转移到其他地方,在JMS入口点使用单个消费者。根据手头的任务,它也可能是一个充分的解决方案。