Java编码实现ActiveMQ通讯
JMS编码总体规范
由ConnectionFactory工厂获得了连接 Connection,由连接 Connection获得了Session ,Session创建了对应的消息Msg。
生成者把消息发送到Destination,目的地包含队列与主题
-
一对一 sender 例如张三给李四单独发送了一条消息
-
一对多 publish(发布与订阅)关注了某个公众号,批量发送关注公众号的人员
-
POM文件
<dependencies>
<!-- activemq 所需要的jar 包-->
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-all</artifactId>
<version>5.15.9</version>
</dependency>
<!-- activemq 和 spring 整合的基础包 -->
<dependency>
<groupId>org.apache.xbean</groupId>
<artifactId>xbean-spring</artifactId>
<version>3.16</version>
</dependency>
</dependencies>
- JMS开发的基本步骤
目的地(Destination)
- 两大模式特性
- 在点对点的消息传递域中,目的地被称为对列
- 在发布订阅的消息传递域中,目的地被称为主题
QUEUE
- 生产者 代码
package com.example.activemq.queue;
import org.apache.activemq.ActiveMQConnectionFactory;
import javax.jms.*;
public class JmsProduce {
private static final String ACTIVEMQ_URL = "tcp://172.17.35.110:8161";
private static final String QUEUE_NAME = "queue01";
public static void main(String[] args) throws JMSException {
//1.创建连接工厂,按照给定的url地址采用默认的用户名与密码
ActiveMQConnectionFactory activeMQConnectionFactory = new ActiveMQConnectionFactory(ACTIVEMQ_URL);
//2.通过连接工厂,获得连接connection并启动访问
Connection connection = activeMQConnectionFactory.createConnection();
connection.start();
//3.创建会话session 两个参数 事务,签收
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
//4.创建目的地 队列或者主题
Queue queue = session.createQueue(QUEUE_NAME);
//5.创建消息的生产者,放到Mq目的地消息队列里面
MessageProducer messageProducer = session.createProducer(queue);
//6.通过使用消息生产者生产3条消息发送到mq队列里面
for (int i = 0; i < 3; i++) {
//7.创建消息,生产者按照mq的格式写好了需求消息
TextMessage textMessage = session.createTextMessage("msg --- " + i);//理解为一个字符串
//8.通过messageProducer发送给mq
messageProducer.send(textMessage);
}
//9.关闭资源
messageProducer.close();
session.close();
connection.close();
System.out.println("消息发布到mq完成");
}
}
- 消费者 代码
package com.example.activemq.queue;
import org.apache.activemq.ActiveMQConnectionFactory;
import javax.jms.*;
public class JmsConsumer {
private static final String ACTIVEMQ_URL = "tcp://172.17.35.110:8161";
private static final String QUEUE_NAME = "queue01";
public static void main(String[] args) throws JMSException {
//1.创建连接工厂,按照给定的url地址采用默认的用户名与密码
ActiveMQConnectionFactory activeMQConnectionFactory = new ActiveMQConnectionFactory(ACTIVEMQ_URL);
//2.通过连接工厂,获得连接connection并启动访问
Connection connection = activeMQConnectionFactory.createConnection();
connection.start();
//3.创建会话session 两个参数 事务,签收
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
//4.创建目的地 队列或者主题
Queue queue = session.createQueue(QUEUE_NAME);
//5.创建消费者
MessageConsumer messageConsumer = session.createConsumer(queue);
while (true) {
//死等,无时间限制 long 有等待时间
TextMessage textMessage = (TextMessage) messageConsumer.receive();
if (null != textMessage) {
System.out.println("消费者收到消息" + textMessage.getText());
} else {
break;
}
}
messageConsumer.close();
session.close();
connection.close();
}
}
- 订阅者或者接收者在调用MessageConsumer的recive()方法,消费消息。(同步阻塞方式)
- Message receive() throws JMSException
该方法在能够接收到消息之前,将一直等待 - Message receive(long var1) throws JMSException
参数时间 ,消费者不需要进行死等,当超过时间期限就退出消费者数量。
- Message receive() throws JMSException
- 通过监听的方法消费消息 (异步非阻塞方式 监听器 onMessage())
当消息到达之后,系统会自动调用监听器MessageListener的onMessage() 方法。使用监听器,需要注意给消费者一点时间等他消费完了开始关闭。 == System.in.read();==
package com.example.activemq.queue;
import org.apache.activemq.ActiveMQConnectionFactory;
import javax.jms.*;
import java.io.IOException;
public class JmsConsumer {
private static final String ACTIVEMQ_URL = "tcp://172.17.35.110:8161";
private static final String QUEUE_NAME = "queue01";
public static void main(String[] args) throws JMSException, IOException {
//1.创建连接工厂,按照给定的url地址采用默认的用户名与密码
ActiveMQConnectionFactory activeMQConnectionFactory = new ActiveMQConnectionFactory(ACTIVEMQ_URL);
//2.通过连接工厂,获得连接connection并启动访问
Connection connection = activeMQConnectionFactory.createConnection();
connection.start();
//3.创建会话session 两个参数 事务,签收
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
//4.创建目的地 队列或者主题
Queue queue = session.createQueue(QUEUE_NAME);
//5.创建消费者
MessageConsumer messageConsumer = session.createConsumer(queue);
messageConsumer.setMessageListener(new 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();
}
}
}
});
System.in.read();
messageConsumer.close();
session.close();
connection.close();
}
}
- 先生产,只启动1号消费者,1号消费者能消费消息吗? Y
- 先生产,先启动1号消费者,在启动2号消费者,2号消费者能消费消息吗?N
一号消费者消费完了,2号消费者在默默监听者,因为消费的消息已经出队列了
- 先启动两个消费者,在生产6条消息 ,消费情况如何?.
负载均衡,平均分配
总结
TOPIC
先要启动订阅在启动生产,不然发送的消息是废消息
- 生产者代码
package com.example.activemq.queue;
import org.apache.activemq.ActiveMQConnectionFactory;
import javax.jms.*;
public class JmsProduce_Topic {
private static final String ACTIVEMQ_URL = "tcp://172.17.35.110:8161";
private static final String TOPIC_NAME = "topic_01";
public static void main(String[] args) throws JMSException {
//1.创建连接工厂,按照给定的url地址采用默认的用户名与密码
ActiveMQConnectionFactory activeMQConnectionFactory = new ActiveMQConnectionFactory(ACTIVEMQ_URL);
//2.通过连接工厂,获得连接connection并启动访问
Connection connection = activeMQConnectionFactory.createConnection();
connection.start();
//3.创建会话session 两个参数 事务,签收
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
//4.创建目的地 队列或者主题
Queue queue = (Queue) session.createTopic(TOPIC_NAME);
//5.创建消息的生产者,放到Mq目的地消息队列里面
MessageProducer messageProducer = session.createProducer(queue);
//6.通过使用消息生产者生产3条消息发送到mq队列里面
for (int i = 0; i < 3; i++) {
//7.创建消息,生产者按照mq的格式写好了需求消息
TextMessage textMessage = session.createTextMessage("msg --- " + i);//理解为一个字符串
//8.通过messageProducer发送给mq
messageProducer.send(textMessage);
}
//9.关闭资源
messageProducer.close();
session.close();
connection.close();
System.out.println("消息发布到mq完成");
}
}
- 消费者代码
package com.example.activemq.queue;
import org.apache.activemq.ActiveMQConnectionFactory;
import javax.jms.*;
import java.io.IOException;
public class JmsConsumer_Topic {
private static final String ACTIVEMQ_URL = "tcp://172.17.35.110:8161";
private static final String TOPIC_NAME = "topic_01";
public static void main(String[] args) throws JMSException, IOException {
//1.创建连接工厂,按照给定的url地址采用默认的用户名与密码
ActiveMQConnectionFactory activeMQConnectionFactory = new ActiveMQConnectionFactory(ACTIVEMQ_URL);
//2.通过连接工厂,获得连接connection并启动访问
Connection connection = activeMQConnectionFactory.createConnection();
connection.start();
//3.创建会话session 两个参数 事务,签收
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
//4.创建目的地 队列或者主题
Queue queue = (Queue) session.createTopic(TOPIC_NAME);
//5.创建消费者
MessageConsumer messageConsumer = session.createConsumer(queue);
System.out.println("***我是1号消费者");
messageConsumer.setMessageListener(message -> {
if (null != message && message instanceof TextMessage) {
TextMessage textMessage = (TextMessage) message;
try {
System.out.println("****消费者收到消息:MessageListener---" + textMessage.getText());
} catch (JMSException e) {
e.printStackTrace();
}
}
});
System.out.println("***我是1号消费者");
messageConsumer.setMessageListener(new MessageListener() {
@Override
public void onMessage(Message message) {
if (null != message && message instanceof TextMessage) {
TextMessage textMessage = (TextMessage) message;
try {
System.out.println("****消费者收到消息:MessageListener---" + textMessage.getText());
} catch (JMSException e) {
e.printStackTrace();
}
}
}
});
System.in.read();
messageConsumer.close();
session.close();
connection.close();
}
}
在topic模式中,凡是订阅者都可以收到,在topic模式中,先生产者生产在消费者消费,就会导致先生产的数据没有被消费到
区别
activemq默认端口号为:61616 ,对外访问的端口号为:ip:8161/admin/”