出于POC的目的,我构建了一个Spring Boot应用程序,该应用程序使用ActiveMQ通过JMSTemplate进行消息传递。
为了进行监视,我想使用“咨询主题”来监听放在队列中和从队列中删除的消息。
我已经更新了ActiveMQ配置以启用相关咨询:
<!-- activemq.xml -->
<broker xmlns="http://activemq.apache.org/schema/core" useJmx="true" brokerName="localhost" dataDirectory="${activemq.data}">
<destinationPolicy>
<policyMap>
<policyEntries>
<policyEntry topic=">" advisoryForConsumed="true" advisoryForDelivery="true">
<pendingMessageLimitStrategy>
<constantPendingMessageLimitStrategy limit="1000"/>
</pendingMessageLimitStrategy>
</policyEntry>
<policyEntry queue=">" advisoryForConsumed="true" advisoryForDelivery="true">
<pendingMessageLimitStrategy>
<constantPendingMessageLimitStrategy limit="1000"/>
</pendingMessageLimitStrategy>
</policyEntry>
</policyEntries>
</policyMap>
</destinationPolicy>
</broker>
在应用程序中,我已经配置了JMS连接工厂和JMS侦听器容器工厂以启用咨询和pubsub域,并为咨询主题设置了侦听器:
@Configuration
public class JmsConfig {
@Autowired
MessageListener messageListener;
@Bean
public ConnectionFactory connectionFactory() {
ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory();
connectionFactory.setWatchTopicAdvisories(true);
connectionFactory.setBrokerURL("vm://localhost?broker.persistent=false");
return connectionFactory;
}
@Bean
public JmsListenerContainerFactory<?> myFactory(ConnectionFactory connectionFactory,
DefaultJmsListenerContainerFactoryConfigurer configurer) throws JMSException {
DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
factory.setPubSubDomain(true);
configurer.configure(factory, connectionFactory);
Connection connection = connectionFactory.createConnection();
connection.start();
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
Queue bulkQueue = session.createQueue("bulk");
Topic deliveredAdvisoryTopic = AdvisorySupport.getMessageDeliveredAdvisoryTopic(bulkQueue);
MessageConsumer deliveredAdvisoryTopicConsumer = session.createConsumer(deliveredAdvisoryTopic);
deliveredAdvisoryTopicConsumer.setMessageListener(messageListener);
Topic consumedAdvisoryTopic = AdvisorySupport.getMessageConsumedAdvisoryTopic(bulkQueue);
MessageConsumer consumedAdvisoryTopicConsumer = session.createConsumer(consumedAdvisoryTopic);
consumedAdvisoryTopicConsumer.setMessageListener(messageListener);
return factory;
}
将读取咨询性主题的侦听器仅用于记录日志:
@Component
public class AdvisoryMessageListener implements MessageListener {
@Override public void onMessage(Message message) {
System.out.println("Received advisory message");
System.out.println(message);
}
}
将从队列中读取的实际侦听器类似于咨询消息侦听器:
@Component
public class Receiver {
@JmsListener(destination = "bulk", containerFactory = "jmsListenerContainerFactory")
public void receiveMessage(Email email) {
System.out.println("Received <" + email + ">");
}
}
Rest API将触发应用程序将消息放入队列:
@RestController("/emails")
public class EmailController {
@Autowired
private JmsTemplate jmsTemplate;
@PostMapping("/")
public void persistEmail(@RequestBody Email email) {
jmsTemplate.setExplicitQosEnabled(true);
jmsTemplate.setTimeToLive(0L);
jmsTemplate.convertAndSend("bulk", email);
}
}
无论何时调用API并将电子邮件放入队列,Receiver.receiveMessage都会读取并记录下来,但AdvisoryMessageListener中没有任何动作。
控制台中唯一显示的内容是:
Received <Email{to=foo@bar.com, body=Hello}>
由Receiver.receiveMessage打印
我在做什么错了?
答案 0 :(得分:1)
这对我来说很好...
@SpringBootApplication
public class So59196698Application {
public static void main(String[] args) {
SpringApplication.run(So59196698Application.class, args);
}
@JmsListener(destination = "so59196698")
public void listen(Message in) {
System.out.println("Received:" + in);
}
@JmsListener(destination = "#{advisoryTopicNames.deliveredTopic}", containerFactory = "topicFactory")
public void delivered(Message in) {
System.out.println("Delivered:" + in);
}
@JmsListener(destination = "#{advisoryTopicNames.consumedTopic}", containerFactory = "topicFactory")
public void consumed(Message in) {
System.out.println("Consumed:" + in);
}
@Bean
public ApplicationRunner runner(JmsTemplate template) {
return args -> {
Thread.sleep(5000);
template.convertAndSend("so59196698", "test");
};
}
@Bean
public JmsListenerContainerFactory<?> topicFactory(ConnectionFactory connectionFactory,
DefaultJmsListenerContainerFactoryConfigurer configurer) {
DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
configurer.configure(factory, connectionFactory);
factory.setPubSubDomain(true);
return factory;
}
}
@Component
class AdvisoryTopicNames {
private static final Destination QUEUE = new ActiveMQQueue("so59196698");
public String getDeliveredTopic() throws JMSException {
return AdvisorySupport.getMessageDeliveredAdvisoryTopic(QUEUE).getTopicName();
}
public String getConsumedTopic() throws JMSException {
return AdvisorySupport.getMessageConsumedAdvisoryTopic(QUEUE).getTopicName();
}
}
和
Received:ActiveMQTextMessage {commandId = 11, ...
Delivered:ActiveMQMessage {commandId = 0, ...
Consumed:ActiveMQMessage {commandId = 0, ...