2016-10-20 81 views
2

我想聽聽使用下面的代碼段的主題。但是它默認監聽隊列。在這種情況下沒有xml配置。我完全依靠註釋。此外,我完全依賴Spring引導提供的AutoConfiguration。我不知道如何將目標類型設置爲主題,在JmsListener中。 Spring JMS大師請幫忙。如何聽話題使用彈簧引導jms

@Component 
    public class MyTopicListener { 

     @JmsListener(destination = "${trans.alert.topic}") 
     public void receiveMessage(TransactionAlert alert) { 
      logger.info("AlertSubscriberEmail :: Sending Email => <" + alert + ">"); 
     } 
    } 

回答

3

我只是把整個春季啓動例如來自:https://github.com/spring-guides/gs-messaging-jms/

在這個它是從一個隊列中的消息的發送和接收產生。要將其更改爲主題,您必須在Factory實例中設置Pub-Sub屬性。

import org.springframework.beans.factory.support.BeanDefinitionBuilder; 
import org.springframework.beans.factory.support.DefaultListableBeanFactory; 
import org.springframework.boot.SpringApplication; 
import org.springframework.boot.autoconfigure.SpringBootApplication; 
import org.springframework.boot.autoconfigure.jms.DefaultJmsListenerContainerFactoryConfigurer; 
import org.springframework.context.ConfigurableApplicationContext; 
import org.springframework.context.annotation.Bean; 
import org.springframework.jms.annotation.EnableJms; 
import org.springframework.jms.config.DefaultJmsListenerContainerFactory; 
import org.springframework.jms.config.JmsListenerContainerFactory; 
import org.springframework.jms.connection.CachingConnectionFactory; 
import org.springframework.jms.core.JmsTemplate; 
import org.springframework.jms.support.converter.MappingJackson2MessageConverter; 
import org.springframework.jms.support.converter.MessageConverter; 
import org.springframework.jms.support.converter.MessageType; 

import javax.jms.ConnectionFactory; 

@SpringBootApplication 
@EnableJms 
public class JmsSampleApplication { 

public void registerBeans(ConfigurableApplicationContext context){ 
    BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(JmsTemplate.class); 
    CachingConnectionFactory cachingConnectionFactory = new CachingConnectionFactory(); 

    builder.addPropertyValue("connectionFactory", cachingConnectionFactory);  // set property value 
    DefaultListableBeanFactory factory = (DefaultListableBeanFactory) context.getAutowireCapableBeanFactory(); 
    factory.registerBeanDefinition("jmsTemplateName", builder.getBeanDefinition()); 
} 

@Bean 
public JmsListenerContainerFactory<?> topicListenerFactory(ConnectionFactory connectionFactory, 
               DefaultJmsListenerContainerFactoryConfigurer configurer) { 
    DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory(); 
    factory.setPubSubDomain(true); 
    // This provides all boot's default to this factory, including the message converter 
    configurer.configure(factory, connectionFactory); 
    // You could still override some of Boot's default if necessary. 
    return factory; 
} 

@Bean 
public JmsListenerContainerFactory<?> queueListenerFactory(ConnectionFactory connectionFactory, 
                  DefaultJmsListenerContainerFactoryConfigurer configurer) { 
    DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory(); 
    //factory.setPubSubDomain(true); 
    // This provides all boot's default to this factory, including the message converter 
    configurer.configure(factory, connectionFactory); 
    return factory; 
} 

@Bean // Serialize message content to json using TextMessage 
public MessageConverter jacksonJmsMessageConverter() { 
    MappingJackson2MessageConverter converter = new MappingJackson2MessageConverter(); 
    converter.setTargetType(MessageType.TEXT); 
    converter.setTypeIdPropertyName("_type"); 
    return converter; 
} 
public static void main(String[] args) { 
    ConfigurableApplicationContext context = SpringApplication.run(JmsSampleApplication.class, args); 

    JmsTemplate jmsTemplate = context.getBean(JmsTemplate.class); 

    // Send a message with a POJO - the template reuse the message converter 
    System.out.println("Sending an email message."); 
    jmsTemplate.convertAndSend("mailbox.topic", new Email("[email protected]", "Hello")); 
    jmsTemplate.convertAndSend("mailbox.queue", new Email("[email protected]", "Hello")); 

    } 
} 

聽者

package org.springboot.jms; 

import org.springframework.jms.annotation.JmsListener; 
import org.springframework.stereotype.Component; 

/** 
* Created by RGOVIND on 10/20/2016. 
*/ 
@Component 
public class HelloTopicListener { 

    @JmsListener(destination = "mailbox.topic", containerFactory = "topicListenerFactory") 
    public void receiveTopicMessage(Email email) { 
     System.out.println("Received <" + email + ">"); 
    } 

    @JmsListener(destination = "mailbox.queue", containerFactory = "queueListenerFactory") 
    public void receiveQueueMessage(Email email) { 
     System.out.println("Received <" + email + ">"); 
    } 
} 

一旦做到這一點,你都設置訂閱選擇的話題。

有多種方法這門課程的,你可以有地圖豆不同jmsTemplates,每一個都可以在需要時根據隊列或主題來使用的。可以使用您在SO Question中討論的選擇喜歡的方法實例化模板&。希望它可以幫助

+0

當我嘗試用** JmsListenerContainerFactory豆**或設置該屬性**春天。 jms.pub-sub-domain = true **在application.properties中,隊列發送者和偵聽者的所有其他代碼都起作用,就好像他們正在讀寫主題而不是隊列一樣。有沒有解決方案可以使隊列和主題的偵聽器共存。 – zikzakjack

+0

你總是可以選擇擁有多個工廠。在代碼的情況下,您可以選擇同時擁有隊列和主題。問題是當你選擇接收時,你將不得不選擇工廠。在這種情況下,你可以有2個工廠,從一個主題中獲得並從隊列中獲得。編輯我的答案以及 –

+0

我試過使用多個工廠,即使那麼這樣創建的主題就像一個隊列只有即創建多個偵聽器消息分佈在自己之間。相反,每個用戶應該得到所有的消息 – anon

2

在春天啓動的Application.properties,嘗試設置以下屬性:

spring.jms.pub-sub-domain=true 

然後,使用該屬性的集裝箱工廠,使用的是聽的話題。

+0

實際上,Boot auto-configures的默認容器工廠將自動使用該標誌。 –

+1

我懷疑使用這個屬性會使所有可用的監聽器都在監聽主題。我正在尋找一種方法,如何在同一個項目中爲隊列和主題分別設置監聽器。 – zikzakjack

+0

您不能擁有相同的connectionFactory來偵聽隊列和主題。您的偵聽器將從connectionFactory派生,該工廠將配置爲偵聽點對點(隊列)或發佈 - 訂閱(主題)。因此,有兩個連接功能,主題和隊列各一個,然後根據需要使用它們。 pub-sub-domain的默認設置被設置爲false,這意味着默認情況下它將偵聽隊列。 –

0

答案標記爲正確幾乎是正確的。它仍然不會工作,因爲:

factory.setPubSubDomain(true) 

必須出現在:

configurer.configure(factory, connectionFactory); 

否則pubSubDomain標誌被設置爲true配置默認時丟失和工廠實例仍然會與隊列而不是主題工作。