//消息中间件:异步的消息发送机制。当一个业务不需要同步的返回值的时候。也就是方法内的执行对结果没有影响的时候,
为了提高效率,我们使用消息中间健异步发送消息,异步执行,相当于另外开了线程
****常见的消息中间件产品:**********
(1)ActiveMQ
ActiveMQ 是 Apache 出品,最流行的,能力强劲的开源消息总线。ActiveMQ 是一个完
全支持 JMS1.1 和 J2EE 1.4 规范的 JMS Provider 实现。我们在本次课程中介绍 ActiveMQ 的使
用。
(2)RabbitMQ
AMQP 协议的领导实现,支持多种场景。淘宝的 MySQL 集群内部有使用它进行通讯,
OpenStack 开源云平台的通信组件,最先在金融行业得到运用。
(3)ZeroMQ
史上最快的消息队列系统
(4)Kafka
Apache 下的一个子项目 。特点:高吞吐,在一台普通的服务器上既可以达到 10W/s
的吞吐速率;完全的分布式系统。适合处理海量数据。
****JMS***********
JMS是java中定义的一种面向消息中间健的消息发送的规范, 类似于jdbc,但是jdbc 是不能直接访问数据库的,各大厂商根据接口规范,
开发自己的驱动,连接产品数据库
JMS 定义了五种不同的消息正文格式:
· TextMessage--一个字符串对象
· MapMessage--一套名称-值对
· ObjectMessage--一个序列化的 Java 对象
· BytesMessage--一个字节的数据流
· StreamMessage -- Java 原始值的数据流
JMS传递消息有两种形式:
点对点:即一个生产者和一个消费者一一对应; 生产者生产了,消费者没有消费会存在中间件的缓存中
另一种是发布/ 订阅模式: 即一个生产者产生消息并进行发送后,可以由多个消费者进行接收。就行广播,广播开了,可以多台收音机接收
但是如果,你的收音机在广播的时候没开,那你就收不到了,过时不候
**************************《《ActiveMQ下载和安装》》*****************************
1.3.1 下载(文件中已下好)
官方网站下载:http://activemq.apache.org/
传到虚拟机: Alt+P
put d:/apache-activemq-5.12.0-bin.tar.gz
解压此文件:
tar zxvf apache-activemq-5.12.0-bin.tar.gz
为 apache-activemq-5.12.0 目录赋权:
chmod 777 apache-activemq-5.12.0
进入 apache-activemq-5.12.0\bin 目录:
赋与执行权限:
chmod 755 activemq
并启动:
./activemq start
控制台输出 为启动成功:
INFO: pidfile created : '/root/apache-activemq-5.12.0//data/activemq.pid' (pid '5846')
假设服务器地址为 192.168.25.130 ,打开浏览器输入地址
http://192.168.25.130:8161/ 即可进入 ActiveMQ 管理页面
点击进入管理页面
点击————> Manage ActiveMQ broker 账号密码都是admin
*******************入门************************
//新建项目导包 web微服务
******************原生JMS使用ActiveMQ发送消息
//生产者执行流程
创建一个 new ActiveMQConnectionFactory("tcp://192.168.25.135:61616");工厂 确定地址值
获取Connection连接,启动连接———》 获取Session 然后通过Session 设置 队列对象(是点对点还是订阅) ,生产者,和要发送的消息
然后通过 Session获取的生产者MessageProducer发送消息,关闭资源
//消费者,也是这个流程,只是Session获取的消费者对象,设置监听 system.in.read();
******************
//分析: 在需要发送消息的web 中 导入
//生产者**
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-client</artifactId>
<version>5.13.4</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jms</artifactId>
</dependency>
//将配置文件 applicationContext-jms-producer.xml放置 resources 下的 spring 中 改名 spring-jms
并修改:
Value="tcp://虚拟机ip地址:61616"/
在web.xml 中 的
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring/spring-jms.xml</param-value>
</context-param>
加载到 spring 中容器中
//代码部分:
//用于发送 solr 导入的消息 同是也是选择发送消息的方式 是点对点还是发布订阅
//如果是发布订阅(按配置文件中id):
// @Autowired
// private Destination topicTextDestination;
@Autowired
private Destination queueSolrDestination;
@Autowired
private JmsTemplate jmsTemplate;
@RequestMapping("/updateStatus.do")
public Result updateStatus(Long[] ids, String status){
try {
goodsService.updateStatus(ids, status);
if ("1".equals(status)){
List<TbItem> itemList = goodsService.findItemListByGoodsIdandStatus(ids, status);
//调用搜索接口实现数据批量导入
if(itemList.size()>0){
//因为是集合 所以先将 集合用JSON转换成字符串 再在接收后转换回来*******
final String jsonString = JSON.toJSONString(itemList);
jmsTemplate.send(queueSolrDestination, new MessageCreator() {
@Override
public Message createMessage(Session session) throws JMSException
{
return session.createTextMessage(jsonString);
}
});
//*************************
}else{
System.out.println("没有明细数据");
}
//静态页生成
for(Long goodsId:ids){
itemPageService.genItemHtml(goodsId);
}
}
return new Result(true, "成功");
} catch (Exception e) {
e.printStackTrace();
return new Result(false, "失败");
}
}
//消费者**
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-client</artifactId>
<version>5.13.4</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jms</artifactId>
</dependency>
导入配置文件 applicationContext-jms-consumer.xml
并修改: 将value值修改成 生产者队列名称
<!--这个是队列目的地,点对点的 文本信息-->
<bean id="queueTextDestination" class="org.apache.activemq.command.ActiveMQQueue">
<constructor-arg value="pinyougou_queue_solr"/>
</bean>
修改:value="tcp://192.168.25.130:61616"/> 成自己ip地址
删除我的监听类路径 用注解配置
**这个类要建在 <dubbo:annotation package="com.pinyougou.search.service.impl" />的目录下 这里其实就做了一个扫描的动作
自定义一个名称:<property name="messageListener" ref="itemSearchListener" />
并创建一个类ItemSearchListener 实现MessageListener 接口
*注意类上要加上@Component注解 ,加载到spring容器
package com.pinyougou.search.service.impl;
import com.pinyougou.page.service.ItemPageService;
import org.springframework.beans.factory.annotation.Autowired;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.TextMessage;
import org.springframework.stereotype.Component;
@Component
public class ItemSerachListener implements MessageListener {
@Reference //这里是远程调用
private ItemPageService itemPageService;
@Override
public void onMessage(Message message) {
TextMessage textMessage= (TextMessage)message;
try {
String text = textMessage.getText();
System.out.println("接收到消息:"+text);
boolean b = itemPageService.genItemHtml(Long.parseLong(text));
} catch (Exception e) {
e.printStackTrace();
}
}
}
//拓展项目实战:
<!--这个是订阅模式 用于删除页面-->
<bean id="topicPageDeleteDestination" class="org.apache.activemq.command.ActiveMQTopic">
<constructor-arg value="pinyougou_topic_page_delete"/>
</bean>
//生产者Controller层 从solr和数据库删除
@Autowired
private Destination topicPageDeleteDestination;//用于删除静态网页的消息
@RequestMapping("/delete")
public Result delete(final Long [] ids){
goodsService.delete(ids);
//删除页面
jmsTemplate.send(topicPageDeleteDestination, new MessageCreator() {
@Override
public Message createMessage(Session session) throws JMSException {
return session.createObjectMessage(ids);
}
});
}
消费者:
<!--这个是订阅模式 用于删除页面-->
<bean id="topicPageDeleteDestination" class="org.apache.activemq.command.ActiveMQTopic">
<constructor-arg value="pinyougou_topic_page_delete"/>
</bean>
<!-- 消息监听容器 -->
<bean class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="connectionFactory" ref="connectionFactory" />
<property name="destination" ref="topicPageDeleteDestination" />
<property name="messageListener" ref="itemDeleteListener" />
</bean>
package com.pinyougou.search.service.impl;
import java.util.Arrays;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.ObjectMessage;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.pinyougou.search.service.ItemSearchService;
@Component
public class ItemDeleteListener implements MessageListener {
@Autowired
private ItemSearchService itemSearchService;
@Override
public void onMessage(Message message) {
ObjectMessage objectMessage =(ObjectMessage)message;
try {
Long[] goodsIds= (Long[]) objectMessage.getObject();
System.out.println("监听获取到消息:"+goodsIds);
itemSearchService.deleteByGoodsIds(Arrays.asList(goodsIds));
System.out.println("执行索引库删除");
} catch (JMSException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}