今日目标:
(1)理解消息中间件、JMS等概念
(2)掌握JMS点对点与发布订阅模式的收发消息
(3)掌握Spring JMS
(4)完成商品审核,导入索引
(5)完成商品删除,移除索引
(6)完成商品审核生成商品详细页
(7)完成商品删除,删除详细页
目录
1、商品审核-导入solr索引库
1.1 需求分析
运用消息中间件activeMQ实现运营商后台与搜索服务的零耦合。运营商执行商品审核后,向activeMQ发送消息(SKU列表),搜索服务从activeMQ接收到消息并导入到solr索引库。
1.2 消息生产者-运营商后台
(1)导入依赖(manager-web)
<!--ActiveMQ消息中间件-->
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-all</artifactId>
</dependency>
(2)编写配置文件(spring-jms-producer.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:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:amq="http://activemq.apache.org/schema/core"
xmlns:jms="http://www.springframework.org/schema/jms"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!-- 真正可以产生Connection的ConnectionFactory,由对应的 JMS服务厂商提供-->
<bean id="targetConnectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
<property name="brokerURL" value="tcp://192.168.25.170: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="queueSolrDestination" class="org.apache.activemq.command.ActiveMQQueue">
<constructor-arg value="pinyougou_queue_solr"/>
</bean>
<!--这个是订阅模式 文本信息-->
<bean id="topicTextDestination" class="org.apache.activemq.command.ActiveMQTopic">
<constructor-arg value="topic_text"/>
</bean>
</beans>
(3)修改GoodsController中的updateStatus中的逻辑,发送消息
1.3 消息消费者-搜索服务
(1)导入依赖(search-service)
<!--ActiveMQ消息中间件-->
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-all</artifactId>
</dependency>
(2)编写配置文件(applicationContext-jms-consumer.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:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:amq="http://activemq.apache.org/schema/core"
xmlns:jms="http://www.springframework.org/schema/jms"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!-- 真正可以产生Connection的ConnectionFactory,由对应的 JMS服务厂商提供-->
<bean id="targetConnectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
<property name="brokerURL" value="tcp://192.168.25.170: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="queueSolrDestination" class="org.apache.activemq.command.ActiveMQQueue">
<constructor-arg value="pinyougou_queue_solr"/>
</bean>
<!-- 消息监听容器 -->
<bean class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="connectionFactory" ref="connectionFactory" />
<property name="destination" ref="queueSolrDestination" />
<property name="messageListener" ref="itemSearchLinstener" />
</bean>
</beans>
(3)编写监听类(ItemSearchLinstener)
package com.pinyougou.search.service.impl;
import com.alibaba.fastjson.JSON;
import com.pinyougou.pojo.TbItem;
import com.pinyougou.search.service.ItemSearchService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.TextMessage;
import java.util.List;
/**
* 商品导入solr消息监听器
* Author xushuai
* Description
*/
@Component
public class ItemSearchLinstener implements MessageListener {
@Autowired
private ItemSearchService itemSearchService;
@Override
public void onMessage(Message message) {
try {
// 接收消息
TextMessage textMessage = (TextMessage) message;
String json = textMessage.getText();
// 将json转换为itemList对象
List<TbItem> itemList = JSON.parseArray(json, TbItem.class);
// 执行导入solr索引库操作
itemSearchService.importList(itemList);
} catch (JMSException e) {
e.printStackTrace();
}
}
}
2、商品删除-移除索引
2.1 需求分析
通过消息中间件实现在商品删除时也同时移除索引库记录的功能。
2.2 消息生产者-运营商后台
(1)配资文件新增配置(spring-jms-producer.xml)
<!--删除索引库消息-->
<bean id="queueSolrDeleteDestination" class="org.apache.activemq.command.ActiveMQQueue">
<constructor-arg value="pinyougou_queue_solr_delete"/>
</bean>
(2)修改GoodsController中的delete方法的逻辑
2.3 消息消费者-搜索服务
(1)修改配置文件(applicationContext-jms-consumer.xml新增配置)
<!--删除索引消息-->
<bean id="queueSolrDeleteDestination" class="org.apache.activemq.command.ActiveMQQueue">
<constructor-arg value="pinyougou_queue_solr_delete"/>
</bean>
<!-- 消息监听容器 -->
<bean class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="connectionFactory" ref="connectionFactory" />
<property name="destination" ref="queueSolrDeleteDestination" />
<property name="messageListener" ref="itemDeleteLinstener" />
</bean>
(2)创建索引删除监听器(ItemDeleteLinstener)
package com.pinyougou.search.service.impl;
import com.pinyougou.search.service.ItemSearchService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.ObjectMessage;
import java.util.Arrays;
/**
* 删除索引消息监听器
* Author xushuai
* Description
*/
@Component
public class ItemDeleteLinstener implements MessageListener {
@Autowired
private ItemSearchService itemSearchService;
@Override
public void onMessage(Message message) {
ObjectMessage objectMessage = (ObjectMessage) message;
try {
Long[] ids = (Long[]) objectMessage.getObject();
// 执行删除索引操作
itemSearchService.deleteByGoodsIds(Arrays.asList(ids));
} catch (JMSException e) {
e.printStackTrace();
}
}
}
3、商品审核执行网页静态化
3.1 需求分析
运用消息中间件activeMQ实现运营商后台与网页生成服务的零耦合。运营商执行商品审核后,向activeMQ发送消息(商品ID),网页生成服务从activeMQ接收到消息后执行网页生成操作。
3.2 消息生产者-运营商后台
(1)修改配置文件(spring-jms-producer.xml新增配置)
<!--生成商品详细页发布订阅消息-->
<bean id="topicPageDestination" class="org.apache.activemq.command.ActiveMQTopic">
<constructor-arg value="pinyougou_topic_page"/>
</bean>
(2)修改GoodsController中updateStatus中生成商品详细页的逻辑
3.3 消息消费者-页面服务
(1)导入依赖
<!--activemq-->
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-all</artifactId>
</dependency>
(2)编写配置文件(applicationContext-jms-consumer.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:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:amq="http://activemq.apache.org/schema/core"
xmlns:jms="http://www.springframework.org/schema/jms"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!-- 真正可以产生Connection的ConnectionFactory,由对应的 JMS服务厂商提供-->
<bean id="targetConnectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
<property name="brokerURL" value="tcp://192.168.25.170: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="topicPageDestination" class="org.apache.activemq.command.ActiveMQTopic">
<constructor-arg value="pinyougou_topic_page"/>
</bean>
<!-- 消息监听容器 -->
<bean class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="connectionFactory" ref="connectionFactory" />
<property name="destination" ref="topicPageDestination" />
<property name="messageListener" ref="itemPageListener" />
</bean>
</beans>
(3)编写ItemPageLinstener监听器
package com.pinyougou.page.service.impl;
import com.pinyougou.page.service.ItemPageService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.ObjectMessage;
/**
* 生成商品详细页消息监听器
* Author xushuai
* Description
*/
@Component
public class ItemPageListener implements MessageListener {
@Autowired
private ItemPageService itemPageService;
@Override
public void onMessage(Message message) {
// 接收消息
ObjectMessage objectMessage = (ObjectMessage) message;
try {
Long goodsId = (Long) objectMessage.getObject();
// 执行生成商品详细页
itemPageService.genItemPage(goodsId);
} catch (JMSException e) {
e.printStackTrace();
}
}
}
4、商品删除-删除商品详细页
4.1 需求分析
执行商品删除后,同时删除每个服务器上的商品详细页
4.2 消息生产者-运营商后台
(1)修改配置文件(spring-jms-producer.xml新增配置)
<!--删除商品详细页发布订阅消息-->
<bean id="topicPageDeleteDestination" class="org.apache.activemq.command.ActiveMQTopic">
<constructor-arg value="pinyougou_topic_page_delete"/>
</bean>
(2)修改GoodsController中的delete方法的逻辑
4.3 消息消费者-页面服务
(1)修改配置文件(applicationContext-jms-consumer.xml新增配置)
<!--生成商品详细页消息-->
<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="itemPageDeleteListener" />
</bean>
(2)服务层接口,新增方法(ItemPageService)
/**
* 删除指定商品的商品详细页
*
* @param goodsIds 商品ID数组
* @return boolean
*/
boolean deleteItemPage(Long[] goodsIds);
(3)服务层实现,实现(ItemPageServiceImpl)
@Override
public boolean deleteItemPage(Long[] goodsIds) {
try {
for (Long goodsId : goodsIds) {
// 删除文件夹中的文件
new File(PAGE_DIR + goodsId + ".html").delete();
}
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
(3)编写ItemPageDeleteLinstener 监听器
package com.pinyougou.page.service.impl;
import com.pinyougou.page.service.ItemPageService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.ObjectMessage;
/**
* 删除商品详细页消息监听器
* Author xushuai
* Description
*/
@Component
public class ItemPageDeleteListener implements MessageListener {
@Autowired
private ItemPageService itemPageService;
@Override
public void onMessage(Message message) {
// 接收消息
ObjectMessage objectMessage = (ObjectMessage) message;
try {
Long[] ids = (Long[]) objectMessage.getObject();
// 执行删除商品详细页
itemPageService.deleteItemPage(ids);
} catch (JMSException e) {
e.printStackTrace();
}
}
}