JMS的一种实现-----ActiveMQ

1.什么是JMS?

JMS是Java消息服务(Java Message Service),是Java平台中关于面向消息中间件(MOM)的API。用于在两个程序之间、或者分布式系统中发送消息进行异步通信。Java消息服务是一个与具体平台无关的API,绝大多数MOM提供商都对JMS提供支持。

JMS只是一个接口,不同的提供商或者开源组织对其有不同的实现。ActiveMQ就是其中之一,它支持JMS,是Apache推出的。JMS中有几个对象模型:

连接工厂:ConnectionFactory 

JMS连接:Connection 

JMS会话:Session 

JMS目的:Destination 

JMS生产者:Producer 

JMS消费者:Consumer 

JMS消息两种类型:点对点发布/订阅

        从上面可以看出JMS和JDBC有点类似,JDBC是用来访问不同关系数据库的API,而JMS则是提供同样与厂商无关的访问方法,以访问消息收发服务。这篇博文主要讲讲ActiveMQ的使用。


2.ActiveMQ

关于ActiveMQ 是一个完全支持JMS1.1和J2EE 1.4规范的 JMS Provider实现,尽管JMS规范出台已经是很久的事情了,

但是JMS在当今的J2EE应用中间仍然扮演着特殊的地位。 使用ActiveMQ首先需要去官网下载,我用的是apache-activemq-5.13.2,

(目前官网最新的apache-activemq-5.15.2我本地启动失败)下载后解压缩,会看到里面有个apache-activemq-5.13.2.jar,这个jar是接下来我们写程序的时候需要加进工程里的。

 在使用ActiveMQ之前,首先得先启动,刚才解压后的目录中有个bin目录,里面有win32和win64两个目录,根据自己电脑选择其中一个打开运行

activemq.bat启动ActiveMQ。 启动完成后,在浏览器中输入http://127.0.0.1:8161/admin/来访问ActiveMQ的服务器,

用户名和密码是admin/admin。如下:


这里主要关注Queues和Topics这两个选项,因为这就是上面提到的点对点和发布/订阅的查看窗口。有了以上的准备工作下来就写两个

Demo测一下。

3.先写一个点对点消息的Demo

首先写消息的生产者,也就是发送消息。

package com.xuhao.demo;

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 xuhao
 *
 */

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 con = null;  // 连接
		Session session;  // 会话,接收或者发送消息的线程
		Destination destination;  //消息的目的地
		MessageProducer messageProducer;  // 消息的发送者(生产者)
		
		// 实例化连接工厂
		connectionFactory = new ActiveMQConnectionFactory(USERNAME, PASSWORD, BROKEURL);
		try {
			con = connectionFactory.createConnection();  // 通过工厂获取连接
			con.start();  // 连接启动
			session = con.createSession(Boolean.TRUE, Session.AUTO_ACKNOWLEDGE);  // 获取session
			destination = session.createQueue("FirstQueue1");  // 创建消息队列  
			messageProducer = session.createProducer(destination);  // 创建消息生产者
			sendMessage(session, messageProducer);  // 发送消息
			session.commit();  // 因为上面加了事务Boolean.TRUE表示有事务,所以要commit
			
		} catch (JMSException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
			if(con != null){
				try {
					con.close();
				} catch (JMSException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
		
		
		
	}
	
	
	/**
	 * 发送消息
	 * @param session
	 * @param messageProducer
	 * @throws JMSException 
	 */
	public static void sendMessage(Session session, MessageProducer messageProducer) throws JMSException{
		for (int i = 0; i < JMSProducer.SENDNUM; i++) {
			// 创建消息
			TextMessage message = session.createTextMessage("ActiveMQ发送的消息" + i);
			System.out.println("ActiveMQ发送的消息" + i);
			// 发送消息
			messageProducer.send(message);
			
		}
	}
	
	
	
}
可以看出,主要的流程就是上面提到的JMS的一些对象模型,这个和JDBC很类似,接下来再写消息的消费者,也就是接收方。

package com.xuhao.demo;

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 org.apache.activemq.ActiveMQConnection;
import org.apache.activemq.ActiveMQConnectionFactory;

/**
 * 消息的消费者,也即是接收消息
 * @author xuhao
 *
 */
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 connection = null; // 连接
        Session session; // 会话,接收或者发送消息的线程
        Destination destination; // 消息的目的地
        MessageConsumer messageConsumer; // 消息消费者
        // 实例化连接工厂
        connectionFactory = new ActiveMQConnectionFactory(USERNAME, PASSWORD, BROKEURL);
        try {
			connection = connectionFactory.createConnection();  // 通过连接工厂获取连接
			connection.start();  // 启动连接
	        session = connection.createSession(Boolean.FALSE, Session.AUTO_ACKNOWLEDGE); // 获取Session,不需要加事务了
	        destination = session.createQueue("FirstQueue1"); // 创建消息队列,名为FirstQueue1
	        messageConsumer = session.createConsumer(destination); // 创建消息消费者
	        // 注册消息监听
	        messageConsumer.setMessageListener(new Listener());
			
		} catch (JMSException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} 
        
		
	}
    
    
}
接收消息需要一个监听器,这个监听器可以自己来实现,需要实现MessageListener接口,如下:

package com.xuhao.demo;

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


/**
 * 用于接收消息的监听器
 * @author xuhao
 *
 */
public class Listener implements MessageListener{

	@Override
	public void onMessage(Message message) {
		// TODO Auto-generated method stub
		try {
			System.out.println("收到的消息:" + ((TextMessage)message).getText());
		} catch (JMSException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	
	
}
运行这两个程序,首先运行JMSProducer,然后运行JMSConsumer就可以看到控制台的消息输出。然后打开ActiveMQ的

服务器,可以看到如下信息: 


可以看出,总共产生了30条消息,消费了30条消息,这就是点对点的模式。

4.订阅/发布消息

下面写一个订阅/发布消息的demo。和上面点对点类似,不过代码有一些细节上的差异,另外订阅方用两个Consumer来模拟一下,

发布方用一个Producer来模拟。 

发布消息:

package com.xuhao.demo.topics;

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 xuhao
 *
 */

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 connection = null; // 连接
        Session session; // 会话,接收或者发送消息的线程
        Destination destination; // 消息的目的地
        MessageProducer messageProducer; // 消息发送者

        // 实例化连接工厂
        connectionFactory = new ActiveMQConnectionFactory(USERNAME, PASSWORD, BROKEURL);
        try {
            connection = connectionFactory.createConnection(); // 通过连接工厂获取连接
            connection.start();  // 启动连接
            session = connection.createSession(Boolean.TRUE, Session.AUTO_ACKNOWLEDGE); // 获取Session
            destination = session.createTopic("FirstTopic1"); // 创建消息队列,名为FirstTopic1
            messageProducer = session.createProducer(destination); // 创建消息生产者
            sendMessage(session, messageProducer); // 发送消息
            session.commit(); // 因为上面加了事务Boolean.TRUE表示有事务,所以要commit
        } catch (JMSException 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();
                }
            }           
        }
    }

    /**
     * @Description 发布消息
     * @param session
     * @param messageProducer
     * @throws JMSException 
     */
    public static void sendMessage(Session session, MessageProducer messageProducer) throws JMSException {
        for(int i = 0; i < JMSProducer.SENDNUM; i++) {
            TextMessage message = session.createTextMessage("ActiveMQ 发布的消息" + i);
            System.out.println("ActiveMQ 发布的消息" + i);
            messageProducer.send(message);
        }
    }
	
	
}
和点对点有个细微的区别,这里是用session.createTopic,注意一下即可。 
订阅消息:

package com.xuhao.demo.topics;

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 org.apache.activemq.ActiveMQConnection;
import org.apache.activemq.ActiveMQConnectionFactory;

/**
 * 消息的消费者,也即是接收消息
 * @author xuhao
 *
 */
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 connection = null; // 连接
	        Session session; // 会话,接收或者发送消息的线程
	        Destination destination; // 消息的目的地
	        MessageConsumer messageConsumer; // 消息消费者
	        // 实例化连接工厂
	        connectionFactory = new ActiveMQConnectionFactory(USERNAME, PASSWORD, BROKEURL);
	        try {
	            connection = connectionFactory.createConnection(); // 通过连接工厂获取连接
	            connection.start();  // 启动连接
	            session = connection.createSession(Boolean.FALSE, Session.AUTO_ACKNOWLEDGE); // 获取Session,不需要加事务了
	            destination = session.createTopic("FirstTopic1"); // 创建消息队列,名为FirstTopic1
	            messageConsumer = session.createConsumer(destination); // 创建消息消费者
	            //注册消息监听
	            messageConsumer.setMessageListener(new Listener());
	        } catch (JMSException e) {
	            // TODO Auto-generated catch block
	            e.printStackTrace();
	        } 
	    }
	
}
同样地,这里也是使用createTopic,另一个订阅方的代码和这个一样,就不写了,然后运行所有的JMSConsumer,

再运行JMSProducer,就会看到控制台会打印出消息。再看一下服务器上的状态: 



我们可以看到,有两个订阅者,发布了10条消息,消费了20条。以上就是ActiveMQ使用的简单demo。





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值