public class TopicPersistentTest {
//编写消息的发送端-----生产者
@Test
public void test1() throws Exception{
//创建链接工厂对象
ConnectionFactory connectionFactory = new ActiveMQConnectionFactory("tcp://localhost:61616");
//从工厂中获取一个链接对象
Connection connection = connectionFactory.createConnection();
//获取session对象
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
//通过session对象创建主题
Topic topic = session.createTopic("topic");
//通过session对象创建消息的发送者
MessageProducer producer = session.createProducer(topic);
//开启持久化
producer.setDeliveryMode(DeliveryMode.PERSISTENT);
//连接MQ服务
connection.start();
//通过session创建消息对象
TextMessage message = session.createTextMessage("ping");
//发送消息
producer.send(message, DeliveryMode.PERSISTENT, 1, 1000*60*60*24);
//关闭相关资源
producer.close();
session.close();
connection.close();
}
//编写消息的接收端-----消费者
@Test
public void test2() throws Exception{
//创建链接工厂对象
ConnectionFactory connectionFactory = new ActiveMQConnectionFactory("tcp://localhost:61616");
//从工厂中获取一个链接对象
Connection connection = connectionFactory.createConnection();
//设置客户端id
connection.setClientID("client-1");
//连接MQ服务
connection.start();
//获取session对象
final Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
//通过session对象创建主题
Topic topic = session.createTopic("topic");
//通过session对象创建消息的消费者
// MessageConsumer consumer = session.createConsumer(topic);
//设置主体的订阅者
TopicSubscriber consumer = session.createDurableSubscriber(topic, "client1-sub");
//指定消息监听器1
consumer.setMessageListener(new MessageListener() {
//当监听的topic中存在消息,这个方法自动执行
public void onMessage(Message message) {
if (null != message && message instanceof TextMessage){
TextMessage textMessage = (TextMessage) message;
try {
System.out.println("消费者接收到了消息:" + textMessage.getText());
} catch (JMSException e) {
e.printStackTrace();
}
}
}
});
while(true) {
}
}
}
总结:
- 在使用Topic主题处理消息时,消费者必须先订阅主题,消费者不能接收到主题订阅之前产生的消息
- 在获取Session对象时如果事务设置为true,则需要调用commit方法提交事务
- 在获取Session对象时如果开启手动签收,必须调用acknowledge方法手动签收,否则消息不会被消费
- 如果开启事务,则会强制自动签收,即当事务被成功提交则消息被自动签收,如果事务回滚,则消息会被再次传送。创建Session对象的第二个签收参数无效
- 生产者开启持久化后,服务器宕机后重启服务器,消费者也能接收到宕机前发送的消息,关闭持久化之后则不能接收到宕机前的消息。默认开启了持久化
- 非持久订阅只有当消费者与MQ保持连接状态才能接收到发送到某个主题的消息,如果消费者处于离线状态,生产者发送的主题消息将会丢失,消费者不会接收到
- 持久订阅:客户端首先向MQ注册一个自己的身份ID识别号,当这个客户端处于离线时,生成者会为这个ID保存所有发送到主题的消息,当消费者再次连接到MQ时会根据消费者的ID得到所有当自己处于离线状态时发送到主题的消息
- 非持久订阅状态下,不能恢复或重新派送一个未签收的消息
- 持久订阅状态下才能恢复或重新派送一个未签收的消息