Spring Boot JMS主题无法正常工作

时间:2017-03-03 07:31:45

标签: spring spring-boot activemq spring-jms

Spring Boot JMS Topic无法正常工作,它的行为类似于队列。

示例代码

应用

@SpringBootApplication
public class Application extends SpringBootServletInitializer {

  public static void main(String[] args) {
    SpringApplication.run(Application.class, args);
  }
}

JMSConfig

@Configuration
@EnableJms
public class JMSConfig {

private static final String JMS_BROKER_URL = "vm://embedded?broker.persistent=false,useShutdownHook=false";
public static final String JMS_TOPIC_MAIL = "mailbox.topic";

@Bean
// Serialize message content to json using TextMessage
public MessageConverter jacksonJmsMessageConverter() {
    MappingJackson2MessageConverter converter = new MappingJackson2MessageConverter();
    converter.setTargetType(MessageType.TEXT);
    converter.setTypeIdPropertyName("_type");
    return converter;
}

@Bean
public ActiveMQConnectionFactory amqConnectionFactory() {

    return new ActiveMQConnectionFactory(JMS_BROKER_URL);

}

@Bean
public CachingConnectionFactory connectionFactory() {

    return new CachingConnectionFactory(amqConnectionFactory());

}

@Bean
public ActiveMQTopic destinationTopic() {

    return new ActiveMQTopic(JMS_TOPIC_MAIL);
}

@Bean
public JmsTemplate jmsTemplate() {

    JmsTemplate jmsTemplate = new JmsTemplate(connectionFactory());
    // jmsTemplate.setDefaultDestination(destinationTopic());;
    jmsTemplate.setDefaultDestinationName(JMS_TOPIC_MAIL);
    jmsTemplate.setConnectionFactory(connectionFactory());
    jmsTemplate.setMessageConverter(jacksonJmsMessageConverter());
    return jmsTemplate;
}

@Bean
public JmsListenerContainerFactory<?> jmsListenerContainerFactory(
        ConnectionFactory connectionFactory,
        DefaultJmsListenerContainerFactoryConfigurer configurer) {
    DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
    factory.setPubSubDomain(true);
    factory.setConnectionFactory(connectionFactory());
    // 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;
}
}

这里的听众是

第一个听众

@Component
public class JMSTopicListener1 {

@JmsListener(destination = JMSConfig.JMS_TOPIC_MAIL, containerFactory = "jmsListenerContainerFactory")
public void receiveTopicMessage(Email email) {
    System.out.println("JMSTopicListener#1 Received <" + email + ">");
}
}

第二个听众

@Component
public class JMSTopicListener2 {

@JmsListener(destination = JMSConfig.JMS_TOPIC_MAIL, containerFactory = "jmsListenerContainerFactory")
public void receiveTopicMessage(Email email) {
    System.out.println("JMSTopicListener#2 Received <" + email + ">");
}
}

通过网络访问

@RestController
public class WebController {

@Autowired
JmsTemplate jmsTemplate;


@RequestMapping("/sendEmail")
public String sendEmail() {

    System.out.println("Sending ************************ .");

    jmsTemplate.convertAndSend(JMSConfig.JMS_TOPIC_MAIL, new Email(
            "info@example.com", "Hello"));


    return "Email send success!!!";
}
}

输出

发送************************。 JMSTopicListener#2已收到

但是两个侦听器都应该订阅消息,因为它附加了Topic

1 个答案:

答案 0 :(得分:5)

添加到 aplication.properties

spring.jms.pub-sub-domain=true

或将bean定义代码更改为:

@Bean
public JmsListenerContainerFactory<?> jmsListenerContainerFactory(
        ConnectionFactory connectionFactory,
        DefaultJmsListenerContainerFactoryConfigurer configurer) {
    DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
    factory.setConnectionFactory(connectionFactory());
    // 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.
    // As you said if you want to override Boot's defaults or 
    // values from aplication.properties you have to do it after configurer.configure()
    factory.setPubSubDomain(true);
    return factory;
}

<强>更新

您还需要更新jmsTemplate以使用主题

@Bean
public JmsTemplate jmsTemplate() {

    JmsTemplate jmsTemplate = new JmsTemplate(connectionFactory());
    // jmsTemplate.setDefaultDestination(destinationTopic());;
    jmsTemplate.setDefaultDestinationName(JMS_TOPIC_MAIL);
    jmsTemplate.setConnectionFactory(connectionFactory());
    jmsTemplate.setMessageConverter(jacksonJmsMessageConverter());
    jmsTemplate.setPubSubDomain(true);
    return jmsTemplate;
}

@RestController
public class WebController {

@Autowired
JmsTemplate jmsTemplate;

@Autowired
ActiveMQTopic  destinationTopic;

@RequestMapping("/sendEmail")
public String sendEmail() {

    System.out.println("Sending ************************ .");

    jmsTemplate.convertAndSend(destinationTopic, new Email(
            "info@example.com", "Hello"));


    return "Email send success!!!";
}
}