一、什么是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(); } } }