一、JMS概述
1、四大元素
JMS provider 中间件,消息服务器
JMS producer 生产者,创建和发送jms消息的客户端应用
jms consumer 消费者
jms message 消息–消息头–消息属性–消息体
2、JMS消息头
JMSDestination 消息目的地:队列Queue或主题Topic
JMSDeliveryMode 持久或者非持久DeliveryMode.PERSISTENT持久
JMSExpiration 过期时间:默认永不过期,
JMSPriority 优先级0-4普通,5-9加急,默认是4级
JMSMessageID 唯一识别每个消息的标识
3、JMS消息体
TextMessage 字符串
MapMessage key value键值对
BytesMessage 二进制数组
StreamMessage 流式填充
ObjectMessage 对象消息
4、JMS消息属性
需要消息头以外的值则添加消息属性
识别、去重、重点标注等操作非常有用的方法
TextMessage textMessage = session.createTextMessage("text--msg" + i);
//创建消息,消息属性
textMessage.setStringProperty("c01","vip");
//获取消息属性
String c01 = textMessage.getStringProperty("c01");
System.out.println("消息属性"+c01);
二、JMS保证消息可靠性
1、持久性
2、事务
3、签收
1、消息的持久化,系统默认是持久化
生产消息时的参数设置
//持久化,消息存在
producer.setDeliveryMode(DeliveryMode.PERSISTENT);
//非持久化,服务器宕机,消息不存在,并不能消费的到
producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
消息持久化后,待消费的消息会存储消息,可以正常消费
此模式保证这些消息只被传送一次,和成功使用一次,这些消息,可靠性是优先考虑的因素
在消费者消费前不会丢失消息
点对点传输下
订阅模式下
JMS发布订阅总结:
非持久和持久
非持久化订阅
持久化订阅
三、ActiveMQ集成springboot
生产者
private final static Logger logger = LoggerFactory.getLogger(TestController.class);
private final static String BROKERURL = "failover:(tcp://192.168.137.128:61616,tcp://192.168.137.128:61617,tcp://192.168.137.128:61618)";
private final static String QUEUE_NAME = "failoverQueue01";
public static void main(String[] args) throws Exception {
ActiveMQConnectionFactory acMqConnection = new ActiveMQConnectionFactory(BROKERURL);
//开启异步投递
acMqConnection.setUseAsyncSend(true);
//创建连接工厂
Connection connection = acMqConnection.createConnection();
//获得连接
connection.start();
//两个参数1:事务2:签收
/**
* 当第一个参数为true时,表示使用了事务,现在使用send方法,并不能发送还需要
* commit提交
*/
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
//队列或topic
//队列
Queue queue = session.createQueue(QUEUE_NAME);
//创建消息生产者
MessageProducer producer = session.createProducer(queue);
//持久化
producer.setDeliveryMode(DeliveryMode.PERSISTENT);
//producer.setTimeToLive(30000L);
try {
for (int i = 0; i < 5; i++) {
TextMessage textMessage = session.createTextMessage("text--msg" + i);
//创建消息
// textMessage.setStringProperty("c01", "vip");
//使用mysql,必须开启持久化
producer.send(textMessage);
}
producer.close();
//在生产者关闭前添加提交
// session.commit();
System.out.println("生产完成!");
} catch (JMSException e) {
//消息队列回滚
// session.rollback();
e.printStackTrace();
} finally {
if (session != null) {
session.close();
}
if (connection != null) {
connection.close();
}
}
消费者
yml
spring:
application:
name: test_activemq_consumer
activemq:
broker-url: tcp://192.168.137.128:61616
user: admin
password: admin
jms: #队列false,true为订阅
pub-sub-domain: false
myqueue: myTopicqueue #这个为队列名称
package com.active.common.consumer;
import org.springframework.jms.annotation.JmsListener;
import org.springframework.stereotype.Component;
import javax.jms.JMSException;
import javax.jms.TextMessage;
/*
* @ClassName:TestConsumer
* @Description
* @Author
* @Time 2019/7/4 16:48
*/
@Component
public class TestConsumer {
public static void main(String[] args){
System.out.println("111111111111");
}
@JmsListener(destination = "${myqueue}")
public void receie(TextMessage textMessage){
try {
System.out.println("消费者受到消息:"+textMessage.getText());
} catch (JMSException e) {
e.printStackTrace();
}
}
}
消费者2
package com.example.docker.consumer;
import org.apache.activemq.ActiveMQConnectionFactory;
import org.apache.activemq.RedeliveryPolicy;
import org.springframework.data.redis.core.RedisTemplate;
import javax.jms.*;
/*
* @ClassName:TestConsumer
* @Description
* @Author 李奥
* @Time 2019/6/19 20:34
*/
public class TestConsumer {
private final static String BROKERURL = "failover:(tcp://192.168.137.128:61616,tcp://192.168.137.128:61617,tcp://192.168.137.128:61618)";
private final static String QUEUE_NAME = "failoverQueue01";
private RedisTemplate redisTemplate;
public static void main(String[] args) throws Exception {
ActiveMQConnectionFactory acMqConnection = new ActiveMQConnectionFactory(BROKERURL);
//自定义重复消费次数
RedeliveryPolicy queuePolicy = new RedeliveryPolicy();
//消费了3次后进死心队列
queuePolicy.setMaximumRedeliveries(3);
acMqConnection.setRedeliveryPolicy(queuePolicy);
//创建连接工厂
Connection connection = acMqConnection.createConnection();
//获得连接
connection.start();
//两个参数1:事务2:签收
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
//队列或topic
//队列
Queue queue = session.createQueue(QUEUE_NAME);
//创建消息消费者
MessageConsumer consumer = session.createConsumer(queue);
/* //1、同步阻塞,订阅模式
while (true){
//3秒内没消息我撤
TextMessage receive =(TextMessage) consumer.receive(3000L);
if(receive!=null){
System.out.println("消费者消费:"+receive.getText());
}else {
break;
}
}*/
//2、监听消费,可能消费不到,还没消费就给close了,异步非阻塞
consumer.setMessageListener((message) -> {
if (message != null && message instanceof TextMessage) {
TextMessage textMessage = (TextMessage) message;
try {
String c01 = textMessage.getStringProperty("c01");
System.out.println("消息属性" + c01);
System.out.println("消费消息:" + textMessage.getText());
//手动签收
// textMessage.acknowledge();
} catch (JMSException e) {
e.printStackTrace();
}
} else if (message != null && 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();
// session.commit();
consumer.close();
session.close();
connection.close();
System.out.println("消费完成!");
//1.先生产后启动一号和二号消费者
//两个消费者等候消息,会一人一半,会存在轮休的味道
}
}