这里我们使用RabbitMQ消息通信,后台添加商品,通知前台,删除与商品相关的缓存内容。在后台系统中,我们定义交换器和模板。在前台系统中定义队列,监听和模板。在Web的管理工具中绑定交换器和队列;
后台系统
1.在Pom.xml文件中引入依赖
<dependency>
<groupId>org.springframework.amqp</groupId>
<artifactId>spring-rabbit</artifactId>
<version>1.4.0.RELEASE</version>
</dependency>
2.把RabbitMQ加入到Spring的管理中。
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:rabbit="http://www.springframework.org/schema/rabbit"
xsi:schemaLocation="http://www.springframework.org/schema/rabbit
http://www.springframework.org/schema/rabbit/spring-rabbit-1.4.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.1.xsd">
<!-- 定义RabbitMQ的连接工厂 -->
<rabbit:connection-factory id="connectionFactory"
host="${rabbitmq.ip}" port="${rabbitmq.port}" username="${rabbitmq.username}" password="${rabbitmq.password}"
virtual-host="${rabbitmq.vhost}" />
<!-- MQ的管理,包括队列、交换器等,声明交换器 -->
<rabbit:admin connection-factory="connectionFactory"/>
<!-- 定义交换机,durable性能更高 -->
<rabbit:topic-exchange name="TAOTAO-ITEM-EXCHANGE" auto-declare="true" durable="false"/>
<!-- 定义一个模板 -->
<rabbit:template id="taotaoItemTemplate" connection-factory="connectionFactory" exchange="TAOTAO-ITEM-EXCHANGE"></rabbit:template>
</beans>
3.属性配置
rabbitmq.ip=127.0.0.1
rabbitmq.port=5672
rabbitmq.username=taotao
rabbitmq.password=taotao
rabbitmq.vhost=/taotao
4.后台系统在添加商品的时候,向交换器中发送消息
@Service
public class ItemServiceImpl implements ItemService {
@Autowired
private TbItemMapper itemMapper;
@Autowired
private TbItemDescMapper itemDescMapper;
@Autowired
private TbItemParamItemMapper itemParamItemMapper;
//****************************************************
@Autowired
private RabbitTemplate rabbitTemplate;
private final static ObjectMapper MAPPER=new ObjectMapper();
//****************************************************
* 添加商品信息;
* itemParam商品规格参数
*/
@Override
public TaotaoResult createItem(TbItem item, String desc,String itemParam) {
//生成商品id
long itemId = IDUtils.genItemId();
//补全TbItem属性
item.setId(itemId);
//商品状态:1-正常,2-下架,3-删除
item.setStatus((byte)1);
//创建时间和更新时间
Date date = new Date();
item.setCreated(date);
item.setUpdated(date);
//插入商品表
itemMapper.insert(item);
//商品描述
TbItemDesc itemDesc = new TbItemDesc();
itemDesc.setItemId(itemId);
itemDesc.setItemDesc(desc);
itemDesc.setCreated(date);
itemDesc.setUpdated(date);
//插入商品描述数据;
itemDescMapper.insert(itemDesc);
//商品规格参数
TbItemParamItem itemParamItem = new TbItemParamItem();
itemParamItem.setItemId(itemId);
itemParamItem.setParamData(itemParam);
itemParamItem.setCreated(date);
itemParamItem.setUpdated(date);
//插入商品规格参数;
itemParamItemMapper.insert(itemParamItem);
//***************************************************
//发送消息给其他系统
sendMsg(item.getId(), "insert");
//****************************************************
return TaotaoResult.ok();
}
//后台系统关于RabbitMQ消息通信的配置;
private void sendMsg(long itemId,String type)
{
//处理异常,不能影响正常的业务逻辑,所以应该抓取;
try {
//发送消息通知其他系统
Map<String, Object> msg= new HashMap<String, Object>();
msg.put("itemId", itemId);
msg.put("type",type);
msg.put("date", System.currentTimeMillis());
//指定路由键和消息
//消息中包含,商品Id;
this.rabbitTemplate.convertAndSend("item." + type,MAPPER.writeValueAsString(msg));
} catch (Exception e) {
e.printStackTrace();
}
}
}
前台系统
1和3拷贝到前台系统相关位置
RabbitMQ的配置如下
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:rabbit="http://www.springframework.org/schema/rabbit"
xsi:schemaLocation="http://www.springframework.org/schema/rabbit
http://www.springframework.org/schema/rabbit/spring-rabbit-1.4.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.1.xsd">
<!-- 前台配置 -->
<!-- 定义RabbitMQ的连接工厂 -->
<rabbit:connection-factory id="connectionFactory"
host="${rabbitmq.ip}" port="${rabbitmq.port}" username="${rabbitmq.username}" password="${rabbitmq.password}"
virtual-host="${rabbitmq.vhost}" />
<!-- MQ的管理,包括队列、交换器等 -->
<rabbit:admin connection-factory="connectionFactory" />
<!-- 定义队列 -->
<rabbit:queue name="TOATAO-WEB-ITEM-QUEUE" auto-declare="true" durable="false"></rabbit:queue>
<bean id="itemMQController" class="com.taotao.rest.mq.ItemMQController"></bean>
<!-- 定义消费者监听队列-->
<rabbit:listener-container connection-factory="connectionFactory">
<rabbit:listener ref="itemMQController" method="execute" queue-names="TOATAO-WEB-ITEM-QUEUE"/>
</rabbit:listener-container>
<!-- 定义一个模板 -->
<rabbit:template id="taotaoItemTemplate" connection-factory="connectionFactory" exchange="TAOTAO-ITEM-EXCHANGE"></rabbit:template>
</beans>
创建一个消费者,当添加商品的时候,删除缓存中商品前缀的内容。
package com.taotao.rest.mq;
import java.util.Iterator;
import java.util.Set;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.taotao.rest.component.JedisClient;
/**
* 商品消息的处理
* @author fxq
*
*/
public class ItemMQController {
private static final ObjectMapper MAPPER = new ObjectMapper();
@Autowired
private JedisClient jedisClient;
@Value("${REDIS_ITEM_KEY}")
private String REDIS_ITEM_KEY;
@Value("${ITEM_BASE_INFO_KEY}")
private String ITEM_BASE_INFO_KEY;
public void execute(String msg)
{
//解析数据
JsonNode jsonNode;
try {
jsonNode = MAPPER.readTree(msg);
Long itemId = jsonNode.get("itemId").asLong();
//删除Redis中的缓存数据;
//jedisClient.del(REDIS_ITEM_KEY + ":" + itemId + ":"+ITEM_BASE_INFO_KEY);
Set<String> keys = jedisClient.keys(REDIS_ITEM_KEY);
Iterator<String> iterator = keys.iterator();
while (iterator.hasNext()) {
String key = (String) iterator.next();
System.out.println(key);
jedisClient.del(key);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
交换器和队列绑定
前台系统和后台系统,不直接调用,使用消息进行通信,实现解耦合与异步通信。