1. 商品审核导入solr索引库
运用消息中间件activeMQ实现运营商后台与搜索服务的零耦合。运营商执行商品审核后,向activeMQ发送消息(SKU列表),搜索服务从activeMQ接收到消息并导入到solr索引库。
1.1 生产者(运营商后台)
1)解除manager-web与搜索服务接口itemSearchService的耦合,然后添加activeMQ的依赖
<dependency>
<groupId>com.pinyougou</groupId>
<artifactId>pinyougou-search-interface</artifactId>
<version>0.0.3-SNAPSHOT</version>
</dependency>
2)添加JMS配置文件
<?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.130: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)修改web.xml
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring/spring-*.xml</param-value>
</context-param>
4)在GoodsController中修该代码
// 1.2 导入索引库
if(!CollectionUtils.isEmpty(itemList)){
// itemSearchService.importList(itemList);
// 使用activeMQ来实现
// 注意:L这里需要转成json字符串,因为数据源是list集合,list集合没有实现可序列化接口不能再网络传递数据
final String jsonString = JSON.toJSONString(itemList);
jmsTemplate.send(queueSolrDestination, new MessageCreator() {
@Override
public Message createMessage(Session session) throws JMSException {
return session.createTextMessage(jsonString);
}
});
}
1.2 消费者(搜索服务)
1)添加ActiveMQ依赖
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-client</artifactId>
<version>5.13.4</version>
</dependency>
2)添加jms配置文件
<?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.130: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="itemSearchListener" />
</bean>
</beans>
3)编写消息监听器MessageListener
package com.pinyougou.search.service.impl;
import java.util.List;
import javax.annotation.Resource;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.TextMessage;
import org.springframework.stereotype.Component;
import com.alibaba.fastjson.JSON;
import com.pinyougou.pojo.TbItem;
import com.pinyougou.search.service.ItemSearchService;
@Component
public class ItemSearchListener implements MessageListener{
@Resource
private ItemSearchService itemSearchService;
@Override
public void onMessage(Message message) {
TextMessage textMessage = (TextMessage)message;
try {
// 获取消息队列中的数据
String itemListStr = textMessage.getText();
List<TbItem> itemList = JSON.parseArray(itemListStr, TbItem.class);
// 执行方法,存入solr库
itemSearchService.importList(itemList);
} catch (JMSException e) {
System.out.println("搜索服务接收消息失败!");
e.printStackTrace();
}
}
}
2. 商品审核删除solr索引库
步骤差不多
2.1 生产者
1)配置文件:添加一个队列对象queueSolrDestination的配置
注意;如果测试的发现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: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">
<bean id="connectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
<constructor-arg index="0" value="admin"/>
<constructor-arg index="1" value="admin"/>
<constructor-arg index="2" value="tcp://192.168.25.130:61616"/>
<property name="useAsyncSend" value="true"></property>
<property name="clientID" value="prod1"></property>
</bean>
<!--new add begin-->
<bean id="cachingConnectionFactory" class="org.springframework.jms.connection.CachingConnectionFactory">
<property name="targetConnectionFactory" ref="connectionFactory"/>
<property name="sessionCacheSize" value="100" />
</bean>
<!-- Spring提供的JMS工具类,它可以进行消息发送、接收等 -->
<bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
<!-- 这个connectionFactory对应的是我们定义的Spring提供的那个ConnectionFactory对象 -->
<property name="connectionFactory" ref="cachingConnectionFactory"/>
</bean>
<!-- 注入队列对象 这个是队列目的地,点对点的 文本信息-->
<bean id="queueSolrDestination" class="org.apache.activemq.command.ActiveMQQueue">
<constructor-arg value="pinyougou_queue_solr"/>
</bean>
<bean id="queueSolrDeleDestination" class="org.apache.activemq.command.ActiveMQQueue">
<constructor-arg value="pinyougou_queue_solr_dele"/>
</bean>
<!--注入队列对象 这个是订阅模式 文本信息-->
<!-- <bean id="topicTextDestination" class="org.apache.activemq.command.ActiveMQTopic">
<constructor-arg value="topic_text"/>
</bean> -->
</beans>
2)代码
注意:这里用SolrTemplate根据“item_goodsid”删除的时候,一直删除不掉,所以改成了按照id删除,可以成功删除
2.2 消费者
配置文件同生产者的原理,我使用的是连接池配置,
<?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">
<bean id="connectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
<constructor-arg index="0" value="admin"/>
<constructor-arg index="1" value="admin"/>
<constructor-arg index="2" value="tcp://192.168.25.130:61616"/>
<property name="useAsyncSend" value="true"></property>
<property name="clientID" value="con1"></property>
</bean>
<!--new add begin-->
<bean id="cachingConnectionFactory" class="org.springframework.jms.connection.CachingConnectionFactory">
<property name="targetConnectionFactory" ref="connectionFactory"/>
<property name="sessionCacheSize" value="100" />
</bean>
<!--这个是队列目的地,点对点的 文本信息 添加到solr库-->
<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="cachingConnectionFactory" />
<property name="destination" ref="queueSolrDestination" />
<property name="messageListener" ref="itemSearchListener" />
</bean>
<!--这个是队列目的地,点对点的 文本信息 删除solr库-->
<bean id="queueSolrDeleDestination" class="org.apache.activemq.command.ActiveMQQueue">
<constructor-arg value="pinyougou_queue_solr_dele"/>
</bean>
<!-- 消息监听容器 -->
<bean class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="connectionFactory" ref="cachingConnectionFactory" />
<property name="destination" ref="queueSolrDeleDestination" />
<property name="messageListener" ref="itemSearchDeleListener" />
</bean>
</beans>
2)代码实现,新增一个监听器
package com.pinyougou.search.service.impl;
import java.util.Arrays;
import java.util.List;
import javax.annotation.Resource;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.TextMessage;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import com.alibaba.fastjson.JSON;
import com.pinyougou.search.service.ItemSearchService;
/**
* 删除索引库 jms监听器
* @author Administrator
*
*/
@Component
public class ItemSearchDeleListener implements MessageListener {
@Resource
private ItemSearchService itemSearchService;
@Override
public void onMessage(Message message) {
TextMessage textMessage = (TextMessage)message;
try {
String str = textMessage.getText();
System.out.println("接收到了消息:");
if(!StringUtils.isEmpty(str)){
//Long[] goodsIds = (Long[]) objectMessage.getObject();
List<Long> ids = JSON.parseArray(str, Long.class);
System.out.println("接收到的消息:" + ids.toString());
itemSearchService.deleteByGoodsIds(ids);
System.out.println("删除索引库成功!");
}
} catch (JMSException e) {
System.out.println("删除索引库失败!");
e.printStackTrace();
}
}
}
3. 商品审核-执行网页静态化
3.1 生产者
1)修改pinyougou-manager-web,移除网页生成服务接口依赖page-interface
2)GoodsController.java中删除调用网页生成服务接口的相关代码
3)在activeMQ的spring配置文件中加入topic队列的注入对象
<!--这个是订阅模式 文本信息-->
<bean id="topicPageDestination" class="org.apache.activemq.command.ActiveMQTopic">
<constructor-arg value="pinyougou_topic_page"/>
</bean>
4)代码实现
为了不过多的改代码,保留原来的循环逻辑不变,代码如下
/* 2. 审核成功之后,生成商品详情页*/
for(final Long goodsId : ids){
// boolean flag = itemPageService.genItemHtml(goodsId);
jmsTemplate.send(topicPageDestination, new MessageCreator() {
@Override
public Message createMessage(Session session) throws JMSException {
return session.createTextMessage(goodsId+"");
}
});
}
3.2 消费者(页面生成服务)
1)解除Dubbox依赖
注意:可以不必解除,但是已经用不到了,所以给删除掉这部分依赖比较好
2)spring的配置文件中删除dubbox的配置
3)添加包扫描配置信息
<context:component-scan base-package="com.pinyougou.page.service.impl"/>
4)添加activeMQ依赖
添加JMS的配置文件
<?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">
<bean id="connectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
<constructor-arg index="0" value="admin"/>
<constructor-arg index="1" value="admin"/>
<constructor-arg index="2" value="tcp://192.168.25.130:61616"/>
<property name="useAsyncSend" value="true"></property>
<property name="clientID" value="con2"></property>
</bean>
<!--new add begin-->
<bean id="cachingConnectionFactory" class="org.springframework.jms.connection.CachingConnectionFactory">
<property name="targetConnectionFactory" ref="connectionFactory"/>
<property name="sessionCacheSize" value="100" />
</bean>
<!--这个是队列目的地,点对点的 文本信息 添加到solr库-->
<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="cachingConnectionFactory" />
<property name="destination" ref="topicPageDestination" />
<property name="messageListener" ref="pageListener" />
</bean>
</beans>
5)代码编写
package com.pinyougou.page.service.impl;
import javax.annotation.Resource;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.TextMessage;
import org.springframework.stereotype.Component;
import com.pinyougou.page.service.ItemPageService;
/**页面生成监听器
* @author Administrator
*
*/
@Component
public class PageListener implements MessageListener {
@Resource
private ItemPageService itemPageService;
@Override
public void onMessage(Message message) {
System.out.println("页面监听器接收到有消息发送");
TextMessage textMessage = (TextMessage)message;
try {
String text = textMessage.getText();
System.out.println("页面监听器接收到消息:" + text);
Long id = Long.valueOf(text);
boolean html = itemPageService.genItemHtml(id);
if(html){
System.out.println("页面生成成功!");
} else {
System.out.println("页面生成失败!");
}
} catch (JMSException e) {
System.out.println("页面生成出错!");
e.printStackTrace();
}
}
}
4. 商品删除——删除详情页
4.1 生产者
1)添加配置
<bean id="topicPageDeleteDestination" class="org.apache.activemq.command.ActiveMQTopic">
<constructor-arg value="pinyougou_topic_page_delete"/>
</bean>
2)修改GoodsController.java
/*
* 删除页面
* */
jmsTemplate.send(topicPageDeleDestination, new MessageCreator() {
@Override
public Message createMessage(Session session) throws JMSException {
return session.createObjectMessage(ids);
}
});
4.2 消费者
1)修改配置文件
<!--删除页面 -->
<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="pageDeleteListener" />
</bean>
2)在pinyougou-page-service的ItemPageServiceImpl.java方法中国添加删除方法
@Override
public boolean deleItemHtml(Long [] ids){
try {
for(Long id : ids){
// 1. 获取文件
File file = new File(pageDir + id + ".html");
if(file.exists()){
file.delete();
}
}
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
3)创建监听类
@Component
public class PageDeleteListener implements MessageListener {
@Autowired
private ItemPageService itemPageService;
@Override
public void onMessage(Message message) {
ObjectMessage objectMessage= (ObjectMessage)message;
try {
Long[] goodsIds = (Long[]) objectMessage.getObject();
System.out.println("ItemDeleteListener监听接收到消息..."+goodsIds);
boolean b = itemPageService.deleteItemHtml(goodsIds);
System.out.println("网页删除结果:"+b);
} catch (JMSException e) {
e.printStackTrace();
}
}
}