文章大纲
一 、第八天课程计划
二、同步索引库分析
三、ActiveMQ
四、ActiveMQ的安装
五、ActiveMQ的使用方法
六、Activemq整合spring
七、activemq整合到项目中
淘淘商城课程大纲
课程大纲
一共14天课程
(1)第一天:电商介绍–互联网术语-SOA-分布式-集群介绍-环境配置-框架搭建
(2)第二天:Dubbo介绍_dubbo框架整合_商品列表查询实现_分页_逆向工程
(3)第三天:Git&.Nginx,类目选择,新增商品
(4)第四天:门户网站介绍&商城首页搭建&内容系统创建&CMS实现
(5)第五天:首页轮播图显示实现,Redis环境搭建,Redis实现缓存
(6)第六天:solr索引库搭建&solr搜索功能实现&图片显示问题解决
(7)第七天:solr集群搭建_全局异常处理
(8)第八天:activeMQ介绍_搭建_解决同步索引库问题
(9)第九天:FreeMark入门_静态化页面标签介绍_静态化页面实现
(10)第十天:Nginx代理详解…单点登录系统工程搭建_接口文档讲解
(11)第十一天:SSO系统的搭建&单点登录系统实现_用户名回显_cookie跨域问题
(12)第十二天:购物车订单系统的实现。
(13)第十三天:订单提交的功能实现&项目的部署&服务器的域名规划。
(14)项目总结。
1. 第八天课程计划
1、什么是MQ
2、MQ的应用场景
3、ActiveMQ的使用方法。
4、使用消息队列实现商品同步。
2. 同步索引库分析
方案一:在taotao-manager中,添加商品的业务逻辑中,添加一个同步索引库的业务逻辑。
缺点:业务逻辑耦合度非常高,业务拆分不明确
方案二:业务逻辑在taotao-search中实现,调用服务在taotao-manager实现。业务逻辑分开。
缺点:
服务之间的耦合度变高,启动有先后顺序。
随着调用的服务会越来越多,服务之间的调用越来越复杂,难以管理。
方案三:使用消息队列。
存在的问题:
1、如果MQ挂了,所有相关的服务都挂了
2、MQ有性能的瓶颈,尽量减少消息的内容的大小
技术的选型和具体的业务有关,只选择合适的技术。
如果MQ挂了:
1.通过日志查找原因
2.通知相关的人员修复
3.关键的业务必须保证有备用方案
3. ActiveMQ
MQ是一个消息中间件,比如:ActiveMQ、RabbitMQ、kafka都属于MQ,是MQ的产品。
3.1. 什么是ActiveMQ
ActiveMQ 是Apache出品,最流行的,能力强劲的开源消息总线。ActiveMQ 是一个完全支持JMS1.1和J2EE 1.4规范的 JMS Provider实现,尽管JMS规范出台已经是很久的事情了,但是JMS在当今的J2EE应用中间仍然扮演着特殊的地位。
主要特点:
1. 多种语言和协议编写客户端。语言: Java, C, C++, C#, Ruby, Perl, Python, PHP。应用协议: OpenWire,Stomp REST,WS Notification,XMPP,AMQP
2. 完全支持JMS1.1和J2EE 1.4规范 (持久化,XA消息,事务)
3. 对Spring的支持,ActiveMQ可以很容易内嵌到使用Spring的系统里面去,而且也支持Spring2.0的特性
4. 通过了常见J2EE服务器(如 Geronimo,JBoss 4, GlassFish,WebLogic)的测试,其中通过JCA 1.5 resource adaptors的配置,可以让ActiveMQ可以自动的部署到任何兼容J2EE 1.4 商业服务器上
5. 支持多种传送协议:in-VM,TCP,SSL,NIO,UDP,JGroups,JXTA
6. 支持通过JDBC和journal提供高速的消息持久化
7. 从设计上保证了高性能的集群,客户端-服务器,点对点
8. 支持Ajax
9. 支持与Axis的整合
10. 可以很容易得调用内嵌JMS provider,进行测试
3.2. ActiveMQ的消息形式
对于消息的传递有两种类型:
一种是点对点的,即一个生产者和一个消费者一一对应;
另一种是发布/订阅模式,即一个生产者产生消息并进行发送后,可以由多个消费者进行接收。
JMS定义了五种不同的消息正文格式,以及调用的消息类型,允许你发送并接收以一些不同形式的数据,提供现有消息格式的一些级别的兼容性。
· StreamMessage – Java原始值的数据流
· MapMessage–一套名称-值对
· TextMessage–一个字符串对象
· ObjectMessage–一个序列化的 Java对象
· BytesMessage–一个字节的数据流
4. ActiveMQ的安装
进入http://activemq.apache.org/下载ActiveMQ
使用的版本是5.13.0
4.1. 安装环境:
1、activemq是java语言开发的,需要jdk
2、安装Linux系统。生产环境都是Linux系统。
4.2. 安装步骤
第一步: 把ActiveMQ 的压缩包上传到Linux系统。
第二步:解压缩。
第三步:启动。
使用bin目录下的activemq命令
启动:
[root@localhost bin]# ./activemq start
关闭:
[root@localhost bin]# ./activemq stop
查看状态:
[root@localhost bin]# ./activemq status
进入管理后台:
http://192.168.25.130:8161/admin
用户名:admin
密码:admin
5. ActiveMQ的使用方法
点对点:
发布/订阅:
使用其他的工程来学习:
工程需要添加jar包:
5.1. Queue
5.1.1. Producer
生产者:生产消息,发送端。
第一步:创建ConnectionFactory对象,需要指定服务端ip及端口号。
第二步:使用ConnectionFactory对象创建一个Connection对象。
第三步:开启连接,调用Connection对象的start方法。
第四步:使用Connection对象创建一个Session对象。
第五步:使用Session对象创建一个Destination对象(topic、queue),此处创建一个Queue对象。
第六步:使用Session对象创建一个Producer对象。
第七步:创建一个Message对象,创建一个TextMessage对象。
第八步:使用Producer对象发送消息。
第九步:关闭资源。
@Test
public void testQueueProducer() throws Exception {
// 第一步:创建ConnectionFactory对象,需要指定服务端ip及端口号。
//brokerURL服务器的ip及端口号
ConnectionFactory connectionFactory = new ActiveMQConnectionFactory("tcp://192.168.25.130:61616");
// 第二步:使用ConnectionFactory对象创建一个Connection对象。
Connection connection = connectionFactory.createConnection();
// 第三步:开启连接,调用Connection对象的start方法。
connection.start();
// 第四步:使用Connection对象创建一个Session对象。
//第一个参数:是否开启事务。true:开启事务,第二个参数忽略。
//第二个参数:当第一个参数为false时,才有意义。消息的应答模式。1、自动应答2、手动应答。一般是自动应答。
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
// 第五步:使用Session对象创建一个Destination对象(topic、queue),此处创建一个Queue对象。
//参数:队列的名称。
Queue queue = session.createQueue("queue-test");
// 第六步:使用Session对象创建一个Producer对象。
MessageProducer producer = session.createProducer(queue);
// 第七步:创建一个Message对象,创建一个TextMessage对象。
/*TextMessage message = new ActiveMQTextMessage();
message.setText("hello activeMq,this is my first test.");*/
TextMessage textMessage = session.createTextMessage("hello activeMq,this is my first test.");
// 第八步:使用Producer对象发送消息。
producer.send(textMessage);
// 第九步:关闭资源。
producer.close();
session.close();
connection.close();
}
5.1.2. Consumer
消费者:接收消息。
第一步:创建一个ConnectionFactory对象。
第二步:从ConnectionFactory对象中获得一个Connection对象。
第三步:开启连接。调用Connection对象的start方法。
第四步:使用Connection对象创建一个Session对象。
第五步:使用Session对象创建一个Destination对象。和发送端保持一致queue,并且队列的名称一致。
第六步:使用Session对象创建一个Consumer对象。
第七步:接收消息。
第八步:打印消息。
第九步:关闭资源
public class QueueCustomer {
@Test
public void recieve() throws Exception{
// 1.创建一个连接工厂 (Activemq的连接工厂)参数:指定连接的activemq的服务
ConnectionFactory connectionFactory = new ActiveMQConnectionFactory("tcp://192.168.25.130:61616");
// 2.获取连接
Connection connection = connectionFactory.createConnection();
// 3.开启连接
connection.start();
// 4.根据连接对象创建session
// 第一个参数:表示是否使用分布式事务(JTA)
// 第二个参数:如果第一个参数为false,第二个参数才有意义;表示使用的应答模式 :自动应答,手动应答.这里选择自动应答。
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
// 5.根据session创建Destination(目的地,queue topic,这里使用的是queue)
Queue queue = session.createQueue("queue-test");
// 6.创建消费者
MessageConsumer consumer = session.createConsumer(queue);
//7.接收消息
//第一种
// while(true){
// //接收消息 (参数的值表示的是超过一定时间 以毫秒为单位就断开连接)
// Message message = consumer.receive(10000);
// //如果message为空,没有接收到消息了就跳出
// if(message==null){
// break;
// }
//
// if(message instanceof TextMessage){
// TextMessage messaget = (TextMessage)message;
// System.out.println(">>>获取的消息内容:"+messaget.getText());//获取消息内容
// }
// }
System.out.println("start");
//第二种:
//设置监听器,其实开启了一个新的线程。
consumer.setMessageListener(new MessageListener() {
//接收消息,如果有消息才进入,如果没有消息就不会进入此方法
@Override
public void onMessage(Message message) {
if(message instanceof TextMessage){
TextMessage messaget = (TextMessage)message;
try {
//获取消息内容
System.out.println(">>>获取的消息内容:"+messaget.getText());
} catch (JMSException e) {
e.printStackTrace();
}
}
}
});
System.out.println("end");
Thread.sleep(10000);//睡眠10秒钟。
// 9.关闭资源
consumer.close();
session.close();
connection.close();
}
}
5.2. Topic
5.2.1. Producer
使用步骤:
第一步:创建ConnectionFactory对象,需要指定服务端ip及端口号。
第二步:使用ConnectionFactory对象创建一个Connection对象。
第三步:开启连接,调用Connection对象的start方法。
第四步:使用Connection对象创建一个Session对象。
第五步:使用Session对象创建一个Destination对象(topic、queue),此处创建一个Topic对象。
第六步:使用Session对象创建一个Producer对象。
第七步:创建一个Message对象,创建一个TextMessage对象。
第八步:使用Producer对象发送消息。
第九步:关闭资源。
public class TopicProducer {
@Test
public void send() throws Exception{
// 1.创建一个连接工厂 (Activemq的连接工厂)参数:指定连接的activemq的服务
ConnectionFactory connectionFactory = new ActiveMQConnectionFactory("tcp://192.168.25.130:61616");
// 2.获取连接
Connection connection = connectionFactory.createConnection();
// 3.开启连接
connection.start();
// 4.根据连接对象创建session
// 第一个参数:表示是否使用分布式事务(JTA)
// 第二个参数:如果第一个参数为false,第二个参数才有意义;表示使用的应答模式 :自动应答,手动应答.这里选择自动应答。
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
// 5.根据session创建Destination(目的地,queue topic,这里使用的是topic)
Topic topic = session.createTopic("topic-test");//---------------------
// 6.创建生产者
MessageProducer producer = session.createProducer(topic);
// 7.构建消息对象,(构建发送消息的内容) 字符串类型的消息格式(TEXTMessage)
TextMessage textMessage = new ActiveMQTextMessage();
textMessage.setText("发送消息123");// 消息的内容
// 8.发送消息
producer.send(textMessage);
// 9.关闭资源
producer.close();
session.close();
connection.close();
}
}
5.2.2. Consumer
消费者:接收消息。
第一步:创建一个ConnectionFactory对象。
第二步:从ConnectionFactory对象中获得一个Connection对象。
第三步:开启连接。调用Connection对象的start方法。
第四步:使用Connection对象创建一个Session对象。
第五步:使用Session对象创建一个Destination对象。和发送端保持一致topic,并且话题的名称一致。
第六步:使用Session对象创建一个Consumer对象。
第七步:接收消息。
第八步:打印消息。
第九步:关闭资源
public class TopicCustomer1 {
@Test
public void reieve() throws Exception{
// 1.创建一个连接工厂 (Activemq的连接工厂)参数:指定连接的activemq的服务
ConnectionFactory connectionFactory = new ActiveMQConnectionFactory("tcp://192.168.25.130:61616");
// 2.获取连接
Connection connection = connectionFactory.createConnection();
// 3.开启连接
connection.start();
// 4.根据连接对象创建session
// 第一个参数:表示是否使用分布式事务(JTA)
// 第二个参数:如果第一个参数为false,第二个参数才有意义;表示使用的应答模式 :自动应答,手动应答.这里选择自动应答。
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
// 5.根据session创建Destination(目的地,queue topic,这里使用的是queue)
Topic topic = session.createTopic("topic-test");//---------------------
// 6.创建消费者
MessageConsumer consumer = session.createConsumer(topic);
// 7.接收消息
while(true){
//接收消息 (参数的值表示的是超过一定时间 以毫秒为单位就断开连接)
Message message = consumer.receive(100000);
//如果message为空,没有接收到消息了就跳出
if(message==null){
break;
}
if(message instanceof TextMessage){
TextMessage messaget = (TextMessage)message;
System.out.println(">>>获取的消息内容:"+messaget.getText());//获取消息内容
}
}
// 第二种:
// 设置监听器,其实开启了一个新的线程。
// consumer.setMessageListener(new MessageListener() {
// // 接收消息,如果有消息才进入,如果没有消息就不会进入此方法
// @Override
// public void onMessage(Message message) {
// if (message instanceof TextMessage) {
// TextMessage messaget = (TextMessage) message;
// try {
// // 获取消息内容
// System.out.println(">>>获取的消息内容:" + messaget.getText());
// } catch (JMSException e) {
// e.printStackTrace();
// }
// }
// }
// });
//Thread.sleep(10000);// 睡眠10秒钟。
// 9.关闭资源
consumer.close();
session.close();
connection.close();
}
}
5.3. 小结
queue 是点对点模式,只能是一个生产者产生一个消息,被一个消费者消费。
topic 是发布订阅模式,一个生产者可以一个消息,可以被多个消费者消费。
queue 默认是存在于MQ的服务器中的,发送消息之后,消费者随时取。但是一定是一个消费者取,消费完消息也就没有了。
topic 默认是不存在于MQ服务器中的,一旦发送之后,如果没有订阅,消息则丢失。
6. Activemq整合spring
6.1. 配置
第一步:引用相关的jar包。
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jms</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
</dependency>
第二步:配置文件applicationContext-activemq.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.2.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.2.xsd">
<bean id="targetConnection" class="org.apache.activemq.ActiveMQConnectionFactory">
<property name="brokerURL" value="tcp://192.168.25.130:61616"></property>
</bean>
<!-- 通用的connectionfacotry 指定真正使用的连接工厂 -->
<bean id="connectionFactory" class="org.springframework.jms.connection.SingleConnectionFactory">
<property name="targetConnectionFactory" ref="targetConnection"></property>
</bean>
<!-- 接收和发送消息时使用的类 -->
<bean class="org.springframework.jms.core.JmsTemplate">
<property name="connectionFactory" ref="connectionFactory"></property>
</bean>
<bean id="queueDestination" class="org.apache.activemq.command.ActiveMQQueue">
<constructor-arg name="name" value="item-change-queue"></constructor-arg>
</bean>
<!-- <bean id="topicDestination" class="org.apache.activemq.command.ActiveMQTopic">
<constructor-arg name="name" value="item-change-topic"></constructor-arg>
</bean> -->
<bean id="myMessageListener" class="com.itheima.activemq.spring.MyMessageListener"></bean>
<bean class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="connectionFactory" ref="connectionFactory"></property>
<property name="destination" ref="topicDestination"></property>
<property name="messageListener" ref="myMessageListener"></property>
</bean>
</beans>
6.2. 代码测试
此处只是为了测试,使用的是同一个配置文件(生产者和消费者都使用同一个配置文件)
6.2.1. 发送消息
第一步:初始化一个spring容器
第二步:从容器中获得JMSTemplate对象。
第三步:从容器中获得一个Destination对象
第四步:使用JMSTemplate对象发送消息,需要知道Destination
public class Producer {
@Test
public void send() throws Exception{
//1.初始化spring容器
ApplicationContext context = new ClassPathXmlApplicationContext("classpath:applicationContext-activemq.xml");
//2.获取到jmstemplate的对象
JmsTemplate jmsTemplate = context.getBean(JmsTemplate.class);
//3.获取destination
Destination destination = (Destination) context.getBean(Destination.class);
//4.发送消息
jmsTemplate.send(destination, new MessageCreator() {
@Override
public Message createMessage(Session session) throws JMSException {
return session.createTextMessage("通过spring发送的消息123");
}
});
Thread.sleep(100000);
}
}
6.2.2. 接收消息
创建一个MessageListener的实现类。
public class MyMessageListener implements MessageListener {
@Override
public void onMessage(Message message) {
if(message instanceof TextMessage){
TextMessage textMessage = (TextMessage)message;
String text;
try {
text = textMessage.getText();
System.out.println(text);
} catch (JMSException e) {
e.printStackTrace();
}
}
}
}
7. activemq整合到项目中
需要在商品的添加/修改,删除的时候,同步索引库。将数据从数据库中查询出来导入到索引库更新。
消息的发送方为:所在工程taotao-manager-service
消息的接收方为:所在工程taotao-search-service
两个工程都需要依赖activmq:
7.1. Producer
taotao-manager-service工程中发送消息。
功能分析:
当商品添加完成后发送一个TextMessage,包含一个商品id即可。
接收端接收到商品id通过数据库查询到商品的信息(搜索的结果商品的信息)再同步索引库。
applicationContext-activemq.xml配置
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.2.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.2.xsd">
<bean id="targetConnection" class="org.apache.activemq.ActiveMQConnectionFactory">
<property name="brokerURL" value="tcp://192.168.25.128:61616"></property>
</bean>
<!-- 通用的connectionfacotry 指定真正使用的连接工厂 -->
<bean id="connectionFactory" class="org.springframework.jms.connection.SingleConnectionFactory">
<property name="targetConnectionFactory" ref="targetConnection"></property>
</bean>
<!-- 接收和发送消息时使用的类 模板对象-->
<bean class="org.springframework.jms.core.JmsTemplate">
<property name="connectionFactory" ref="connectionFactory"></property>
</bean>
<bean id="topicDestination" class="org.apache.activemq.command.ActiveMQTopic">
<constructor-arg name="name" value="item-change-topic"></constructor-arg>
</bean>
</beans>
代码添加发送消息逻辑的实现
在itemserviceImpl中添加业务逻辑。
@Override
public TaotaoResult creatItem(TbItem item,String desc) {
//生成商品的id
final long itemId = IDUtils.genItemId();
//1.补全item 的其他属性
item.setId(itemId);
item.setCreated(new Date());
//1-正常,2-下架,3-删除',
item.setStatus((byte) 1);
item.setUpdated(item.getCreated());
//2.插入到item表 商品的基本信息表
mapper.insertSelective(item);
//3.补全商品描述中的属性
TbItemDesc desc2 = new TbItemDesc();
desc2.setItemDesc(desc);
desc2.setItemId(itemId);
desc2.setCreated(item.getCreated());
desc2.setUpdated(item.getCreated());
//4.插入商品描述数据
//注入tbitemdesc的mapper
descmapper.insertSelective(desc2);
//添加发送消息的业务逻辑
jmsTemplate.send(destination, new MessageCreator() {
@Override
public Message createMessage(Session session) throws JMSException {
//发送的消息内容
return session.createTextMessage(itemId+"");
}
});
//5.返回taotaoresult
return TaotaoResult.ok();
}
7.2. Consumer
在taotao-search-service中消费消息。
需要加入activmq的依赖。
功能分析
1、接收消息。需要创建MessageListener接口的实现类。
2、取消息,取商品id。
3、根据商品id查询数据库。
4、创建一SolrInputDocument对象。
5、使用SolrServer对象写入索引库。
6、返回成功,返回TaotaoResult。
Dao层
根据商品id查询商品信息。
返回一个searchItem
SearchItemMapper接口中添加如下的方法:
public SearchItem getItemById(Long itemId);
SearchItemMapper.xml映射文件:
<select id="getSearchItemById" parameterType="long" resultType="com.taotao.common.pojo.SearchItem">
SELECT
a.id,
a.title,
a.image,
a.price,
a.sell_point,
b.`name` as category_name,
c.item_desc
FROM
tb_item a,
tb_item_cat b,
tb_item_desc c
WHERE
a.cid = b.id
AND a.id = c.item_id
and a.id=#{itemId}
</select>
SearchDao类中添加如下方法:
/**
* @Description 更新索引库
* @Author LH
* @Date 2020/9/20 10:08
* @Param [itemId]
* @return com.taotao.common.pojo.TaotaoResult
**/
public TaotaoResult updateSearchItemById(Long itemId) throws Exception{
//注入Mapper
//查询到记录
SearchItem item = mapper.getSearchItemById(itemId);
//把记录更新到索引库
//创建solrserver 注入进来
//创建solrinputdocument对象
SolrInputDocument document = new SolrInputDocument();
//向文档对象中添加域
document.addField("id", item.getId().toString());//这里是字符串需要转换
document.addField("item_title", item.getTitle());
document.addField("item_sell_point", item.getSell_point());
document.addField("item_price", item.getPrice());
document.addField("item_image", item.getImage());
document.addField("item_category_name", item.getCategory_name());
document.addField("item_desc", item.getItem_desc());
//向索引库中添加文档
solrServer.add(document);
//提交
solrServer.commit();
return TaotaoResult.ok();
}
Service层
参数:商品ID
业务逻辑:
1、根据商品id查询商品信息。
2、创建一SolrInputDocument对象。
3、使用SolrServer对象写入索引库。
4、返回成功,返回TaotaoResult。
返回值:TaotaoResult
SearchService接口定义
//根据商品的id查询商品的数据,并且更新到索引库中
public TaotaoResult updateItemById(Long itemId) throws Exception;
SearchServiceImpl实现类实现:
@Override
public TaotaoResult updateSearchItemById(Long itemId) throws Exception {
return searchDao.updateSearchItemById(itemId);
}
Listener
package com.taotao.search.listener;
import com.taotao.common.pojo.TaotaoResult;
import com.taotao.search.service.SearchService;
import org.springframework.beans.factory.annotation.Autowired;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.TextMessage;
/**
* @Description : 接收消息的监听器
* @ClassName : ItemChangeMessageListener
* @Author : LH
* @Date: 2020-09-20 09:47
* @Version: 1.0
*/
public class ItemChangeMessageListener implements MessageListener {
//注入service 直接调用 方法更新即可
@Autowired
private SearchService service;
@Override
public void onMessage(Message message) {
//判断消息的类型是否为textmessage
if(message instanceof TextMessage){
//如果是 获取商品的id
TextMessage message2 = (TextMessage)message;
String itemidstr;
try {
//获取的就是商品的id的字符串
itemidstr = message2.getText();
Long itemId = Long.parseLong(itemidstr);
//通过商品的id查询数据 需要开发mapper 通过id查询商品(搜索时)的数据
//更新索引库
TaotaoResult taotaoResult = service.updateSearchItemById(itemId);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
Spring配置监听
在taotao-search-service的配置文件中:配置:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.2.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.2.xsd">
<bean id="targetConnection" class="org.apache.activemq.ActiveMQConnectionFactory">
<property name="brokerURL" value="tcp://192.168.25.128:61616"></property>
</bean>
<!-- 通用的connectionfacotry 指定真正使用的连接工厂 -->
<bean id="connectionFactory" class="org.springframework.jms.connection.SingleConnectionFactory">
<property name="targetConnectionFactory" ref="targetConnection"></property>
</bean>
<bean id="topicDestination" class="org.apache.activemq.command.ActiveMQTopic">
<constructor-arg name="name" value="item-change-topic"></constructor-arg>
</bean>
<!-- messagelistener的初始化 -->
<bean id="itemChangeMessageListener" class="com.taotao.search.listener.ItemChangeMessageListener"></bean>
<!-- 设置默认的监听容器 -->
<bean class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="connectionFactory" ref="connectionFactory"></property>
<property name="destination" ref="topicDestination"></property>
<property name="messageListener" ref="itemChangeMessageListener"></property>
</bean>
</beans>
这样就实现商品数据的索引库和数据库的同步。
7.3.实现效果
添加后可以直接去搜索到,自动更新索引库