Java 如何使用 Spring JMS 发布 JMS 主题?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3518292/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-14 01:28:19  来源:igfitidea点击:

How do you publish a JMS topic with Spring JMS?

javaspringjmsactivemq

提问by wsb3383

I have a component that sends messages to a queue to be handled by another system. It should also publish a topic about job statuses every once in a while. Can I just use the same JmsTemplate used to send to a queue AND to publish to a topic?

我有一个组件将消息发送到队列以供另一个系统处理。它还应该每隔一段时间发布一个关于工作状态的主题。我可以只使用用于发送到队列并发布到主题的相同 JmsTemplate 吗?

I created a new topic in ActiveMQ, except that when I send from JmsTemplate a message, a new queue with the topic name gets created with the sent message (instead of sending the data to the actual topic), what am I doing wrong here?

我在 ActiveMQ 中创建了一个新主题,除了当我从 JmsTemplate 发送消息时,使用发送的消息创建了一个具有主题名称的新队列(而不是将数据发送到实际主题),我在这里做错了什么?

here's my config:

这是我的配置:

<bean id="connectionFactory" class="org.springframework.jms.connection.CachingConnectionFactory">
    <constructor-arg ref="amqConnectionFactory" />
    <property name="exceptionListener" ref="jmsExceptionListener" />
    <property name="sessionCacheSize" value="100" />
</bean>

<!--  JmsTemplate Definition -->
<bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
    <constructor-arg ref="connectionFactory" />
</bean>


<bean id="messageFacade" class="org.foo.MessageFacadeJms">
    <property name="jmsTemplate" ref="jmsTemplate" />
</bean>

MessageFacadeJms is the class I use to send a queue message (and it works), can I also just used that to publish a topic?

MessageFacadeJms 是我用来发送队列消息的类(它可以工作),我也可以用它来发布主题吗?

Can I just use this to do both queue sending and topic publishing?:

我可以用它来做队列发送和主题发布吗?:

jmsTemplate.convertAndSend("TOPIC_NAME" /* or queue name */, message);

采纳答案by skaffman

This might seem a bit odd, you need to tell JmsTemplate that it's a topic rather than a queue, by setting its pubSubDomainproperty to true.

这可能看起来有点奇怪,您需要通过将其pubSubDomain属性设置为 来告诉 JmsTemplate 它是一个主题而不是队列true

That means you're going to need two JmsTemplatebeans, one for the queue, and one for the topic:

这意味着您将需要两个JmsTemplatebean,一个用于队列,另一个用于主题:

<bean id="jmsQueueTemplate" class="org.springframework.jms.core.JmsTemplate">
   <constructor-arg ref="connectionFactory" />
   <property name="pubSubDomain" value="false"/>
</bean>

<bean id="jmsTopicTemplate" class="org.springframework.jms.core.JmsTemplate">
   <constructor-arg ref="connectionFactory" />
   <property name="pubSubDomain" value="true"/>
</bean>

回答by Eran Harel

If you create the destination as a spring bean rather than using the destination name in your code, Spring won't need to know whether it is a topic or a queue. Else the solution suggested above should work as well.

如果您将目标创建为 spring bean 而不是在代码中使用目标名称,则 Spring 不需要知道它是主题还是队列。否则上面建议的解决方案也应该有效。

AMQ JMS destinations can be created by directly instantiating them:

AMQ JMS 目标可以通过直接实例化它们来创建:

  <bean id="destination" class="org.apache.activemq.command.ActiveMQTopic">
    <constructor-arg value="TOPIC_NAME" />
  </bean>

or fetching from JNDI:

或从 JNDI 获取:

<bean id="topic" class="org.springframework.jndi.JndiObjectFactoryBean">
        <property name="jndiName" value="TOPIC_NAME"/>
        <property name="jndiTemplate" ref="jmsJndiTemplate"/> 
</bean>

I prefer the JNDI technique as it is more standard.

我更喜欢 JNDI 技术,因为它更标准。

回答by Gian Marco Gherardi

If it's ok for you to use a naming convention for queue/topics, then you can implement a custom org.springframework.jms.support.destination.DestinationResolver

如果您可以为队列/主题使用命名约定,那么您可以实现自定义 org.springframework.jms.support.destination.DestinationResolver

public class NamingDestinationResolver implements DestinationResolver {
   public Destination resolveDestinationName(Session session, String destinationName, boolean pubSubDomain) throws JMSException {
      if (destinationName.endsWith("Queue")) {
         return session.createQueue(destinationName);
      } else if (destinationName.endsWith("Topic")) {
         return session.createTopic(destinationName);
      }
      throw new RuntimeException("Naming convention not respected for destination " + destinationName);
   }
}

and reference it using JmsTemplate.setDestinationResolver

并使用引用它 JmsTemplate.setDestinationResolver