2010-08-19 43 views
12

我有一個組件將消息發送到另一個系統處理的隊列。它還應該每隔一段時間發佈一次關於工作狀態的主題。我可以使用相同的JmsTemplate用於發送到隊列併發布到主題嗎?如何使用Spring JMS發佈JMS主題?

我在ActiveMQ中創建了一個新主題,除了當我從JmsTemplate發送一條消息時,主題名稱的一個新隊列通過發送的消息創建(而不是將數據發送到實際主題),我是什麼在這裏做錯了嗎?

這裏是我的配置:

<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被我用來發送隊列消息(和它的作品),類可我也只是使用了發佈一個話題?

可我只是用這個做兩隊列發送和話題發佈?:

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

回答

28

這似乎有點奇怪,你需要告訴JmsTemplate的,這是一個話題,而不是一個隊列,通過設置pubSubDomain財產至true

這意味着你將需要兩個JmsTemplate豆,一個隊列,以及一個用於話題:如果您創建目標作爲一個Spring bean

<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> 
5

,而不是使用在目的地名稱你的代碼,Spring不需要知道它是一個主題還是一個隊列。否則上面建議的解決方案也應該可以工作。

AMQ JMS目標可以通過直接實例化它們被創建:

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

或從JNDI獲取:

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

我更喜歡JNDI技術,因爲它是更標準。

1

是否確定你使用的隊列/主題的命名規則,就可以實現自定義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); 
    } 
} 

,並使用JmsTemplate.setDestinationResolver

+0

非常完美,我引用它。如果您將@Component添加到DestinationResolver,則您甚至不需要將其設置在JmsTemplate – danielnovy 2018-01-12 21:32:13

+0

@danielnovy上,如果您發現該答案有用,則可以讚賞:) – 2018-01-14 07:14:46