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
答案 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!!!";
}
}