今日目標:
(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();
}
}
}