黑马淘淘商城第八天 什么是MQ 、MQ的应用场景、ActiveMQ的使用方法、使用消息队列实现商品同步...

1. 课程计划

第八天:

1、什么是MQ
2、MQ的应用场景
3、ActiveMQ的使用方法。
4、使用消息队列实现商品同步。

2. 同步索引库分析

方案一:在taotao-manager中,添加商品的业务逻辑中,添加一个同步索引库的业务逻辑。
缺点:业务逻辑耦合度高,业务拆分不明确
方案二:业务逻辑在taotao-search中实现,调用服务在taotao-manager实现。业务逻辑分开。
缺点:服务之间的耦合度变高。服务的启动有先后顺序。
方案三:使用消息队列。MQ是一个消息中间件。
在这里插入图片描述
MQ是一个消息中间件,ActiveMQ、RabbitMQ、kafka
为了实现系统之间的通信,把系统之间的调用耦合度降低就可以使用MQ

3. ActiveMQ

1:消息中间件

消息中间件:在分布式系统中,完成消息的发送和接收的基础软件,在分布式系统中起着非常重要的作用。
通过消息中间件,可以让应用程序间实现可靠的异步通讯,从而降低系统间的耦合度。
Note:如果应用程序A直接调用应用程序B,要么导入B的jar 要么导入B的接口,无论哪一种A和B耦合在一起。通过消息中间件,A和B实现完全解耦,A甚至都不知道B的存在
在这里插入图片描述
实际场景:在这里插入图片描述
图2是传统架构,传统架构弊端
1:交易服务依赖其他多个服务接口,耦合度高。
2:如果其他服务是串行化调用,耗时长,长时间占用线程,导致线程挂起.
图3引入消息中间件,架构优点:
1:交易服务与其他服务完全解耦
2:交易服务不会出现线程阻塞
3:其他服务几乎可以并行执行,效率高
2:JMS
JMS:是javaEE中关于消息的规范,是一套与具体平台无关的api,跟jdbc类似。
在这里插入图片描述
javaEE规范了这套接口,activeMQ、rabbitMQ根据接口做了具体的实现
3:消息模型
1:点对点或者队列模型
在这里插入图片描述
生产者可以多个,消费者可以多个,但是对于一条具体消息来说,永远只有一个生产者和一个消费者 一条消息一旦被某个消费者消化掉,其他消费者不可能再消化同一条消息。
2:发布者/订阅者模型
在这里插入图片描述
对于一条具体某个主题,可能存在多个消费者同时消费,只要改消费者订阅了该主题,有点广播的意思。

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
在这里插入图片描述

4.1. 安装环境:

1、需要jdk
jdk
2、安装Linux系统。生产环境都是Linux系统。

4.2. 安装步骤

第一步: 把ActiveMQ 的压缩包上传到Linux系统。
activemq-all-5.11.2.jar和apache-activemq-5.12.0-bin.tar.gz
第二步:解压缩。
第三步:启动。
使用bin目录下的activemq命令启动:
[root@localhost bin]# ./activemq start
关闭:
[root@localhost bin]# ./activemq stop
查看状态:
[root@localhost bin]# ./activemq status

注意:如果ActiveMQ整合spring使用不要使用activemq-all-5.12.0.jar包。建议使用5.11.2

进入管理后台:
http://192.168.25.168:8161/admin
用户名:admin
密码:admin

5. ActiveMQ的使用方法

在这里插入图片描述

5.1. Queue

5.1.1. Producer
生产者:生产消息,发送端。
把jar包添加到工程中。使用5.11.2版本的jar包。
在这里插入图片描述
第一步:创建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.168: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("test-queue");
		// 第六步:使用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对象。
第七步:接收消息。
第八步:打印消息。
第九步:关闭资源

@Test
	public void testQueueConsumer() throws Exception {
		// 第一步:创建一个ConnectionFactory对象。
		ConnectionFactory connectionFactory = new ActiveMQConnectionFactory("tcp://192.168.25.168:61616");
		// 第二步:从ConnectionFactory对象中获得一个Connection对象。
		Connection connection = connectionFactory.createConnection();
		// 第三步:开启连接。调用Connection对象的start方法。
		connection.start();
		// 第四步:使用Connection对象创建一个Session对象。
		Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
		// 第五步:使用Session对象创建一个Destination对象。和发送端保持一致queue,并且队列的名称一致。
		Queue queue = session.createQueue("test-queue");
		// 第六步:使用Session对象创建一个Consumer对象。
		MessageConsumer consumer = session.createConsumer(queue);
		// 第七步:接收消息。
		consumer.setMessageListener(new MessageListener() {
			
			@Override
			public void onMessage(Message message) {
				try {
					TextMessage textMessage = (TextMessage) message;
					String text = null;
					//取消息的内容
					text = textMessage.getText();
					// 第八步:打印消息。
					System.out.println(text);
				} catch (JMSException e) {
					e.printStackTrace();
				}
			}
		});
		//等待键盘输入
		System.in.read();
		// 第九步:关闭资源
		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对象发送消息。
第九步:关闭资源。

@Test
	public void testTopicProducer() throws Exception {
		// 第一步:创建ConnectionFactory对象,需要指定服务端ip及端口号。
		// brokerURL服务器的ip及端口号
		ConnectionFactory connectionFactory = new ActiveMQConnectionFactory("tcp://192.168.25.168: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),此处创建一个topic对象。
		// 参数:话题的名称。
		Topic topic = session.createTopic("test-topic");
		// 第六步:使用Session对象创建一个Producer对象。
		MessageProducer producer = session.createProducer(topic);
		// 第七步:创建一个Message对象,创建一个TextMessage对象。
		/*
		 * TextMessage message = new ActiveMQTextMessage(); message.setText(
		 * "hello activeMq,this is my first test.");
		 */
		TextMessage textMessage = session.createTextMessage("hello activeMq,this is my topic test");
		// 第八步:使用Producer对象发送消息。
		producer.send(textMessage);
		// 第九步:关闭资源。
		producer.close();
		session.close();
		connection.close();
	}

5.2.2. Consumer
消费者:接收消息。
第一步:创建一个ConnectionFactory对象。
第二步:从ConnectionFactory对象中获得一个Connection对象。
第三步:开启连接。调用Connection对象的start方法。
第四步:使用Connection对象创建一个Session对象。
第五步:使用Session对象创建一个Destination对象。和发送端保持一致topic,并且话题的名称一致。
第六步:使用Session对象创建一个Consumer对象。
第七步:接收消息。
第八步:打印消息。
第九步:关闭资源

@Test
	public void testTopicConsumer() throws Exception {
		// 第一步:创建一个ConnectionFactory对象。
		ConnectionFactory connectionFactory = new ActiveMQConnectionFactory("tcp://192.168.25.168:61616");
		// 第二步:从ConnectionFactory对象中获得一个Connection对象。
		Connection connection = connectionFactory.createConnection();
		// 第三步:开启连接。调用Connection对象的start方法。
		connection.start();
		// 第四步:使用Connection对象创建一个Session对象。
		Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
		// 第五步:使用Session对象创建一个Destination对象。和发送端保持一致topic,并且话题的名称一致。
		Topic topic = session.createTopic("test-topic");
		// 第六步:使用Session对象创建一个Consumer对象。
		MessageConsumer consumer = session.createConsumer(topic);
		// 第七步:接收消息。
		consumer.setMessageListener(new MessageListener() {

			@Override
			public void onMessage(Message message) {
				try {
					TextMessage textMessage = (TextMessage) message;
					String text = null;
					// 取消息的内容
					text = textMessage.getText();
					// 第八步:打印消息。
					System.out.println(text);
				} catch (JMSException e) {
					e.printStackTrace();
				}
			}
		});
		System.out.println("topic的消费端03。。。。。");
		// 等待键盘输入
		System.in.read();
		// 第九步:关闭资源
		consumer.close();
		session.close();
		connection.close();
	}

注意:
topic话题消费者都可以接受到消息生产者自动发送的消息,简称广播式发送。当消息订阅者(消费者)的某段时间由于某种原因断开了与消息发布者的连接时,这个时间段内的消息将丢失,除非将消息的订阅模式设置为持久订阅,这是消息的发布者将会为消息的订阅者保留这段时间锁产生的消息。当消息的订阅者重新连接消息发布者是,消息订阅者仍然可以获得这部分消息,而不至于丢失这部分消息。

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>

第二步:配置Activemq整合spring。配置ConnectionFactory

<?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.0.xsd
	http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
	http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd 
	http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
	http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd">


	<!-- 真正可以产生Connection的ConnectionFactory,由对应的 JMS服务厂商提供 -->
	<bean id="targetConnectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
		<property name="brokerURL" value="tcp://192.168.25.168:61616" />
	</bean>
	<!-- Spring用于管理真正的ConnectionFactory的ConnectionFactory -->
	<bean id="connectionFactory"
		class="org.springframework.jms.connection.SingleConnectionFactory">
		<!-- 目标ConnectionFactory对应真实的可以产生JMS Connection的ConnectionFactory -->
		<property name="targetConnectionFactory" ref="targetConnectionFactory" />
	</bean>
</beans>

第三步:配置生产者。
使用JMSTemplate对象。发送消息。
第四步:在spring容器中配置Destination。

<?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.0.xsd
	http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
	http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
	http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd">

	<!-- 真正可以产生Connection的ConnectionFactory,由对应的 JMS服务厂商提供 -->
	<bean id="targetConnectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
		<property name="brokerURL" value="tcp://192.168.25.168:61616" />
	</bean>
	<!-- Spring用于管理真正的ConnectionFactory的ConnectionFactory -->
	<bean id="connectionFactory"
		class="org.springframework.jms.connection.SingleConnectionFactory">
		<!-- 目标ConnectionFactory对应真实的可以产生JMS Connection的ConnectionFactory -->
		<property name="targetConnectionFactory" ref="targetConnectionFactory" />
	</bean>
	<!-- 配置生产者 -->
	<!-- Spring提供的JMS工具类,它可以进行消息发送、接收等 -->
	<bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
		<!-- 这个connectionFactory对应的是我们定义的Spring提供的那个ConnectionFactory对象 -->
		<property name="connectionFactory" ref="connectionFactory" />
	</bean>
	<!--这个是队列目的地,点对点的 -->
	<bean id="queueDestination" class="org.apache.activemq.command.ActiveMQQueue">
		<constructor-arg>
			<value>spring-queue</value>
		</constructor-arg>
	</bean>
	<!--这个是主题目的地,一对多的 -->
	<bean id="topicDestination" class="org.apache.activemq.command.ActiveMQTopic">
		<constructor-arg value="topic" />
	</bean>
</beans>

第五步:代码测试

6.2. 代码测试
6.2.1. 发送消息
第一步:初始化一个spring容器
第二步:从容器中获得JMSTemplate对象。
第三步:从容器中获得一个Destination对象
第四步:使用JMSTemplate对象发送消息,需要知道Destination

@Test
	public void testQueueProducer() throws Exception {
		// 第一步:初始化一个spring容器
		ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:spring/applicationContext-activemq.xml");
		// 第二步:从容器中获得JMSTemplate对象。
		JmsTemplate jmsTemplate = applicationContext.getBean(JmsTemplate.class);
		// 第三步:从容器中获得一个Destination对象
		Queue queue = (Queue) applicationContext.getBean("queueDestination");
		// 第四步:使用JMSTemplate对象发送消息,需要知道Destination
		jmsTemplate.send(queue, new MessageCreator() {
			
			@Override
			public Message createMessage(Session session) throws JMSException {
				TextMessage textMessage = session.createTextMessage("spring activemq test");
				return textMessage;
			}
		});
	}

6.2.2. 接收消息
Taotao-search-Service中接收消息。
第一步:把Activemq相关的jar包添加到工程中
第二步:创建一个MessageListener的实现类。

public class MyMessageListener implements MessageListener {

	@Override
	public void onMessage(Message message) {
		
		try {
			TextMessage textMessage = (TextMessage) message;
			//取消息内容
			String text = textMessage.getText();
			System.out.println(text);
		} catch (JMSException e) {
			e.printStackTrace();
		}
	}

}

第三步:配置spring和Activemq整合。

<?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.0.xsd
	http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
	http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
	http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd">

	<!-- 真正可以产生Connection的ConnectionFactory,由对应的 JMS服务厂商提供 -->
	<bean id="targetConnectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
		<property name="brokerURL" value="tcp://192.168.25.168:61616" />
	</bean>
	<!-- Spring用于管理真正的ConnectionFactory的ConnectionFactory -->
	<bean id="connectionFactory"
		class="org.springframework.jms.connection.SingleConnectionFactory">
		<!-- 目标ConnectionFactory对应真实的可以产生JMS Connection的ConnectionFactory -->
		<property name="targetConnectionFactory" ref="targetConnectionFactory" />
	</bean>
	<!--这个是队列目的地,点对点的 -->
	<bean id="queueDestination" class="org.apache.activemq.command.ActiveMQQueue">
		<constructor-arg>
			<value>spring-queue</value>
		</constructor-arg>
	</bean>
	<!--这个是主题目的地,一对多的 -->
	<bean id="topicDestination" class="org.apache.activemq.command.ActiveMQTopic">
		<constructor-arg value="topic" />
	</bean>
	<!-- 接收消息 -->
	<!-- 配置监听器 -->
	<bean id="myMessageListener" class="com.taotao.search.listener.MyMessageListener" />
	<!-- 消息监听容器 -->
	<bean class="org.springframework.jms.listener.DefaultMessageListenerContainer">
		<property name="connectionFactory" ref="connectionFactory" />
		<property name="destination" ref="queueDestination" />
		<property name="messageListener" ref="myMessageListener" />
	</bean>
</beans>

第四步:测试代码。

@Test
	public void testQueueConsumer() throws Exception {
		//初始化spring容器
		ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:spring/applicationContext-activemq.xml");
		//等待
		System.in.read();
	}

7. 添加商品同步索引库

以topic话题模式来发送消息?
答:添加商品涉及到同步索引库和同步静态页面,而这两个服务在两个不同的服务进程里,如果用队列,会导致一方收不到,所以采用topic模式 广播

7.1. Producer

Taotao-manager-server工程中发送消息。
当商品添加完成后发送一个TextMessage,包含一个商品id。
在这里插入图片描述
在这里插入图片描述

@Override
	public TaotaoResult addItem(TbItem item, String desc) {
		// 1、生成商品id
		final long itemId = IDUtils.genItemId();
		// 2、补全TbItem对象的属性
		item.setId(itemId);
		//商品状态,1-正常,2-下架,3-删除
		item.setStatus((byte) 1);
		Date date = new Date();
		item.setCreated(date);
		item.setUpdated(date);
		// 3、向商品表插入数据
		itemMapper.insert(item);
		// 4、创建一个TbItemDesc对象
		TbItemDesc itemDesc = new TbItemDesc();
		// 5、补全TbItemDesc的属性
		itemDesc.setItemId(itemId);
		itemDesc.setItemDesc(desc);
		itemDesc.setCreated(date);
		itemDesc.setUpdated(date);
		// 6、向商品描述表插入数据
		itemDescMapper.insert(itemDesc);
		//发送一个商品添加消息
		jmsTemplate.send(topicDestination, new MessageCreator() {
			
			@Override
			public Message createMessage(Session session) throws JMSException {
				TextMessage textMessage = session.createTextMessage(itemId + "");
				return textMessage;
			}
		});
		// 7、TaotaoResult.ok()
		return TaotaoResult.ok();
	}

7.2. Consumer

7.2.1. 功能分析
1、接收消息。需要创建MessageListener接口的实现类。
2、取消息,取商品id。
3、根据商品id查询数据库。
4、创建一SolrInputDocument对象。
5、使用SolrServer对象写入索引库。
6、返回成功,返回TaotaoResult。

7.2.2. Dao层
根据商品id查询商品信息。
在这里插入图片描述
映射文件:

<select id="getItemById" parameterType="long" resultType="com.taotao.common.pojo.SearchItem">
		SELECT
			a.id,
			a.title,
			a.sell_point,
			a.price,
			a.image,
			b. NAME category_name,
			c.item_desc
		FROM
			tb_item a
		JOIN tb_item_cat b ON a.cid = b.id
		JOIN tb_item_desc c ON a.id = c.item_id
		WHERE a.status = 1
		  AND a.id=#{itemId}
	</select>

7.2.3. Service层
参数:商品ID
业务逻辑:
1、根据商品id查询商品信息。
2、创建一SolrInputDocument对象。
3、使用SolrServer对象写入索引库。
4、返回成功,返回TaotaoResult。
返回值:TaotaoResult

public TaotaoResult addDocument(long itemId) throws Exception {
		// 1、根据商品id查询商品信息。
		SearchItem searchItem = searchItemMapper.getItemById(itemId);
		// 2、创建一SolrInputDocument对象。
		SolrInputDocument document = new SolrInputDocument();
		// 3、使用SolrServer对象写入索引库。
		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());
		// 5、向索引库中添加文档。
		solrServer.add(document);
		solrServer.commit();
		// 4、返回成功,返回TaotaoResult。
		return TaotaoResult.ok();
	}

7.2.4. Listener

public class ItemChangeListener implements MessageListener {
	
	@Autowired
	private SearchItemServiceImpl searchItemServiceImpl;

	@Override
	public void onMessage(Message message) {
		try {
			TextMessage textMessage = null;
			Long itemId = null; 
			//取商品id
			if (message instanceof TextMessage) {
				textMessage = (TextMessage) message;
				itemId = Long.parseLong(textMessage.getText());
			}
			//向索引库添加文档
			searchItemServiceImpl.addDocument(itemId);
			
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

}

7.2.5. Spring配置监听
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值