品优购11——消息中间件解决方案JMS

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();
		}			
	}
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值