SSM分布式项目之淘淘商城-第八天(IDEA)

文章大纲
一 、第八天课程计划
二、同步索引库分析
三、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.实现效果

在这里插入图片描述
添加后可以直接去搜索到,自动更新索引库
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值