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;
}
}