一、安装与启动
1.下载安装activemq,下载地址:http://activemq.apache.org/download.html。
2.安装完成后,进入其所在目录的bin目录下面,根据系统位数选择进入win32或者win64目录。
3.双击activemq.bat 文件进行启动,需要安装Java8,配置JAVA_HOME环境变量(注意:计算机名称不能有下划线)。
4.启动完后在浏览器访问 http://127.0.0.1:6181,点击如下选项,然后在弹出的界面输入用户名 admin 密码 admin进入管理页面。
二、三种通信方式
1、操作的主要步骤
(1). 获得JMS connection factory. 通过我们提供特定环境的连接信息来构造factory。
(2). 利用factory构造JMS connection
(3). 启动connection
(4). 通过connection创建JMS session.
(5). 指定JMS destination.
(6). 创建JMS producer或者创建JMS message并提供destination.
(7). 创建JMS consumer或注册JMS message listener.
(8). 发送和接收JMS message.
(9). 关闭所有JMS资源,包括connection, session, producer, consumer等。
2、activemq的连接
创建一个maven项目,加入如下依赖。
<dependencies>
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-client</artifactId>
<version>5.15.4</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>1.7.25</version>
</dependency>
</dependencies>
mq连接代码
import org.apache.activemq.ActiveMQConnectionFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.JMSException;
import javax.jms.Session;
public class MqUtils {
static Logger logger = LoggerFactory.getLogger(MqUtils.class);
private static final String URL="tcp://118.24.115.208:61616"; //连接地址
private static final String USER_NAME="admin"; //用户名
private static final String PASSWORD="admin"; //密码
private static Connection connection =null;
private static Session session=null;
private MqUtils(){}
/**
* 获取session 一个发送或者接受消息的线程
* @return
* @throws JMSException
*/
public static Session getSession() throws JMSException {
//获取连接工厂
ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(USER_NAME,PASSWORD,URL);
if(null == connection){
//获取连接
connection = connectionFactory.createConnection();
connection.start();
logger.info("连接创建成功");
}
if(null == session){
//获取session对象
session = connection.createSession(Boolean.TRUE,Session.AUTO_ACKNOWLEDGE);
logger.info("session创建成功");
}
return session;
}
/**
* 关闭session和连接
* @throws JMSException
*/
public static void closeSession() {
if(null != session){
try {
session.close();
logger.info("session关闭");
} catch (JMSException e) {
e.printStackTrace();
}
}
if(null != connection){
try {
connection.close();
logger.info("连接关闭");
} catch (JMSException e) {
e.printStackTrace();
}
}
}
}
3.第一种通信方式 P2P
p2p的过程则理解起来更加简单。它好比是两个人打电话,这两个人是独享这一条通信链路的。一方发送消息,另外一方接收,就这么简单。在实际应用中因为有多个用户对使用p2p的链路,它的通信场景如下图所示:
在p2p的场景里,相互通信的双方是通过一个类似于队列的方式来进行交流。
代码实现:
Provider代码:
import com.jack.util.MqUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.jms.*;
public class QueryProvider {
static Logger logger = LoggerFactory.getLogger(QueryProvider.class);
public static void main(String[] args) {
try {
//获取session 一个发送消息的线程
Session session = MqUtils.getSession();
//设置消息发送的目的地
Queue destination = session.createQueue("Queue B");
//获取消息发送者
MessageProducer producer = session.createProducer(destination);
//设置不持久化
producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
//发送消息
logger.info("开始发送消息");
sendMessage(session,producer);
//提交,只有提交了消息才会正真发送
session.commit();
logger.info("消息发送完毕");
} catch (JMSException e) {
e.printStackTrace();
}finally {
//关闭连接
MqUtils.closeSession();
}
}
/**
* 发送文本消息
* @param session session对象
* @param producer 消息发送者
* @throws JMSException
*/
public static void sendMessage(Session session,MessageProducer producer) throws JMSException {
//构造文本消息
TextMessage textMessage = session.createTextMessage("{\"name\":\"zhangsan\",\"age\":35,\"sex\":\"male\",\"marry\":false}");
logger.info("发送消息");
//发送消息
producer.send(textMessage);
}
}
consumer代码实现:
import com.jack.util.MqUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.jms.*;
public class QueueConsumer {
static Logger logger = LoggerFactory.getLogger(QueueConsumer.class);
public static void main(String[] args) {
try {
Session session = MqUtils.getSession();
Queue destination = session.createQueue("Queue B");
MessageConsumer consumer = session.createConsumer(destination);
consumer.setMessageListener(new MessageListener() {
@Override
public void onMessage(Message message) {
TextMessage textMessage = (TextMessage) message;
try {
logger.info(textMessage.getText());
} catch (JMSException e) {
e.printStackTrace();
}
try {
session.commit();
} catch (JMSException e) {
e.printStackTrace();
}
}
});
} catch (JMSException e) {
e.printStackTrace();
}
}
}
4、第二种通信方式 publish-subscribe
发布订阅模式有点类似于我们日常生活中订阅报纸。每年到年尾的时候,邮局就会发一本报纸集合让我们来选择订阅哪一个。在这个表里头列了所有出版发行的报纸,那么对于我们每一个订阅者来说,我们可以选择一份或者多份报纸。比如北京日报、潇湘晨报等。那么这些个我们订阅的报纸,就相当于发布订阅模式里的topic。有很多个人订阅报纸,也有人可能和我订阅了相同的报纸。那么,在这里,相当于我们在同一个topic里注册了。对于一份报纸发行方来说,它和所有的订阅者就构成了一个1对多的关系。这种关系如下图所示:
代码实现如下:
Provider代码:
import com.jack.util.MqUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.jms.*;
public class TopicProvider {
static Logger logger = LoggerFactory.getLogger(TopicProvider.class);
/**
* 测试消息发布
* @param args
*/
public static void main(String[] args) {
try {
//获取session
Session session = MqUtils.getSession();
//制定发布地址
Topic topic = session.createTopic("Topic A");
//消息发布者
MessageProducer producer = session.createProducer(topic);
//设置不持久化
producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
logger.info("开始发送消息");
//发送消息
sendMessage(session,producer);
//提交
session.commit();
logger.info("消息发送结束");
} catch (JMSException e) {
e.printStackTrace();
}finally {
//关闭session和连接
MqUtils.closeSession();
}
}
/**
* 发送消息
* @param session 一个发送消息的线程
* @param messageProducer 消息发送者
* @throws JMSException
*/
public static void sendMessage(Session session,MessageProducer messageProducer) throws JMSException {
//构造文本消息
TextMessage message = session.createTextMessage("{\"name\":\"zhangsan\"}");
//发送消息
messageProducer.send(message);
}
}
Consumer代码:
import com.jack.util.MqUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.jms.*;
public class TopicConsumer {
static Logger logger = LoggerFactory.getLogger(TopicConsumer.class);
public static void main(String[] args) {
try {
//获取session
Session session = MqUtils.getSession();
//设置订阅地址
Topic destination = session.createTopic("Topic A");
//订阅消息
MessageConsumer consumer = session.createConsumer(destination);
//消息监听(有事务限制)
consumer.setMessageListener(new MessageListener() {
@Override
public void onMessage(Message message) {
//接收消息
TextMessage textMessage = (TextMessage) message;
try {
logger.info(textMessage.getText());
//提交
session.commit();
} catch (JMSException e) {
e.printStackTrace();
}
}
});
} catch (JMSException e) {
e.printStackTrace();
}
}
}
5.第三种通信方式 request-response
和前面两种方式比较起来,request-response的通信方式很常见,但是不是默认提供的一种模式。在前面的两种模式中都是一方负责发送消息而另外一方负责处理。而我们实际中的很多应用相当于一种一应一答的过程,需要双方都能给对方发送消息。于是请求-应答的这种通信方式也很重要。它也应用的很普遍。
请求-应答方式并不是JMS规范系统默认提供的一种通信方式,而是通过在现有通信方式的基础上稍微运用一点技巧实现的。下图是典型的请求-应答方式的交互过程:
在JMS里面,如果要实现请求/应答的方式,可以利用JMSReplyTo和JMSCorrelationID消息头来将通信的双方关联起来。另外,QueueRequestor和TopicRequestor能够支持简单的请求/应答过程。
代码实现如下:
Provider代码:
import com.jack.util.MqUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.jms.*;
public class DoubleConsumer {
static Logger logger = LoggerFactory.getLogger(DoubleConsumer.class);
public static void main(String[] args) {
try {
//获取session
Session session = MqUtils.getSession();
//设置消息地址
Destination destination = session.createQueue("DoubleA");
//创建消息发送者
MessageProducer messageProducer = session.createProducer(null);
//设置不持久化
messageProducer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
//创建消息接受者
MessageConsumer messageConsumer = session.createConsumer(destination);
//监听消息
messageConsumer.setMessageListener(new MessageListener() {
@Override
public void onMessage(Message message) {
//接收消息
TextMessage textMessage = (TextMessage) message;
try {
//接收后构造回复消息
TextMessage txtMessage = session.createTextMessage();
String messageText = textMessage.getText();
logger.info(messageText);
txtMessage.setText(messageText);
//设置消息的id,保证每个消息的回复相对应
txtMessage.setJMSCorrelationID(message.getJMSCorrelationID());
//回复消息
messageProducer.send(message.getJMSReplyTo(),txtMessage);
session.commit();
} catch (JMSException e) {
e.printStackTrace();
}
}
});
} catch (JMSException e) {
e.printStackTrace();
}
}
}
Consumer代码:
import com.jack.util.MqUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.jms.*;
import java.util.UUID;
public class DoubleProvider {
static Logger logger = LoggerFactory.getLogger(DoubleProvider.class);
public static void main(String[] args) {
try {
//获取连接
Session session = MqUtils.getSession();
//设置地址
Destination destination1 = session.createQueue("DoubleA");
//创建消息发送者
MessageProducer messageProducer = session.createProducer(destination1);
//设置消息不持久化
messageProducer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
//创建接收消息的地址
Destination destination = session.createTemporaryQueue();
//创建消息接受者
MessageConsumer messageConsumer = session.createConsumer(destination);
//监听消息借口
messageConsumer.setMessageListener(new MessageListener() {
@Override
public void onMessage(Message message) {
//接收消息
TextMessage textMessage = (TextMessage) message;
try {
logger.info(textMessage.getText());
} catch (JMSException e) {
e.printStackTrace();
}
}
});
//创建消息体
TextMessage textMessage = session.createTextMessage();
textMessage.setText("HYYYY");
//设置消息发送目的地
textMessage.setJMSReplyTo(destination);
String correlationId = UUID.randomUUID().toString();
//设置消息的id
textMessage.setJMSCorrelationID(correlationId);
//发送消息
messageProducer.send(textMessage);
session.commit();
} catch (JMSException e) {
e.printStackTrace();
}
}
}