1、基本原理

A向消息服务器发送信息,B从消息服务器读取信息,发送和读取不必同步,提高了信息传输处理的灵活性。

消息发送和接收有两种方式,一是点对点方式,即A发送,仅B能接收,接收后队列中消息被删除, 二是主题方式,即A发送,BCD都可以接收,接收后队列中消息仍然存在

2、运行消息服务器

消息服务器有很多种,比如ActiveMQ, RabbitMQ等等。以ActiveMQ消息服务器为例,运行 \bin\win64\activemq.bat即可

3、点对点方式:发送消息

package com.gong.sir.jms;

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.ActiveMQConnectionFactory;

/*
 * 在运行此代码前,需要先运行activeMQ消息服务器
 * 如 路径\bin\win64\activemq.bat
 * 在http://127.0.0.1:8161   admin/admin 查看消息队列的内容
 * 这段代码是向消息服务器 循环发送 100条消息
 * 这段代码的原理是先连接到消息服务器,然后在消息服务器中创建一个队列(如果有则不创造),最后向这个消息队列发送数据
 */

public class QueueSender{
    //消息服务器的地址和队列名称
    public static final String url = "tcp://127.0.0.1:61616";
    public static final String queueName = "queue-test";

    public static void main(String[] args) throws JMSException {
        //1.创建连接工厂
        ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(url);

        //2.创建Connection
        Connection connection = connectionFactory.createConnection();

        //3.启动连接
        connection.start();

        //4.创建会话 第一个参数:是否在事务中去处理, 第二个参数.应答模式
        Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);

        //5.创建一个目标
        Destination destination = session.createQueue(queueName);

        //6创建一个生产者
        MessageProducer producer = session.createProducer(destination);
        for (int i = 0; i < 100; i++) {
            //7.创基建消息
            TextMessage textMessage = session.createTextMessage("test:"+i);
            //8.发送消息
            producer.send(textMessage);
            System.out.println("发送消息:"+textMessage.getText());
        }
        //9关闭连接
        connection.close();
    }
}

4、点对点方式:接收消息

package com.gong.sir.jms;

import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageConsumer;
import javax.jms.MessageListener;
import javax.jms.Session;
import javax.jms.TextMessage;

import org.apache.activemq.ActiveMQConnectionFactory;

/*
 * 在运行此代码前,需要先运行activeMQ消息服务器
 * 如 路径\bin\win64\activemq.bat
 * 
 * 这段代码是监听消息服务器并从中接收消息
 * 这段代码的原理是先连接到消息服务器,然后在消息服务器中创建一个队列(如果有则不创造),最后从这个消息队列接收数据
 */

public class QueueReceiver {
    //消息服务器的地址和队列名称
    public static final String url = "tcp://127.0.0.1:61616";
    public static final String queueName = "queue-test";

    public static void main(String[] args) throws JMSException {
        //1.创建连接工厂
        ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(url);

        //2.创建Connection
        Connection connection = connectionFactory.createConnection();

        //3.启动连接
        connection.start();

        //4.创建会话 第一个参数:是否在事务中去处理, 第二个参数.应答模式
        Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);

        //5.创建一个目标
        Destination destination = session.createQueue(queueName);

        //6创建一个消费者
        MessageConsumer consumber = session.createConsumer(destination);

        //7创建一个监听器
        consumber.setMessageListener(new MessageListener() {

            public void onMessage(Message message) {
                TextMessage textMessage = (TextMessage) message;
                try {
                    System.out.println("接收消息:"+textMessage.getText());
                } catch (JMSException e) {
                    e.printStackTrace();
                }

            }
        });

        //8关闭连接  消息是异步的 ,在程序退出时关闭,在这里不可以关闭,就是持续不断等待消息到来并接收下拉
        //connection.close();
    }
}

5、主题方式:发送消息

package com.gong.sir.jms;

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.ActiveMQConnectionFactory;

public class TopicSender {
    //消息服务器的地址和队列名称
    public static final String url = "tcp://localhost:61616";
    public static final String topicName = "topic-test ";

    public static void main(String[] args) throws JMSException {
        //1.创建连接工厂
        ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(url);

        //2.创建Connection
        Connection connection = connectionFactory.createConnection();

        //3.启动连接
        connection.start();

        //4.创建会话 第一个参数:是否在事务中去处理, 第二个参数.应答模式
        Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);

        //5.创建一个目标
        Destination destination = session.createTopic(topicName);

        //6创建一个生产者
        MessageProducer producer = session.createProducer(destination);
        for (int i = 0; i < 100; i++) {
            //7.创基建消息
            TextMessage textMessage = session.createTextMessage("test:"+i);
            //8.发送消息
            producer.send(textMessage);
            System.out.println("发送消息:"+textMessage.getText());
        }
        //9关闭连接
        connection.close();
    }
}

6、主题方式:接收消息

package com.gong.sir.jms;

import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageConsumer;
import javax.jms.MessageListener;
import javax.jms.Session;
import javax.jms.TextMessage;

import org.apache.activemq.ActiveMQConnectionFactory;

public class TopicReceiver {
    //消息服务器的地址和队列名称
    public static final String url = "tcp://localhost:61616";
    public static final String topicName = "topic-test ";

    public static void main(String[] args) throws JMSException {
        //1.创建连接工厂
        ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(url);

        //2.创建Connection
        Connection connection = connectionFactory.createConnection();

        //3.启动连接
        connection.start();

        //4.创建会话 第一个参数:是否在事务中去处理, 第二个参数.应答模式
        Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);

        //5.创建一个目标
        Destination destination = session.createTopic(topicName);

        //6.创建一个消费者
        MessageConsumer consumber = session.createConsumer(destination);

        //7.创建一个监听器
        consumber.setMessageListener(new MessageListener() {

            public void onMessage(Message message) {
                TextMessage textMessage = (TextMessage) message;
                try {
                    System.out.println("接收消息:"+textMessage.getText());
                } catch (JMSException e) {
                    e.printStackTrace();
                }

            }
        });

        //8.关闭连接  消息是异步的 ,在程序退出时关闭,这里不关闭,就是持续不断地接收消息
        //connection.close();
    }
}

 7.点对点方式:选择接收

当选择接收时,B只选择接收自己的消息,同样C也只接收自己的消息,这就实现了点对多点的消息通信。

重点在于创建消费者时,加一个选择器参数,如:requestConsumer = session.createConsumer(responseDestination, selector);

package com.sec;

import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageConsumer;
import javax.jms.MessageListener;
import javax.jms.MessageProducer;
import javax.jms.Session;
import javax.jms.TextMessage;

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

public class JmsClient
{
    private String url;
    private String regRequestQueue;
    private String regResponseQueue;
    private String requestQueue;
    private String responseQueue;
    private String id;
    private String selector;

    private Connection connection;    
    private Session session;
    private Destination regRequestDestination;
    private Destination regResponseDestination;
    private Destination requestDestination;
    private Destination responseDestination;
    private MessageProducer regProducer;
    private MessageConsumer regConsumer;
    private MessageProducer requestProducer;
    private MessageConsumer requestConsumer;
    private TextMessage textMessage;
    
    public void init() throws JMSException {
        //-----------------创建会话-----------------------------------------------------
        //1.创建连接工厂
        ConnectionFactory connectionFactory = new ActiveMQConnectionFactory("user", "user", url);

        //2.创建Connection
        connection = connectionFactory.createConnection();

        //3.启动连接
        connection.start();

        //4.创建会话 第一个参数:是否在事务中去处理, 第二个参数.应答模式
        session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
        
        
        
        //----------------初始化注册变量--------------------------------------------------
        //1.创建一个目标 注册请求队列
        regRequestDestination = session.createQueue(regRequestQueue);

        //2.创建一个生产者
        regProducer = session.createProducer(regRequestDestination);        
        
        //3.创建一个目标 注册响应队列
        regResponseDestination = session.createQueue(regResponseQueue);

        //4.创建一个注册响应队列消费者 
        regConsumer = session.createConsumer(regResponseDestination);
        
        //5.监听注册响应队列
        setRegResponseQueueListener();
        
        
        //----------------初始化业务请求变量-----------------------------------------------
        //1.创建一个目标 业务请求队列
        requestDestination = session.createQueue(requestQueue);

        //2.创建一个业务请求队列生产者
        requestProducer = session.createProducer(requestDestination);
        
        //3.创建一个目标业务响应队列
        responseDestination = session.createQueue(responseQueue);        
        
    }
    
    // 注册请求过程
    public void sendRegRequest() throws JMSException {        
        
        //1.格式转换        
        textMessage = session.createTextMessage("regRequestQueue");
        
        //2.发送消息
        regProducer.send(textMessage);
        System.out.println("发送消息:regRequestQueue");
                         
    }

    // 业务请求过程
    public void sendRequest(String msg) throws JMSException {        
        
        //1.格式转换
        textMessage = session.createTextMessage(msg);
        textMessage.setStringProperty("ID", id);
        
        //2.发送消息
        requestProducer.send(textMessage);
        System.out.println("发送消息:" + id + "," + msg);        
    }
    
    // 关闭jms连接过程
    public void sendCloseRequest() throws JMSException {
        
        sendRequest("close");    
    }
    
    public void setRegResponseQueueListener() throws JMSException {        

        //1.创建一个监听器 监听注册响应队列的内容
        regConsumer.setMessageListener(new MessageListener() {

            public void onMessage(Message message) {
                textMessage = (TextMessage) message;
                try {
                    //2.获得业务响应队列的id
                    id = textMessage.getText(); 
                    
                    //3.创建一个业务响应队列消费者
                    selector = "ID='" + id + "'";
                    requestConsumer = session.createConsumer(responseDestination, selector);
                    
                    //4.监听业务响应队列
                    setResponseQueueListner();
                                        
                    //5.打印提示
                    System.out.println("成功读取注册响应队列的内容");
                    
                    //6.关闭注册响应队列
                    regConsumer.close();
                } catch (JMSException e) {
                    e.printStackTrace();
                }

            }
        });
    }
    
    public void setResponseQueueListner() throws JMSException {

        //3.创建一个业务响应队列监听器
        requestConsumer.setMessageListener(new MessageListener() {
            
            //4.不要在监听器中关闭自己,可能会不正常
            public void onMessage(Message message) {
                TextMessage textMessage = (TextMessage) message;
                try {
                    String msg = textMessage.getText();
                    System.out.println("i am " + id +", i receive =" + msg); 
                } catch (JMSException e) {
                    e.printStackTrace();
                }

            }
        });       
    }
    
    public void close() throws JMSException {
        
        System.out.println("begin close");
//        session.commit();    //如果createSession的第一个参数为true,则transacted,可以用commit,否则不能用commit    
        session.close();    //先关闭会话
        connection.close(); //最后关闭连接
        System.out.println("end close");
    }
    
    public void deleteQueue() throws JMSException {
        //关闭队列
        if(responseDestination != null) {
            ((ActiveMQConnection)connection).destroyDestination((ActiveMQDestination) responseDestination);
        }
    }
    
    public String getUrl()
    {
        return url;
    }

    public void setUrl(String url)
    {
        this.url = url;
    }
    public String getRegRequestQueue()
    {
        return regRequestQueue;
    }

    public void setRegRequestQueue(String regRequestQueue)
    {
        this.regRequestQueue = regRequestQueue;
    }

    public String getRegResponseQueue()
    {
        return regResponseQueue;
    }

    public void setRegResponseQueue(String regResponseQueue)
    {
        this.regResponseQueue = regResponseQueue;
    }

    public String getRequestQueue()
    {
        return requestQueue;
    }

    public void setRequestQueue(String requestQueue)
    {
        this.requestQueue = requestQueue;
    }
    
    public String getResponseQueue()
    {
        return responseQueue;
    }

    public void setResponseQueue(String responseQueue)
    {
        this.responseQueue = responseQueue;
    }
}