ActiveMQ 即时通讯服务

简介

ActiveMQ 是Apache出品,最流行的、功能强大的即时通讯和集成模式的开源服务器。ActiveMQ是一个完全支持JMS1.1和J2EE 1.4规范的 JMS Provider实现。提供客户端支持跨语言和协议,带有易于在充分支持JMS1.1和1.4使用J2EE企业集成模式和许多先进的功能。

特性

  1. 多种语言和协议编写客户端。语言: Java、C、C++、C#、Ruby、Perl、Python、PHP。应用协议:OpenWire、Stomp REST、WS Notification、XMPP、AMQP
  2. 完全支持JMS1.1和J2EE 1.4规范 (持久化,XA消息,事务)
  3. 对Spring的支持,ActiveMQ可以很容易内嵌到使用Spring的系统里面去,而且也支持Spring2.0的特性
  4. 支持多种传送协议:in-VM、TCP、SSL、NIO、UDP、JGroups、JXTA
  5. 支持通过JDBC和journal提供高速的消息持久化
  6. 从设计上保证了高性能的集群,客户端-服务器,点对点
  7. 支持Ajax
  8. 支持与Axis的整合
  9. 可以很容易得调用内嵌JMS provider,进行测试

安装

开发环境
System : windows
JDK : 1.8+
IDE:eclipse
apache ActiveMQ 5.8

1.下载
apache-activemq-5.8.0-bin.zip

2.解压apache-activemq-5.8.0.zip即可完成ActiveMQ的安装
3.apache-activemq-5.8.0目录

\bin (windows下面的bat和unix/linux下面的sh) 启动ActiveMQ的启动服务就在这里
\conf (activeMQ配置目录,包含最基本的activeMQ配置文件)
\data (默认是空的)
\docs (index,replease版本里面没有文档)
\example (几个例子)
\lib (activeMQ使用到的lib)
\webapps (系统管理员控制台代码)
\webapps-demo(系统示例代码)
\activemq-all-5.8.0.jar (ActiveMQ的binary)
\user-guide.html (部署指引)
\LICENSE
\NOTICE
\README.txt

4.进入bin目录,使用activemq.bat双击启动(windows用户可以选择系统位数,如果你是linux的话,就用命令行的发送去启动),如果一切顺利,你就会看见类似下面的信息:
ActiveMQ 即时通讯服务_第1张图片
5.启动成功就可以访问管理员界面:http://localhost:8161/admin,默认用户名和密码admin/admin。如果你想修改用户名和密码的话,在\conf\jetty-realm.properties中修改即可。
6.关闭
我们暂时不关闭先, 若想关闭可以直接关闭cmd.exe

ActiviteMQ消息的3种形式

JMS 公共 点对点域 发布/订阅域
ConnectFactory QueueConnectionFactory TopicConnectionFactory
Connection QueueConnection TopicConnection
Destination Queue Topic
Session QueueSession TopicSession
MessageProducer QueueSender TopicPublisher
MessageConsumer QueueReceiver TopicSubscriber

1 点对点方式(point-to-point)

点对点的消息发送方式主要建立在 Message Queue,Sender,reciever上,Message Queue 存贮消息,Sneder 发送消息,receive接收消息.具体点就是Sender Client发送Message Queue ,而 receiver Client从Queue中接收消息和”发送消息已接受”到Quere,确认消息接收。消息发送客户端与接收客户端没有时间上的依赖,发送客户端可以在任何时刻发送信息到Queue,而不需要知道接收客户端是不是在运行

2 发布/订阅 方式(publish/subscriber Messaging)

发布/订阅方式用于多接收客户端的方式.作为发布订阅的方式,可能存在多个接收客户端,并且接收端客户端与发送客户端存在时间上的依赖。一个接收端只能接收他创建以后发送客户端发送的信息。作为subscriber ,在接收消息时有两种方法,destination的receive方法,和实现message listener 接口的onMessage 方法。

接收和发送消息基本流程

发送方:

(1)、创建连接使用的工厂类JMS ConnectionFactory
(2)、使用管理对象JMS ConnectionFactory建立连接Connection,并启动
(3)、使用连接Connection 建立会话Session
(4)、使用会话Session和管理对象Destination创建消息生产者MessageSender
(5)、使用消息生产者MessageSender发送消息

接收方:

(1)、创建连接使用的工厂类JMS ConnectionFactory
(2)、使用管理对象JMS ConnectionFactory建立连接Connection,并启动
(3)、使用连接Connection 建立会话Session
(4)、使用会话Session和管理对象Destination创建消息接收者MessageReceiver
(5)、使用消息接收者MessageReceiver接受消息,需要用setMessageListener将MessageListener接口
        绑定到MessageReceiver消息接收者必须实现了MessageListener接口,需要定义onMessage事件方法。

DEMO

此处利用maven管理项目
pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.lee</groupId>
  <artifactId>testJMS</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>jar</packaging>

  <name>testJMS</name>
  <url>http://maven.apache.org</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>

  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>

    <dependency>
        <groupId>org.apache.activemq</groupId>
        <artifactId>activemq-core</artifactId>
        <version>5.7.0</version>
    </dependency>
  </dependencies>
</project>

P2P模式( JMS, Queue )

//发送者
package com.lee.testJMS;

import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.DeliveryMode;
import javax.jms.Destination;
import javax.jms.MessageProducer;
import javax.jms.Session;
import javax.jms.TextMessage;
import org.apache.activemq.ActiveMQConnection;
import org.apache.activemq.ActiveMQConnectionFactory;

public class Sender {

    //发送次数
    private static final int SEND_NUMBER = 5;
    //tcp地址
    public static final String BROKER_URL = "tcp://localhost:61616";
    //目标, 在ActiveMQ管理员控制台点击Queues
    public static final String DESTINATION = "FirstQueue";

    // 构造消息,此处写死,项目就是参数,或者方法获取
    public static void sendMessage(Session session, MessageProducer producer) throws Exception {
        for (int i = 1; i <= SEND_NUMBER; i++) {
            TextMessage message = session.createTextMessage("ActiveMq 发送的消息" + i);
            System.out.println("发送消息:" + "ActiveMq 发送的消息" + i);
            producer.send(message);
        }
    }

    public static void run() throws Exception {

        Connection connection = null;
        Session session = null;

        try {
            //ConnectionFactory :连接工厂,JMS 用它创建连接
            ConnectionFactory factory = new ActiveMQConnectionFactory(ActiveMQConnectionFactory.DEFAULT_USER,
                    ActiveMQConnection.DEFAULT_PASSWORD, BROKER_URL);
            //Connection :JMS 客户端到JMS Provider 的连接
            connection = factory.createConnection();
            //启动连接
            connection.start();

            //创建一个session, 获取操作连接会话
            session = connection.createSession(Boolean.TRUE, Session.AUTO_ACKNOWLEDGE);
            //Destination :消息的目的地;消息发送给谁.
            Destination destination = session.createQueue(DESTINATION);
            //MessageProducer:消息发送者
            MessageProducer producer = session.createProducer(destination);
            //设置持久化模式
            producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
            sendMessage(session, producer);
            //提交会话
            session.commit();

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            //关闭资源
            if (session != null) {
                session.close();
            }
            if (connection != null) {
                connection.close();
            }
        }
    }

    public static void main(String[] args) throws Exception {
        Sender.run();
    }
}
//接收者
package com.lee.testJMS;

import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.Destination;
import javax.jms.MessageConsumer;
import javax.jms.Session;
import javax.jms.TextMessage;
import org.apache.activemq.ActiveMQConnection;
import org.apache.activemq.ActiveMQConnectionFactory;

public class Receiver {

    //tcp地址
    public static final String BROKER_URL = "tcp://localhost:61616";
    //目标, 在activeMQ管理员控制台点击Queues
    public static final String DESTINATION = "FirstQueue";

    public static void run() throws Exception {

        // Connection :JMS 客户端到JMS Provider 的连接
        Connection connection = null;
        // Session: 一个发送或接收消息的线程
        Session session = null;

        try {
            //ConnectionFactory :连接工厂,JMS 用它创建连接
            ConnectionFactory factory = new ActiveMQConnectionFactory(ActiveMQConnection.DEFAULT_USER,
                    ActiveMQConnection.DEFAULT_PASSWORD, BROKER_URL);
            //通过工厂创建一个连接
            connection = factory.createConnection();
            //启动连接
            connection.start();
            //创建一个session会话
            session = connection.createSession(Boolean.TRUE, Session.AUTO_ACKNOWLEDGE);
            // Destination :消息的目的地;消息发送给谁.
            Destination destination = session.createQueue(DESTINATION);
            //创建消息消费者(接收者)
            MessageConsumer consumer = session.createConsumer(destination);

            while (true) {
                //// 设置接收者接收消息的时间,为了便于测试,这里设定为100s
                Message message = consumer.receive(1000 * 100);
                TextMessage text = (TextMessage) message;
                if (text != null) {
                    System.out.println("接收: " + text.getText());
                } else {
                    break;
                }
            }

            //提交会话
            session.commit();
        } catch (Exception e) {
            throw e;
        } finally {
            //关闭资源
            if (session != null) {
                session.close();
            }
            if (connection != null) {
                connection.close();
            }
        }
    }

    public static void main(String[] args) throws Exception {
        Receiver.run();
    }
}

测试过程:
发送
ActiveMQ 即时通讯服务_第2张图片
http://localhost:8161/admin/
发送后
接收
ActiveMQ 即时通讯服务_第3张图片
http://localhost:8161/admin/queues.jsp
接收后

Pub/Sub模式( Topic )

Pub/Sub模式与P2P模式不同, P2P模式Sender发送后会保存在容器中, 直到Receiver来取走, 消息抛弃; Pub/Sub模式过程如下:

  1. activemq启动后,发布消息1,可惜,现在没有消费者启动着,也就是没有消费者进行了订阅。那么,这个消息就被抛弃了。
  2. 消费者1启动了,连接了activemq,进行了订阅,在等待消息~~activemq发布消息2,OK,消费者1收到,并进行处理。消息抛弃。
  3. 消费者2也启动了,连接了activemq,进行了订阅,在等待消息~~activemq发布消息3,OK,消费者1,消费者2都收到,并进行处理。消息抛弃。
  4. 消费者1关掉了。activemq发布消息4,OK,消费者2收到,并进行处理。消息抛弃。
  5. 消费者1又启动了。activemq发布消息5,OK,消费者1,消费者2都收到,并进行处理。消息抛弃。
//订阅者
package com.lee.testTopic;

import javax.jms.JMSException;
import javax.jms.MapMessage;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.Session;
import javax.jms.Topic;
import javax.jms.TopicConnection;
import javax.jms.TopicConnectionFactory;
import javax.jms.TopicSession;
import javax.jms.TopicSubscriber;
import org.apache.activemq.ActiveMQConnection;
import org.apache.activemq.ActiveMQConnectionFactory;

public class TopicReceiver {

    // tcp 地址
    public static final String BROKER_URL = "tcp://localhost:61616";
    // 目标,在ActiveMQ管理员控制台点击Queues查看
    public static final String TARGET = "topic";

    public static void run() throws Exception {

        TopicConnection connection = null;
        TopicSession session = null;
        try {
            // 创建链接工厂
            TopicConnectionFactory factory = new ActiveMQConnectionFactory(ActiveMQConnection.DEFAULT_USER,
                    ActiveMQConnection.DEFAULT_PASSWORD, BROKER_URL);
            // 通过工厂创建一个连接
            connection = factory.createTopicConnection();
            // 启动连接
            connection.start();

            // 创建一个session会话
            session = connection.createTopicSession(Boolean.TRUE, Session.AUTO_ACKNOWLEDGE);
            // 创建一个消息队列
            Topic topic = session.createTopic(TARGET);
            // 创建订阅者
            TopicSubscriber subscriber = session.createSubscriber(topic);

            //创建监听器监听发布者
            subscriber.setMessageListener(new MessageListener() {
                public void onMessage(Message msg) {
                    if (msg != null) {
                        MapMessage map = (MapMessage) msg;
                        try {
                            System.out.println(map.getLong("time") + "接收#" + map.getString("text"));
                        } catch (JMSException e) {
                            e.printStackTrace();
                        }
                    }
                }
            });
            // 休眠100s再关闭, 不然会直接关闭, 无法接收订阅消息
            Thread.sleep(1000 * 100);

            // 提交会话
            session.commit();

        } catch (Exception e) {
            throw e;
        } finally {
            // 关闭释放资源
            if (session != null) {
                session.close();
            }
            if (connection != null) {
                connection.close();
            }
        }
    }

    public static void main(String[] args) throws Exception {
        TopicReceiver.run();
    }
}
//发布者
package com.lee.testTopic;

import javax.jms.DeliveryMode;
import javax.jms.MapMessage;
import javax.jms.Session;
import javax.jms.Topic;
import javax.jms.TopicConnection;
import javax.jms.TopicConnectionFactory;
import javax.jms.TopicPublisher;
import javax.jms.TopicSession;
import org.apache.activemq.ActiveMQConnection;
import org.apache.activemq.ActiveMQConnectionFactory;

public class TopicSender {

    // 发送次数
    public static final int SEND_NUM = 5;
    // tcp 地址
    public static final String BROKER_URL = "tcp://localhost:61616";
    // 目标,在ActiveMQ管理员控制台点击Queues查看
    public static final String DESTINATION = "topic";

    public static void sendMessage(TopicSession session, TopicPublisher publisher) throws Exception {
        for (int i = 0; i < SEND_NUM; i++) {
            String message = "发送消息第" + (i + 1) + "条";

            MapMessage map = session.createMapMessage();
            map.setString("text", message);
            map.setLong("time", System.currentTimeMillis());
            System.out.println(map);

            publisher.send(map);
        }
    }

    public static void run() throws Exception {

        TopicConnection connection = null;
        TopicSession session = null;
        try {
            // 创建链接工厂, user默认为admin, password默认为admin
            TopicConnectionFactory factory = new ActiveMQConnectionFactory(ActiveMQConnection.DEFAULT_USER,
                    ActiveMQConnection.DEFAULT_PASSWORD, BROKER_URL);
            // 通过工厂创建一个连接
            connection = factory.createTopicConnection();
            // 启动连接
            connection.start();

            // 创建一个session会话
            session = connection.createTopicSession(Boolean.TRUE, Session.AUTO_ACKNOWLEDGE);
            // 创建一个消息队列
            Topic topic = session.createTopic(DESTINATION);
            // 创建消息发布者
            TopicPublisher publisher = session.createPublisher(topic);
            // 设置持久化模式
            publisher.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
            sendMessage(session, publisher);
            // 提交会话
            session.commit();

        } catch (Exception e) {
            throw e;
        } finally {
            // 关闭释放资源
            if (session != null) {
                session.close();
            }
            if (connection != null) {
                connection.close();
            }
        }
    }

    public static void main(String[] args) throws Exception {
        TopicSender.run();
    }
}

启动订阅者
ActiveMQ 即时通讯服务_第4张图片
localhost:8161/admin 点击Topics
ActiveMQ 即时通讯服务_第5张图片
启动发布者
ActiveMQ 即时通讯服务_第6张图片

你可能感兴趣的:(java,activemq,即时通讯)