从ActiveMQ原理到实例
来源:互联网 发布:linux端口映射软件 编辑:程序博客网 时间:2024/05/14 02:40
在介绍activemq之前,先简单介绍JMS,它是J2EE的13个规范之一,提供的是消息中间件的规范。
JMS包括以下基本构件:
连接工厂,是客户用来创建连接的对象,ActiveMQ提供的是ActiveMQConnectionFactory;
连接connection;
会话session,是发送和接收消息的上下文,用于创建消息生产者,消息消费者,相比rocketMQ会话session是提供事务性的;
目的地destination,指定生产消息的目的地和消费消息的来源对象;
生产者、消费者,由会话创建的对象,顾名思义。
消息通信机制
点对点模式,每个消息只有1个消费者,它的目的地称为queue队列;
发布/订阅模式,每个消息可以有多个消费者,而且订阅一个主题的消费者,只能消费自它订阅之后发布的消息。
消息确认机制
Session.AUTO_ACKNOWLEDGE,直接使用receive方法。
Session.CLIENT_ACKNOWLEDGE,通过消息的acknowledge 方法确认消息。
Session.DUPS_ACKNOWLEDGE,该选择只是会话迟钝第确认消息的提交。如果JMS provider 失败,那么可能会导致一些重复的消息。如果是重复的消息,那么JMS provider 必须把消息头的JMSRedelivered 字段设置为true。
原理很多,但是把原理映射在实践中,就更容易懂了。一起看看下面的这个小例子,通过代码回想原理,最后运行显示到控制台上,验证结论。
新建一个普通Java Project,引进activemq的jar包,build到项目中。新建生产者producer、消费者consumer,如下:
package com.java.activemq;import javax.jms.Connection;import javax.jms.ConnectionFactory;import javax.jms.Destination;import javax.jms.JMSException;import javax.jms.MessageProducer;import javax.jms.Session;import javax.jms.TextMessage;import org.apache.activemq.ActiveMQConnection;import org.apache.activemq.ActiveMQConnectionFactory;/** * 消息生产者 * @author xing.liu * */public class JMSProducer {private static final String USERNAME=ActiveMQConnection.DEFAULT_USER; // 默认的连接用户名private static final String PASSWORD=ActiveMQConnection.DEFAULT_PASSWORD; // 默认的连接密码private static final String BROKEURL=ActiveMQConnection.DEFAULT_BROKER_URL; // 默认的连接地址private static final int SENDNUM=10; // 发送的消息数量public static void main(String[] args) {ConnectionFactory connectionFactory; // 连接工厂Connection connection = null; // 连接Session session; // 会话 接受或者发送消息的线程Destination destination; // 消息的目的地MessageProducer messageProducer; // 消息生产者// 实例化连接工厂connectionFactory=new ActiveMQConnectionFactory(JMSProducer.USERNAME, JMSProducer.PASSWORD, JMSProducer.BROKEURL);try {connection=connectionFactory.createConnection(); // 通过连接工厂获取连接connection.start(); // 启动连接// 创建Session,第一个参数是开启事务true,第二个参数是消息确认机制属性session=connection.createSession(Boolean.TRUE, Session.AUTO_ACKNOWLEDGE); destination=session.createQueue("FirstQueue1"); // 创建消息队列messageProducer=session.createProducer(destination); // 创建消息生产者sendMessage(session, messageProducer); // 发送消息session.commit();} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();} finally{if(connection!=null){try {connection.close();} catch (JMSException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}}/** * 发送消息 * @param session * @param messageProducer * @throws Exception */public static void sendMessage(Session session,MessageProducer messageProducer)throws Exception{for(int i=0;i<JMSProducer.SENDNUM;i++){TextMessage message=session.createTextMessage("ActiveMQ 发送的消息"+i);System.out.println("发送消息:"+"ActiveMQ 发送的消息"+i);messageProducer.send(message);}}}
package com.java.activemq;import javax.jms.Connection;import javax.jms.ConnectionFactory;import javax.jms.Destination;import javax.jms.JMSException;import javax.jms.MessageConsumer;import javax.jms.Session;import javax.jms.TextMessage;import org.apache.activemq.ActiveMQConnection;import org.apache.activemq.ActiveMQConnectionFactory;/** * 消息消费者 * @author xing.liu * */public class JMSConsumer {private static final String USERNAME=ActiveMQConnection.DEFAULT_USER; // 默认的连接用户名private static final String PASSWORD=ActiveMQConnection.DEFAULT_PASSWORD; // 默认的连接密码private static final String BROKEURL=ActiveMQConnection.DEFAULT_BROKER_URL; // 默认的连接地址public static void main(String[] args) {ConnectionFactory connectionFactory; // 连接工厂Connection connection = null; // 连接Session session; // 会话 接受或者发送消息的线程Destination destination; // 消息的目的地MessageConsumer messageConsumer; // 消息的消费者// 实例化连接工厂connectionFactory=new ActiveMQConnectionFactory(JMSConsumer.USERNAME, JMSConsumer.PASSWORD, JMSConsumer.BROKEURL);try {connection=connectionFactory.createConnection(); // 通过连接工厂获取连接connection.start(); // 启动连接session=connection.createSession(Boolean.FALSE, Session.AUTO_ACKNOWLEDGE); // 创建Sessiondestination=session.createQueue("FirstQueue1"); // 创建连接的消息队列messageConsumer=session.createConsumer(destination); // 创建消息消费者while(true){TextMessage textMessage=(TextMessage)messageConsumer.receive(100000);if(textMessage!=null){System.out.println("收到的消息:"+textMessage.getText());}else{break;}}} catch (JMSException e) {// TODO Auto-generated catch blocke.printStackTrace();} }}
这个demo是简单的点对点模式下,目的地对象是queue队列,代码中可以看出session.createQueue;从代码中可以联想到上边的原理,也是简而易懂。messageConsumer.receive(100000)这使用的是receive模式,这种模式让消费者consumer不断的问producer要消息,很乱的。
安装了ActiveMQ服务器,在浏览器打开后台监控,地址 http://127.0.0.1:8161/admin/
可以在Queues中看到消息未被消费的条数,已消费的条数。后台监控系统都是一样的,类似rocketMQ,我就不介绍了,多点点就能明白。
所以生产中我们常用的是监听listener模式,看看下边这个带监听的consumer:
package com.java.activemq;import javax.jms.Connection;import javax.jms.ConnectionFactory;import javax.jms.Destination;import javax.jms.JMSException;import javax.jms.MessageConsumer;import javax.jms.Session;import javax.jms.TextMessage;import org.apache.activemq.ActiveMQConnection;import org.apache.activemq.ActiveMQConnectionFactory;/** * 消息消费者 * @author xing * */public class JMSConsumer2 {private static final String USERNAME=ActiveMQConnection.DEFAULT_USER; // 默认的连接用户名private static final String PASSWORD=ActiveMQConnection.DEFAULT_PASSWORD; // 默认的连接密码private static final String BROKEURL=ActiveMQConnection.DEFAULT_BROKER_URL; // 默认的连接地址public static void main(String[] args) {ConnectionFactory connectionFactory; // 连接工厂Connection connection = null; // 连接Session session; // 会话 接受或者发送消息的线程Destination destination; // 消息的目的地MessageConsumer messageConsumer; // 消息的消费者// 实例化连接工厂connectionFactory=new ActiveMQConnectionFactory(JMSConsumer2.USERNAME, JMSConsumer2.PASSWORD, JMSConsumer2.BROKEURL);try {connection=connectionFactory.createConnection(); // 通过连接工厂获取连接connection.start(); // 启动连接session=connection.createSession(Boolean.FALSE, Session.AUTO_ACKNOWLEDGE); // 创建Sessiondestination=session.createQueue("FirstQueue1"); // 创建连接的消息队列messageConsumer=session.createConsumer(destination); // 创建消息消费者messageConsumer.setMessageListener(new Listener()); // 注册消息监听} catch (JMSException e) {// TODO Auto-generated catch blocke.printStackTrace();} }}
package com.java.activemq;import javax.jms.JMSException;import javax.jms.Message;import javax.jms.MessageListener;import javax.jms.TextMessage;/** * 消息监听 * @author xing * */public class Listener implements MessageListener{@Overridepublic void onMessage(Message message) {try {System.out.println("收到的消息:"+((TextMessage)message).getText());} catch (JMSException e) {e.printStackTrace();}}}
这种消息监听模式,只是多一个注册消息监听messageConsumer.setMessageListener(new Listener());
- 从ActiveMQ原理到实例
- ActiveMQ从入门到实践
- ActiveMQ从入门到精通(一)
- ActiveMQ从入门到精通(二)
- ActiveMQ从入门到精通(三)
- ActiveMQ从初识到使用(一)
- ActiveMQ从入门到精通(一)
- ActiveMQ从入门到精通(二)
- ActiveMQ从入门到精通(三)
- ActiveMQ 实例
- ActiveMQ实例
- activeMq 实例
- ActiveMQ实例
- ActiveMQ实例
- Activemq实例
- ActiveMQ实例
- 关于深度学习中的注意力机制,这篇文章从实例到原理都帮你参透了
- CRC从原理到实现
- C++ 编程题练习-输出指定结果一(10-2)
- 使用Java进行FreeMarker的web模板开发的基础教程
- 【错误】未能找到类型或命名空间名称
- 短信验证码API的安全
- 2015 acm icpc asia regional changchun 队内 模拟 + 背包复习 +Tire树
- 从ActiveMQ原理到实例
- C语言setpwent()函数:从头读取密码文件中的账号数据
- 使用Live555类库实现的网络直播系统
- swust1741: 最长递增子序列问题
- 享受读书的快乐
- Activiti学习——模型管理模块
- 选择排序法
- Java中使用正则表达式判断是否为手机号和邮箱
- git ignore 文件配置