JMS —— ActiveMQ入门

JMS: Java 消息服务(Java Message Service),是 Java 平台上有关面向 MOM 的技术规范,旨在通过提供标准的产生、发送、接收和处理消息的 API 简化企业应用的开发,类似于 JDBC 和关系型数据库通信方式的抽象。

  • Provider:纯 Java 语言编写的 JMS 接口实现(比如 ActiveMQ 就是)
  • Domains:消息传递方式,包括点对点(P2P)、发布/订阅(Pub/Sub)两种
  • Connection factory:客户端使用连接工厂来创建与 JMS provider 的连接
  • Destination:消息被寻址、发送以及接收的对象

消息生产者和消息消费者又有两种关系 P2P 和 Pub/Sub

P2P (点对点)消息域使用 queue 作为 Destination,消息可以被同步或异步的发送和接收,每个消息只会给一个 Consumer 传送一次。

Consumer 可以使用 MessageConsumer.receive() 同步地接收消息,也可以通过使用MessageConsumer.setMessageListener() 注册一个 MessageListener 实现异步接收。

多个 Consumer 可以注册到同一个 queue 上,但一个消息只能被一个 Consumer 所接收,然后由该 Consumer 来确认消息。并且在这种情况下,Provider 对所有注册的 Consumer 以轮询的方式发送消息。

Pub/Sub(发布/订阅,Publish/Subscribe)消息域使用 topic 作为 Destination,发布者向 topic 发送消息,订阅者注册接收来自 topic 的消息。发送到 topic 的任何消息都将自动传递给所有订阅者。接收方式(同步和异步)与 P2P 域相同。
除非显式指定,否则 topic 不会为订阅者保留消息。当然,这可以通过持久化(Durable)订阅来实现消息的保存。这种情况下,当订阅者与 Provider 断开时,Provider 会为它存储消息。当持久化订阅者重新连接时,将会受到所有的断连期间未消费的消息。

JMS创建程序的通用步骤:

  1. 获取连接工厂
  2. 使用连接工厂创建连接
  3. 启动连接
  4. 从连接创建会话
  5. 获取 Destination
  6. 创建 Producer,或
    • 创建 Producer
    • 创建 message
  7. 创建 Consumer,或发送或接收message发送或接收 message
    • 创建 Consumer
    • 注册消息监听器(可选)
  8. 发送或接收 message
  9. 关闭资源(connection, session, producer, consumer 等)

ActiveMQ步骤:

官网:http://activemq.apache.org/

本地解压后: 进入bin,根据个人系统,选择响应文件夹中的activemq.bat启动

即可访问:ActiveMQ 服务启动地址:http://127.0.0.1:8161/admin/ 用户名/密码 admin/admin

队列:ActiveMQ 在 queue 中存储 Message 时,采用先进先出顺序(FIFO)存储。同一时间一个消息被分派给单个消费者,且只有当 Message 被消费并确认时,它才能从存储中删除。

队列对应点对点模式实现:

将官网下载下来的 activemq-all-5.15.9.jar 导入工程

步骤一:创建消息生产者:

package com.tao.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 
 *
 */
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实例化   connection.createSession(arg0, arg1) arg0:是否加入事务 arg1:消息确认方式
			session = connection.createSession(Boolean.TRUE, Session.AUTO_ACKNOWLEDGE);
			//创建消息队列
			destination = session.createQueue("This is my First Queue");
			//创建消息生产者
			messageProducer = session.createProducer(destination);
			sendMessage(session, messageProducer);
			//提交消息
			session.commit();
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}finally {
				if(connection!=null) {
					try {
						connection.close();
					} catch (JMSException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
			}
		
	}
	
	/**
	 * 发送消息
	 * @param session
	 * @param messageProducer
	 * @throws Exception
	 */
	private static void sendMessage(Session session,MessageProducer messageProducer) throws Exception{
		for(int i=1; i<=JMSProducer.SENDNUM;i++) {
			TextMessage textMessage = session.createTextMessage("ActiveMQ 发送的消息:"+i);
			System.out.println("发送消息:"+ "ActiveMQ 发送的消息:"+i);
			messageProducer.send(textMessage);
			
		}
	}
	
	
	
	

}

创建消息消费者:调用 messageConsumer.receive(1000) 接受消息

package com.tao.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 
 *
 */
public class JMDConsumer {
	
	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(JMDConsumer.USERNAME, JMDConsumer.PASSWORD, JMDConsumer.BROKEURL);
		
		try {
			//通过连接工厂获取连接
			connection = connectionFactory.createConnection();
			//启动连接
			connection.start();
			//session实例化 消费无需加事务
			session = connection.createSession(Boolean.FALSE, Session.AUTO_ACKNOWLEDGE);
			//点对点消费 消费方创建的消息队列名需和生产方一致
			destination = session.createQueue("This is my First Queue");
			//创建消费者
			messageConsumer = session.createConsumer(destination);
			while(true) {
				TextMessage textMessage = (TextMessage) messageConsumer.receive(1000);
				if(textMessage!=null) {
					System.out.println("收到的消息:" + textMessage.getText());
				}else {
					break;
				}
			}
			
			
		} catch (JMSException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}

}

点对点监听进行消费,消息生产者生产消息,消费者进行监听消费:

1.先创建一个监听类:

package com.tao.activemq;

import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.TextMessage;

/**
 * 消息监听
 * @author
 *
 */
public class Listener implements MessageListener{

	@Override
	public void onMessage(Message message) {
		try {
			System.out.println("收到的消息:"+ ((TextMessage)message).getText());
		} catch (JMSException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

}

通过消费方监听来消费消息:

package com.tao.activemq;

import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.Destination;
import javax.jms.MessageConsumer;
import javax.jms.Session;

import org.apache.activemq.ActiveMQConnection;
import org.apache.activemq.ActiveMQConnectionFactory;

/**
 * 消息队列 消费者监听
 * @author 
 *
 */
public class ConsumerListener {
	
	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(ConsumerListener.USERNAME, ConsumerListener.PASSWORD, ConsumerListener.BROKEURL);
		
		try {
			//通过连接工厂获取连接
			connection = connectionFactory.createConnection();
			//启动连接
			connection.start();
			//session实例化 消费无需加事务
			session = connection.createSession(Boolean.FALSE, Session.AUTO_ACKNOWLEDGE);
			//点对点消费 消费方创建的消息队列名需和生产方一致
			destination = session.createQueue("This is my First Queue");
			//创建消费者实例
			messageConsumer = session.createConsumer(destination);
			//通过消费者监听来消费消息
			messageConsumer.setMessageListener(new Listener());
		}catch (Exception e) {
			// TODO: handle exception
		}
	}
}

点对点先运行生产者生产消息,在运行消费者 进行消息消费。

发布订阅模式:

消息发布者我们保持原有不动:

package com.tao.pub.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 javax.jms.Topic;

import org.apache.activemq.ActiveMQConnection;
import org.apache.activemq.ActiveMQConnectionFactory;

/**
 * 消息发布者
 * @author
 *
 */
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实例化   connection.createSession(arg0, arg1) arg0:是否加入事务 arg1:消息确认方式
			session = connection.createSession(Boolean.TRUE, Session.AUTO_ACKNOWLEDGE);
			//发布订阅模式 发布主题不是队列
			destination = session.createTopic("This is my First Topic");
			//创建消息生产者
			messageProducer = session.createProducer(destination);
			sendMessage(session, messageProducer);
			//提交消息
			session.commit();
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}finally {
				if(connection!=null) {
					try {
						connection.close();
					} catch (JMSException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
			}
		
	}
	
	/**
	 * 发送消息
	 * @param session
	 * @param messageProducer
	 * @throws Exception
	 */
	private static void sendMessage(Session session,MessageProducer messageProducer) throws Exception{
		for(int i=1; i<=JMSProducer.SENDNUM;i++) {
			TextMessage textMessage = session.createTextMessage("ActiveMQ 发送的消息:"+i);
			System.out.println("发送消息:"+ "ActiveMQ 发布的消息:"+i);
			messageProducer.send(textMessage);
			
		}
	}
	
	
	
	

}

建立多个订阅者进行订阅消费:

监听者一:

package com.tao.pub.activemq;

import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.TextMessage;

/**
 * 消息订阅者一 监听
 * @author 
 *
 */
public class Listener implements MessageListener{

	@Override
	public void onMessage(Message message) {
		try {
			System.out.println("订阅者一收到的消息:"+ ((TextMessage)message).getText());
		} catch (JMSException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

}
package com.tao.pub.activemq;

import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.Destination;
import javax.jms.MessageConsumer;
import javax.jms.Session;
import javax.jms.Topic;

import org.apache.activemq.ActiveMQConnection;
import org.apache.activemq.ActiveMQConnectionFactory;

/**
 * 消息订阅者一
 * @author
 *
 */
public class ConsumerListener {
	
	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(ConsumerListener.USERNAME, ConsumerListener.PASSWORD, ConsumerListener.BROKEURL);
		
		try {
			//通过连接工厂获取连接
			connection = connectionFactory.createConnection();
			//启动连接
			connection.start();
			//session实例化 消费无需加事务
			session = connection.createSession(Boolean.FALSE, Session.AUTO_ACKNOWLEDGE);
			//发布订阅模式 主题名一致即可
			destination = session.createTopic("This is my First Topic");
			//创建消费者实例
			messageConsumer = session.createConsumer(destination);
			//通过消费者监听来消费消息
			messageConsumer.setMessageListener(new Listener());
		}catch (Exception e) {
			// TODO: handle exception
		}
	}
}

监听者二:

package com.tao.pub.activemq;

import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.TextMessage;

/**
 * 消息订阅者一 监听
 * @author 
 *
 */
public class Listener2 implements MessageListener{

	@Override
	public void onMessage(Message message) {
		try {
			System.out.println("订阅者二收到的消息:"+ ((TextMessage)message).getText());
		} catch (JMSException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

}
package com.tao.pub.activemq;

import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.Destination;
import javax.jms.MessageConsumer;
import javax.jms.Session;
import javax.jms.Topic;

import org.apache.activemq.ActiveMQConnection;
import org.apache.activemq.ActiveMQConnectionFactory;

/**
 * 消息订阅者二
 * @author zhangtao
 *
 */
public class ConsumerListener2 {
	
	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(ConsumerListener2.USERNAME, ConsumerListener2.PASSWORD, ConsumerListener2.BROKEURL);
		
		try {
			//通过连接工厂获取连接
			connection = connectionFactory.createConnection();
			//启动连接
			connection.start();
			//session实例化 消费无需加事务
			session = connection.createSession(Boolean.FALSE, Session.AUTO_ACKNOWLEDGE);
			//发布订阅模式 主题名一致即可
			destination = session.createTopic("This is my First Topic");
			//创建消费者实例
			messageConsumer = session.createConsumer(destination);
			//通过消费者监听来消费消息
			messageConsumer.setMessageListener(new Listener2());
		}catch (Exception e) {
			// TODO: handle exception
		}
	}
}

注意:发布订阅模式,需要先订阅 才能消费。(像订报纸一样)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值