一、什么是ActiveMQ?
ActiveMQ是Apache出品的,非常流行的开源消息中间件,ActiveMQ是一个完全支持JMS1.1和J2EE1.4规范的JMS Provider实现,(JMS是一个Java平台中关于面向消息中间件的API,用于两个应用程序之间,或分布式系统中发送消息,进行异步通信,仅仅定义了一系列的接口,ActiveMQ是对于JMS接口的一种实现)。
二、ActiveMQ的消息形式
对于消息的传递有两种类型:
1)点到点:一个生产者和一个消费者一一对应;(使用时生产者提供的消息会进行缓存,直到消费者使用)
2)发布/订阅:一个生产者产生消息发送后,可以由多个消费者订阅接收;(使用时消息不进行缓存,所以消费者需要提前做好接收准备,否则消息会丢失)
JMS定义了5种不同的消息正文格式:
- StreamMessage--Java原始值的数据流
- MapMessage--一套名称-值对
- TextMessage--一个字符串对象(最常用的消息格式)
- ObjectMessage--一个序列化的Java对象
- BytesMessage--一个字节的数据流
三、ActiveMQ的安装
需要到官方网站下载安装包。
使用时需要提前安装好Java环境即JDK,然后解压到执行目录即可使用。
进入解压后文件的bin目录下,使用命令:./activemq start启动服务。
服务启动后,activemq会自己提供一个管理后台,通过浏览器访问:http://ip:8161/admin,用户名:admin,
密码:admin。
四、ActiveMQ的使用
1)首先引入activeMQ的maven依赖
<!-- activeMQ -->
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-all</artifactId>
<version>5.11.2</version>
</dependency>
2)queue队列形式
创建生产者Producer,创建消息,发送消息:
public void testQueueProducer() throws Exception {
// 创建一个连接工厂对象,brokerURL代表activeMQ服务所在的URL地址,默认连接端口号61616
ConnectionFactory connectionFactory = new ActiveMQConnectionFactory("tcp://192.168.1.8:61616");
// 创建一个连接对象
Connection connection = connectionFactory.createConnection();
// 开启连接
connection.start();
// 创建一个Session会话对象
// 第一个参数是是否开启事物,一般不开启事物,保证数据的最终一致性,可以使用消息队列实现
// 为fase的话第二个参数是消息的应答模式;为true的话第二个参数自动忽略
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
// 使用Session对象创建一个Destination对象,两种形式queue、topic
// 参数是消息队列的名称
Queue queue = session.createQueue("test-queue");
// 使用Session对象创建一个Producer对象
MessageProducer producer = session.createProducer(queue);
// 创建一个TextMessage对象
/*
* TextMessage textMessage = new ActiveMQTextMessage();
* textMessage.setText("hello activemq");
*/
TextMessage textMessage = session.createTextMessage("hello activemq");
// 发送消息
producer.send(textMessage);
// 关闭资源
producer.close();
session.close();
connection.close();
}
创建消费者,向消费者添加消息监听器,接收消息:
public void testQueueConsumer() throws Exception {
// 创建一个连接工厂对象,brokerURL代表activeMQ服务所在的URL地址
ConnectionFactory connectionFactory = new ActiveMQConnectionFactory("tcp://192.168.1.8:61616");
// 创建一个连接对象
Connection connection = connectionFactory.createConnection();
// 开启连接
connection.start();
// 创建一个Session回话对象
// 第一个参数是是否开启事物,一般不开启事物,保证数据的最终一致性,可以使用消息队列实现
// 为fase的话第二个参数是消息的应答模式;为true的话第二个参数自动忽略
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
// 使用Session对象创建一个Destination对象,两种形式queue、topic
// 参数是消息队列的名称
Queue queue = session.createQueue("test-queue");
// 使用Session对象创建一个Consumer对象
MessageConsumer consumer = session.createConsumer(queue);
// 向Consumer对象中设置一个MessageListener对象,用来接收消息
consumer.setMessageListener(new MessageListener() {
@Override
public void onMessage(Message message) {
// 取消息内容
if (message instanceof TextMessage) {
TextMessage textMessage = (TextMessage) message;
try {
String text = textMessage.getText();
// 打印消息内容
System.out.println(text);
} catch (JMSException e) {
e.printStackTrace();
}
}
}
});
// 系统等待接收消息
System.in.read();
// 关闭资源
consumer.close();
session.close();
connection.close();
}
3)topic主题形式
使用方式基本一样,区别在于创建Destination对象时,需要创建对应的Topic对象。
Topic topic = session.createTopic("test-topic");
// 使用Session对象创建一个Consumer对象
MessageConsumer consumer = session.createConsumer(topic);
Topic topic = session.createTopic("test-topic");
/ 创建Producer对象
MessageProducer producer = session.createProducer(topic);
五、spring整合ActiveMQ使用:
1)引入相关的依赖jar包
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jms</artifactId>
<version>4.2.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>4.2.4.RELEASE</version>
</dependency>
2)具体以商品添加时,发送消息通知搜索服务更新索引库为例:
生产者的spring配置文件中配置如下:
<!-- 真正可以产生Connection的ConnectionFactory,由JMS服务厂商提供的 -->
<bean id="targetConnectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
<constructor-arg name="brokerURL" value="tcp://192.168.1.8:61616"></constructor-arg>
</bean>
<!-- spring对象ConnectionFactory的封装 -->
<bean id="connectionFactory" class="org.springframework.jms.connection.SingleConnectionFactory">
<property name="targetConnectionFactory" ref="targetConnectionFactory"></property>
</bean>
<!-- 配置JMSTemplate -->
<bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
<property name="connectionFactory" ref="connectionFactory"></property>
</bean>
<!-- 配置消息的Destination对象,使用Topic主题方式 -->
<bean id="itemAddTopic" class="org.apache.activemq.command.ActiveMQTopic">
<constructor-arg name="name" value="item-add-topic"></constructor-arg>
</bean>
使用时先注入JmsTemplate和Destination对象:
@Autowired
private JmsTemplate jmsTemplate;
@Resource(name = "itemAddTopic")
private Destination destination;
向数据库中添加商品后执行以下代码发布消息:
// 向Activemq发送商品添加消息
jmsTemplate.send(destination, new MessageCreator() {
@Override
public Message createMessage(Session session) throws JMSException {
// 发送商品id
TextMessage textMessage = session.createTextMessage(id + "");
return textMessage;
}
});
消费者的spring配置文件中配置如下:
<!-- 真正可以产生Connection的ConnectionFactory,由JMS服务厂商提供的 -->
<bean id="targetConnectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
<constructor-arg name="brokerURL" value="tcp://192.168.1.8:61616"></constructor-arg>
</bean>
<!-- spring对象ConnectionFactory的封装 -->
<bean id="connectionFactory" class="org.springframework.jms.connection.SingleConnectionFactory">
<property name="targetConnectionFactory" ref="targetConnectionFactory"></property>
</bean>
<!--itemAddTopic需与生产者提供的一样-->
<bean id="itemAddTopic" class="org.apache.activemq.command.ActiveMQTopic">
<constructor-arg name="name" value="item-add-topic"></constructor-arg>
</bean>
<!-- 配置监听器 -->
<!--需自定义监听器类ItemAddMessageListener,该类继承MessageListener,重写onMessage方法实现自己的业务逻辑-->
<bean id="itemAddMessageListener" class="com.taotao.search.listener.ItemAddMessageListener"></bean>
<bean class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="connectionFactory" ref="connectionFactory"></property>
<property name="destination" ref="itemAddTopic"></property>
<property name="messageListener" ref="itemAddMessageListener"></property>
</bean>
ItemAddMessageListener监听类,监听商品添加消息,同步索引库:
public class ItemAddMessageListener implements MessageListener {
@Autowired
private SearchItemMapper searchItemMapper;
@Autowired
private SolrServer solrServer;
@Override
public void onMessage(Message message) {
try {
// 从消息中取商品id
TextMessage textMessage = (TextMessage) message;
String text = textMessage.getText();
long itemId = Long.parseLong(text);
// 根据商品id查询数据,取商品信息
// 等待发送消息方法事物提交
Thread.sleep(1000);
SearchItem searchItem = searchItemMapper.getItemById(itemId);
// 创建文档对象
SolrInputDocument document = new SolrInputDocument();
document.addField("id", searchItem.getId());
document.addField("item_title", searchItem.getTitle());
document.addField("item_sell_point", searchItem.getSell_point());
document.addField("item_price", searchItem.getPrice());
document.addField("item_image", searchItem.getImage());
document.addField("item_category_name", searchItem.getCategory_name());
document.addField("item_desc", searchItem.getItem_desc());
solrServer.add(document);
// 提交
solrServer.commit();
} catch (Exception e) {
e.printStackTrace();
}
}
}