Table of Contents
一、linux 安装activemq及应用
二、JMS
一组成:
二 消息可靠性 : (持久性 ,事务, 签收)
1 persisent 持久性:messageProducer.setDeliverymodel(DeliveryModel.NOO_PERSISENT);//非持久化
2 事务
3 acknowledge 签收
总结:
四、spring整合activemq
五、SpringBoot整合Activemq
1 队列:
2:发布订阅
topic生产者:
topic消费者:
六、AcitveMQ传输协议
tcp语法:tcp://hostname:port?key=value
NIO 传输人协议:
七 activemq持久化
JDBC持久化JDBC persistence.演示
jdbc with journal 演示
八、ActiveMQ集群
九、高级特性
一、linux 安装activemq及应用
https://activemq.apache.org/官网下载apache-activemq-5.15.9-bin.tar.gz 用xftp上传到/opt目录解压在bin目录中启动./activemq start ,前提是需要对应jdk版本(我安装是对应需要jdk1.8)
查看启动:
启动 bin下面的命令
./activemq start
默认后台端口61616 前台端口8161
查看是否启动三种方式
1 netstat -anp |grep 61616
2 ps -er | grep activemq | grep -v grep
3 lsof -i:61616
两个模式:queue和topic
两个模式的差异
javaee
JMS
二、JMS
一组成:
JMS 组成结构和特点
provide 服务器
produce 生产者
consumer 消费者
message :消息头,消息体,消息属性
JMS message
消息头:几个重要的设置
JMSDestination 目的地:发送消息的目的地主要指Queue和Topic
JMSDeliveryModel 持久和非持久
JMSExpiration 消息过期设置
JMSPriority 消息优先级
JMSMessageID 消息唯一标志id:唯一识别每个消息的标志由mq产生
消息体 :封装具体的消息数据
5种消息体格式:
TextMessage 普通的字符串包含一个String
MapMessage 一个Map类型消息,key是String 而值是java基本类型
BytesMessage 二进制数组消息,包含一个byte[]
StreamMessage java数据流消息,用标准的流操作来顺序填充和读取
ObjectMess age 对象消息,包含一个可序列化的java对象
发送和接收消息体类型必须一致对应
消息属性:
如果需要除消息头字段以外的值,那么可以使用消息属性
识别/去重/重点标注等操作非常有用的方法
是一对kv对:如 textMessage.setStringProperty("c01","vip");
二 消息可靠性 : (持久性 ,事务, 签收)
1 persisent 持久性:messageProducer.setDeliverymodel(DeliveryModel.NOO_PERSISENT);//非持久化
DeliveryModel.PERSISENT持久化 默认策略就是持久化
持久化topic:一定要先运行一次消费者等于是想mq注册,类似订阅了这个主题,然后再运行生产者发送消息
此时无论消费者是否在线都会接收到消息,不在线的话下次连接时候会把没有接收过的消息都接收回来。
队列:1 非持久性演示:当服务器宕机 ,消息依然存在
2 持久性演示:当服务器宕机,消息依然存在
3 队列默认策略就是持久化
topic:持久化演示
一定先运行一次消费者,等于向mq注册,类似我们订阅了这个主题,然后再运行生产者发送消息
此时,无论消费者是否在线,都会接受到,不在线的话,下次连接时候会把没有接收的消息都接收下来
----订阅者
private static final String URL_BROKER = "tcp://192.168.163.131:61616";
private static final String TOPIC_NAME = "topic_persisent";
public static void main(String[] args) throws JMSException, IOException {
System.out.println("我是余斌号消费者");
ActiveMQConnectionFactory activeMQConnectionFactory = new ActiveMQConnectionFactory(URL_BROKER);
Connection connection = activeMQConnectionFactory.createConnection();
//指定客户端是哪个订阅了
connection.setClientID("余斌");
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
//创建目的地tipic
Topic topic = session.createTopic(TOPIC_NAME);
//创建持久的订阅者 Subscribers 是订阅哪个主题topic
TopicSubscriber durableSubscriber = session.createDurableSubscriber(topic, "描述信息。。。");
connection.start();
//主题的订阅者接收
Message message = durableSubscriber.receive();
while (message != null) {
TextMessage textMessage = (TextMessage) message;
System.out.println("接收持久化的topic 消息:"+textMessage.getText());
message =durableSubscriber.receive(3000L);
}
session.close();
connection.close();
System.out.println("消息接收完毕!");
--事务偏生产者,签收偏消费者
2 事务
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
如果是false:只要执行send就进入到队列中去,关闭事务,那么第二个签收参数设置需要有效
如果是true,先执行send在执行commit,消息才被真正提交到队列中,消息需要批量发送需要缓冲区处理
生产者--------如果是false 则send的时候就提交成功到目的地,如果是true,一定需要提交commit,出错可以回滚rollback,如果没有commit那么消息就没有发送到目的地。
消费者
3 acknowledge 签收
非事务下的签收:
1 自动签收(默认)
2 手动签署 :需要显示的调用acknowledge方法,如 textMessage.acknowledge();
3 可重复签收:了解即可
事务下的签收:
生产事务开始,只有commit后才能将全部消费变为已消费
当一个事务被成功提交则消息被自动签收,如果事务回滚,则消息会被再次传送,
事务与签收的关系:事务比签收更大,只要是开始事务,不管有没有显示调用acknowledge方法,只要提交就默认是自动签收
如果开启事务但是没有commit调用,即使写了acknowledge方法签收也不会成功。
非事务会话中,消息何时被确认取决于创建会话时候的应答模式(acknowledgement model),如果自动签收就自动,如果手动签收就需要调用textMessage.acknowledge();
总结:
队列
topic
非持久订阅
private static final String URL_BROKER = "tcp://192.168.163.131:61616";
private static final String TOPIC_NAME = "topic_01";
public static void main(String[] args) throws JMSException, IOException {
System.out.println("我是1号消费者");
ActiveMQConnectionFactory activeMQConnectionFactory = new ActiveMQConnectionFactory(URL_BROKER);
Connection connection = activeMQConnectionFactory.createConnection();
connection.start();
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
Topic topic = session.createTopic(TOPIC_NAME);
MessageConsumer consumer = session.createConsumer(topic);
consumer.setMessageListener(message -> {
if(null != message && message instanceof TextMessage) {
TextMessage textMessage = (TextMessage) message;
try {
System.out.println("接收消息:"+textMessage.getText());
} catch (JMSException e) {
e.printStackTrace();
}
}
if(null != message && message instanceof MapMessage) {
MapMessage mapMessage = (MapMessage) message;
try {
String k1 = mapMessage.getString("k1");
System.out.println("接收消息:"+k1);
} catch (JMSException e) {
e.printStackTrace();
}
}
});
System.in.read();
consumer.close();
session.close();
connection.close();
System.out.println("消息接收完毕!");
}
持久订阅
private static final String URL_BROKER = "tcp://192.168.163.131:61616";
private static final String TOPIC_NAME = "topic_persisent";
public static void main(String[] args) throws JMSException, IOException {
System.out.println("我是余斌号消费者");
ActiveMQConnectionFactory activeMQConnectionFactory = new ActiveMQConnectionFactory(URL_BROKER);
Connection connection = activeMQConnectionFactory.createConnection();
//指定客户端是哪个订阅了
connection.setClientID("余斌");
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
//创建目的地tipic
Topic topic = session.createTopic(TOPIC_NAME);
//创建持久的订阅者 Subscribers 是订阅哪个主题topic
TopicSubscriber durableSubscriber = session.createDurableSubscriber(topic, "描述信息。。。");
connection.start();
//主题的订阅者接收
Message message = durableSubscriber.receive();
while (message != null) {
TextMessage textMessage = (TextMessage) message;
System.out.println("接收持久化的topic 消息:"+textMessage.getText());
message =durableSubscriber.receive(3000L);
}
session.close();
connection.close();
System.out.println("消息接收完毕!");
}
必须签收用持久订阅,当丢失消息能够被容忍,则用非持久订阅
三、linux启动不同的配置文件(类似redis)
./activemq start xbean:file:/myactivemq/conf/activemq02.xml
启动本地idea中的broker
public static void main(String[] args) throws Exception {
BrokerService brokerService = new BrokerService();
brokerService.setUseJmx(true);
brokerService.addConnector("tcp://localhost:61616");
brokerService.start();
}
G:\360Downloads\workspace201907\activemq>jps -l
3280 com.yubin.cn.activemq.Embed.EmbedBroker
6464 sun.tools.jps.Jps
1044 org.jetbrains.jps.cmdline.Launcher
5304 org.jetbrains.idea.maven.server.RemoteMavenServer
4284
G:\360Downloads\workspace201907\activemq>
四、spring整合activemq
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="com.yubin.cn.activemq"/>
<bean id ="jmsFactory" class="org.apache.activemq.pool.PooledConnectionFactory" destroy-method="stop">
<property name="connectionFactory">
<bean class="org.apache.activemq.ActiveMQConnectionFactory">
<property name="brokerURL" value="tcp://192.168.163.131:61616"/>
</bean>
</property>
<property name="maxConnections" value="100"></property>
</bean>
<!--目的地队列-->
<bean id="destinationQueue" class="org.apache.activemq.command.ActiveMQQueue">
<constructor-arg index="0" value="spring-active-queue"/>
</bean>
<!--目的地:topic-->
<bean id="destinationTopic" class="org.apache.activemq.command.ActiveMQTopic">
<constructor-arg index="0" value="spring-active-topic"/>
</bean>
<bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
<property name="connectionFactory" ref="jmsFactory"/>
<property name="defaultDestination" ref="destinationTopic"/>
<property name="messageConverter">
<bean class="org.springframework.jms.support.converter.SimpleMessageConverter"/>
</property>
</bean>
<bean id="jmsContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="connectionFactory" ref="jmsFactory"></property>
<property name="destination" ref="destinationTopic"></property>
<property name="messageListener" ref="myMessageListener"></property>
</bean>
</beans>
写实现MessageListener一个监听器的类 :可以实现不启动消费者只启动生产者就可以接收到消息(可以监听队列或者topic,只需要配置监听程序中将队列换成topic就可以)
@Component
public class MyMessageListener implements MessageListener {
@Override
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();
}
}
}
}
五、SpringBoot整合Activemq
1 队列:
//消息生产者主要代码
@Component
public class Queue_Producer {
@Autowired
private JmsMessagingTemplate jmsMessagingTemplate;
@Autowired
private Queue queue;
public void producerMsg() {
jmsMessagingTemplate.convertAndSend(queue,"******:"+UUID.randomUUID().toString().substring(0,6));
}
//间隔三秒往Mq推送消息以达到定时发送case,案例
@Scheduled(fixedDelay= 3000L )
public void produceMsgScheduled() {
jmsMessagingTemplate.convertAndSend(queue,"******Scheduled:"+UUID.randomUUID().toString().substring(0,6));
System.out.println("produceMsgScheduled send ok ");
}
}
//消息消费者部分代码
@Component
public class Queue_Consumer {
@JmsListener(destination = "${myqueue}")
public void receive(TextMessage textMessage) throws JMSException {
System.out.println("监听到的消息为:"+textMessage.getText());
}
}
使用jmsMessagetemplete生产消息,使用receive或者配置监听器消费消息。
2:发布订阅
topic生产者:
application.yml配置文件:
server:
port: 6666
spring:
activemq:
broker-url: tcp://192.168.163.131:61616
user: admin
password: admin
jms:
pub-sub-domain: true
#配置自己的自定义topic
mytopic: springboot-activemq-topic
***********************************************************
配置bean类
@Component
public class confBean {
@Value("${mytopic}")
private String topicName;
@Bean
public Topic topic() {
return new ActiveMQTopic(topicName);
}
}
***********************************************************
定时任务生产消息
@Component
public class Topic_Producer {
@Autowired
private JmsMessagingTemplate jmsMessagingTemplate;
@Autowired
private Topic topic;
@Scheduled(fixedDelay = 3000L)
public void producerTopic() {
jmsMessagingTemplate.convertAndSend(topic,"主题topic生产消息:"+UUID.randomUUID().toString().substring(0,6));
System.out.println("topic producer send end");
}
}
topic消费者:
application.yml配置文件
server:
port: 5567 #5567
spring:
activemq:
broker-url: tcp://192.168.163.131:61616
user: admin
password: admin
jms:
pub-sub-domain: true
#配置自己的自定义topic
mytopic: springboot-activemq-topic
*************************************************
消费者消费消息:
@Component
public class Topic_Consumer {
@JmsListener(destination = "${mytopic}")
public void receiveTopic(TextMessage textMessage) throws JMSException {
System.out.println("topic消费者接收消息:"+textMessage.getText());
}
}
六、AcitveMQ传输协议
tcp语法:tcp://hostname:port?key=value
参数可选的有可以参考官网:
https://activemq.apache.org/tcp-transport-reference
NIO 传输人协议:
amqp:
stomp:协议
SSL协议
mqtt协议:
ws协议
总结:
NIO案例:
消息生产者
public class JmsProduce {
// private static final String URL_BROKER = "tcp://192.168.163.131:61616";
// private static final String URL_BROKER = "tcp://localhost:61616";
private static final String URL_BROKER = "nio://192.168.163.131:61618";
private static final String QUEUE_NAME = "queue1";
public static void main(String[] args) throws JMSException {
//创建连接工厂
ActiveMQConnectionFactory activeMQConnectionFactory = new ActiveMQConnectionFactory(URL_BROKER);
//创建连接
Connection connection = activeMQConnectionFactory.createConnection();
connection.start();
//获取session
Session session = connection.createSession(true, Session.AUTO_ACKNOWLEDGE);
//声明队列
Queue queue = session.createQueue(QUEUE_NAME);
//创建生产者
MessageProducer producer = session.createProducer(queue);
for(int i = 1;i<=3;i++) {
TextMessage textMessage = session.createTextMessage("msg_" + i);
//设置消息属性
textMessage.setStringProperty("c01","vip");
producer.send(textMessage);
}
session.commit();
producer.close();
session.close();
connection.close();
System.out.println("消息发送完毕!");
}
}
**************************************************
消息消费者
// private static final String URL_BROKER = "tcp://192.168.163.131:61616";
// private static final String URL_BROKER = "tcp://localhost:61616";
private static final String URL_BROKER = "nio://192.168.163.131:61618";
private static final String QUEUE_NAME = "queue1";
public static void main(String[] args) throws JMSException, IOException {
System.out.println("我是2号消费者");
ActiveMQConnectionFactory activeMQConnectionFactory = new ActiveMQConnectionFactory(URL_BROKER);
Connection connection = activeMQConnectionFactory.createConnection();
connection.start();
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
Queue queue = session.createQueue(QUEUE_NAME);
MessageConsumer consumer = session.createConsumer(queue);
// 方式一 receive
/*
//订阅者或者接受者MessageConsumer的receive方法来接收消息,receive在能够接收的消息前将一直阻塞
while(true) {
//receive可以接收参数,可以指定等待时间,过时不候 Message receive(long timeout)
TextMessage receive = (TextMessage)consumer.receive();
if(null != receive) {
System.out.println("接收消息:"+receive.getText());
}else {
break;
}
}
consumer.close();
session.close();
connection.close();*/
//方式二 监听MessageListener
// 异步非阻塞方式(监听onMessage())
// 订阅者或者消息接受者MessageConsumer的setMessageListener(MessageLinstener listener)
// 注册一个消息监听,当消息到达后,系统自动调用监听器的监听方法
consumer.setMessageListener(new MessageListener() {
public void onMessage(Message message) {
if(null != message && message instanceof TextMessage) {
TextMessage textMessage = (TextMessage) message;
try {
System.out.println("接收消息:"+textMessage.getText());
System.out.println("接收消息:"+textMessage.getStringProperty("c01"));//获取消息属性
} catch (JMSException e) {
e.printStackTrace();
}
}
}
});
System.in.read();
consumer.close();
session.close();
connection.close();
System.out.println("消息接收完毕!");
}
}
NIO增强改进
七 activemq持久化
leaelDB:消息存储(了解)
步骤:
jar包:mysql-connector-java-5.1.38.jar
JDBC持久化JDBC persistence.演示
连接池的配置:
queue队列演示jdbc持久化结果
发布订阅topic持久化演示: activemq_acks表中存有信息,msg中消费成功也不会删除,会归档,相当于订阅后可以查看之前的历史
消息jdbc持久化总结和开发坑
如果queue,在没有消费者消费的情况下将消息保存到activemq_msgs表中。只要有任意一个消费者已经消费过,消费之后这些消息将会立即被删除。
如果是topic,一般先启动消费者订阅然后再生产的情况下会将消息保存到activemq_acks;
坑:
在配置关系型数据库作为activemq的持久化存储方案时候的坑,
数据库jar包,记得需要使用相关jar文件放在在activemq安装路径下lib目录下,mysql-jdbc驱动的jar包和对应的数据库连接池jar包
crateTablesOnStartup 属性
在jadbPersistenceAdapter标签中设置这个属性为true时在第一次启动activemq时候,activemq服务节点会自动创建所需要数据表。启动完成后可以去掉这个属性或者更改为false;
下划线坑爹。
“java.lang.IllegalStateException.BeanFactory.notinitialized or aleardy closed”
这个是因为您在操作系统的机器名中有“_”符号,请修改机器名并且重启后即可解决
jdbc with journal 演示
带高速缓存日志功能的jdbc 持久
<persistenceFactory>
<journalPersistenceAdapterFactory
journalLogFiles="4"
journalLogFileSize="32768"
useJournal="true"
useQuickJournal="true"
dataSource="mysql-ds"
dataDirectory="activemq-data"
</persistenceFactory>
相当于在mysql数据库前面当了一层journal高速缓存,有数据先从journal中存着,如果七八分钟没有消费就慢慢写入mysql,消费也先从journal消费,然后等七八分钟后同步到mysql,将myslq中删除,有点读写分离的样子。
八、ActiveMQ集群
集群原理图
九、高级特性
一 异步投递
:指定同步或者非事务情况下发送持久化消息两种情况下是同步的,其他都是异步的
官方配置:三种方式
异步发送如何确定发送成功 :正确的异步发送是需要接收回调的
ActiveMQMessageProduce 生产者回调方法确定消息发送成功
public class JmsProduce_mianshi_async {
private static final String URL_BROKER = "tcp://192.168.163.131:61616";
private static final String QUEUE_NAME = "queue_async";
public static void main(String[] args) throws JMSException {
//创建连接工厂
ActiveMQConnectionFactory activeMQConnectionFactory = new ActiveMQConnectionFactory(URL_BROKER);
//开启异步投递
activeMQConnectionFactory.setUseAsyncSend(true);
//创建连接
Connection connection = activeMQConnectionFactory.createConnection();
connection.start();
//获取session
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
//声明队列
Queue queue = session.createQueue(QUEUE_NAME);
//创建生产者
ActiveMQMessageProducer producer = (ActiveMQMessageProducer) session.createProducer(queue);
for (int i = 1; i <= 3; i++) {
TextMessage textMessage = session.createTextMessage("msg_" + i);
textMessage.setJMSMessageID(UUID.randomUUID().toString() + "order yubin");
String jmsMessageID = textMessage.getJMSMessageID();
//设置消息属性
// textMessage.setStringProperty("c01","vip");
producer.send(textMessage, new AsyncCallback() {
//异步发送消息:确认发送成功
@Override
public void onSuccess() {
System.out.println("messageId:" + jmsMessageID + ".消息发送成功");
}
@Override
public void onException(JMSException exception) {
System.out.println("消息发送失败");
}
});
}
producer.close();
session.close();
connection.close();
System.out.println("消息发送完毕!");
}
}
二、延迟投递和定时投递
四大属性:
延迟投递和定时投递使用案例 :步骤
1 broker服务器开启对延迟和定时的支持schedulerSupport="true"
2 代码编写
private static final String URL_BROKER = "tcp://192.168.163.131:61616";
private static final String QUEUE_NAME = "delayAndSchedule";
public static void main(String[] args) throws JMSException {
//创建连接工厂
ActiveMQConnectionFactory activeMQConnectionFactory = new ActiveMQConnectionFactory(URL_BROKER);
//创建连接
Connection connection = activeMQConnectionFactory.createConnection();
connection.start();
//获取session
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
//声明队列
Queue queue = session.createQueue(QUEUE_NAME);
//创建生产者
MessageProducer producer = session.createProducer(queue);
//开启消息持久化
producer.setDeliveryMode(DeliveryMode.PERSISTENT);
Long dalay = 3 * 1000L;
Long period = 4 * 1000L;
int repeat = 5;
for(int i = 1;i<=3;i++) {
TextMessage textMessage = session.createTextMessage("msg_" + i);
//设置消息属性
textMessage.setStringProperty("c01","vip");
textMessage.setLongProperty(ScheduledMessage.AMQ_SCHEDULED_DELAY,dalay);
textMessage.setLongProperty(ScheduledMessage.AMQ_SCHEDULED_PERIOD,period);
textMessage.setIntProperty(ScheduledMessage.AMQ_SCHEDULED_REPEAT,repeat);
producer.send(textMessage);
}
producer.close();
session.close();
connection.close();
System.out.println("消息发送完毕!");
}
三、Activemq重试机制
https://activemq.apache.org/redelivery-policy
面试题:
具体哪些情况会引起消息重试
说说消息重发时间间隔和重发次数
有毒消息Poison ACK谈谈你的理解
体哪些情况会引起消息重试
答案:
1 client用了transactions并且session调用了rollback()
2 client调用transactions并且调用commit()之前关闭或者没有commit
3 client在client_acknowledeg的传递模式下,sesion调用recover()
说说消息重发时间间隔和重发次数
答案:1秒间隔 重发6次数
有毒的posion ack 谈谈理解
一个消息被redelivedred超过默认做大重发次数(6次)时候,消息端会给ma发送一个posion ack表示这个消息有毒,
告诉break不要再发了,这个时候break会把这个消息放到DLQ(死信队列)
重发机制的属性
//手动配置重发机制,不用默认的
RedeliveryPolicy redeliveryPolicy = new RedeliveryPolicy();
redeliveryPolicy.setMaximumRedeliveries(3);
activeMQConnectionFactory.setRedeliveryPolicy(redeliveryPolicy);
//重试机制,开启事务但是不提交,测试消费六次加第一给 后就不会有消费了
public class JmsConsumer_Redelivery_Policy {
private static final String URL_BROKER = "tcp://192.168.163.131:61616";
private static final String QUEUE_NAME = "redleivey_policy";
public static void main(String[] args) throws JMSException, IOException {
System.out.println("我是2号消费者");
ActiveMQConnectionFactory activeMQConnectionFactory = new ActiveMQConnectionFactory(URL_BROKER);
//手动配置重发机制,不用默认的
RedeliveryPolicy redeliveryPolicy = new RedeliveryPolicy();
redeliveryPolicy.setMaximumRedeliveries(3);
activeMQConnectionFactory.setRedeliveryPolicy(redeliveryPolicy);
Connection connection = activeMQConnectionFactory.createConnection();
connection.start();
Session session = connection.createSession(true, Session.AUTO_ACKNOWLEDGE);
Queue queue = session.createQueue(QUEUE_NAME);
MessageConsumer consumer = session.createConsumer(queue);
// 方式一 receive
/*
//订阅者或者接受者MessageConsumer的receive方法来接收消息,receive在能够接收的消息前将一直阻塞
while(true) {
//receive可以接收参数,可以指定等待时间,过时不候 Message receive(long timeout)
TextMessage receive = (TextMessage)consumer.receive();
if(null != receive) {
System.out.println("接收消息:"+receive.getText());
}else {
break;
}
}
consumer.close();
session.close();
connection.close();*/
//方式二 监听MessageListener
// 异步非阻塞方式(监听onMessage())
// 订阅者或者消息接受者MessageConsumer的setMessageListener(MessageLinstener listener)
// 注册一个消息监听,当消息到达后,系统自动调用监听器的监听方法
consumer.setMessageListener(new MessageListener() {
public void onMessage(Message message) {
if(null != message && message instanceof TextMessage) {
TextMessage textMessage = (TextMessage) message;
try {
System.out.println("接收消息:"+textMessage.getText());
System.out.println("接收消息:"+textMessage.getStringProperty("c01"));//获取消息属性
} catch (JMSException e) {
e.printStackTrace();
}
}
}
});
// session.commit();
System.in.read();
consumer.close();
session.close();
connection.close();
System.out.println("消息接收完毕!");
}
重发机制整合在spring中的配置
四、死信队列
死信队列的应用
配置共享和私有的死信队列
shareDeadLetterStrategy,IndvidualDeadLetterStrategy
配置自动删除过期消息
配置存放非持久性的消息到死信队列
死信队列配置案例
五、重复消费问题以及幂等性
面试:如何保证消息不被重复消费,幂等性问题的理解