上文我们一起分析了下如何在商品详情页面展示时添加缓存,本文我会带领大家一起实现商品详情页面展示时缓存的添加。
首先,我们要想清楚缓存应该加到哪个工程当中,现在我们有两个工程可以选择,第一个工程是taotao-item-web(商品详情展示工程),如果把缓存加到这个工程的话,由于该工程是个web工程,不被其它工程所共用,那么这块缓存的功能就只能被它自己使用。第二个工程是taotao-manager(商品服务工程),由于多个工程都依赖taotao-manager,因此缓存的功能可以被多个工程所共用。显然,我们应该选择第二个工程来添加缓存。要使用到Redis缓存技术,就要先添加Redis的依赖,如下图所示。
添加完依赖之后,taotao-manager-service工程中还需要添加对Redis操作的接口及实现类,由于我们在taotao-content-service工程中已经实现过了,因此我们只需要把taotao-content-service工程中关于jedis接口的包、接口及其实现类都拷贝过来,并将包名由原来的com.taotao.content.jedis改为com.taotao.jedis,如下图所示。
下面还需要把taotao-conent-service工程中applicationContext-redis.xml的配置文件给复制过来,如下图所示。
我们打开applicationContext-redis.xml文件,如下图所示,可以看到有单机版和集群版两种配置,现在我用的是单机版Redis,因此我们打开的是单机版的Redis配置。
在上文中我们制定了通过添加Redis缓存前缀来区分key的策略,而这个key我们是不能写死到代码当中的,应该配置到配置文件当中,还有就是商品的过期时间,这个也应该是可配置的,因此我们需要在taotao-manager-service工程中添加一个resource.properties配置文件,如下图所示。
resource.properties配置文件的内容如下:
# Redis中缓存商品信息的前缀
REDIS_ITEM_KEY=REDIS_ITEM
# 设置商品数据缓存的过期时间,默认5个小时
REDIS_ITEM_EXPIRE=18000
添加了配置文件,就要让Spring容器能够扫描到,因此我们打开applicationContext-dao.xml文件,把关于加载配置文件的配置由原来的db.properties修改为*.properties,这样properties目录下的所有配置文件都可以被扫描到了。
下面我们真正开始写缓存代码,在ItemServiceImpl类中的获取商品基本信息方法(getItemById)和获取商品描述信息方法(getItemDesc)中添加缓存代码,添加完缓存后,ItemServiceImpl类的所有代码如下:
/**
* 商品管理Service
* Title: ItemServiceImpl
* Description:
* Company: www.itcast.cn
* @version 1.0
*/
@Service
public class ItemServiceImpl implements ItemService {
@Autowired
private TbItemMapper itemMapper;
@Autowired
private TbItemDescMapper itemDescMapper;
@Autowired
private JmsTemplate jmsTemplate;
@Resource(name="topicDestination")
private Topic topicDestination;
@Autowired
private JedisClient jedisClient;
@Value("${REDIS_ITEM_KEY}")
private String REDIS_ITEM_KEY;
@Value("${REDIS_ITEM_EXPIRE}")
private Integer REDIS_ITEM_EXPIRE;
@Override
public TbItem getItemById(long itemId) {
// 先查询缓存
try {
String json = jedisClient.get(REDIS_ITEM_KEY + ":" + itemId + ":BASE");
if (StringUtils.isNotBlank(json)) {
TbItem tbItem = JsonUtils.jsonToPojo(json, TbItem.class);
return tbItem;
}
} catch (Exception e) {
e.printStackTrace();
}
// 如果缓存中没有命中,那么查询数据库
TbItem item = itemMapper.selectByPrimaryKey(itemId);
// 添加到缓存
try {
jedisClient.set(REDIS_ITEM_KEY + ":" + itemId + ":BASE", JsonUtils.objectToJson(item));
// 设置过期时间
jedisClient.expire(REDIS_ITEM_KEY + ":" + itemId + ":BASE", REDIS_ITEM_EXPIRE);
} catch (Exception e) {
e.printStackTrace();
}
return item;
}
@Override
public TbItemDesc getItemDesc(long itemId) {
// 先查询缓存
try {
String json = jedisClient.get(REDIS_ITEM_KEY + ":" + itemId + ":DESC");
if (StringUtils.isNotBlank(json)) {
TbItemDesc tbItemDesc = JsonUtils.jsonToPojo(json, TbItemDesc.class);
return tbItemDesc;
}
} catch (Exception e) {
e.printStackTrace();
}
// 如果缓存中没有命中,那么查询数据库
TbItemDesc itemDesc = itemDescMapper.selectByPrimaryKey(itemId);
// 添加到缓存
try {
jedisClient.set(REDIS_ITEM_KEY + ":" + itemId + ":DESC", JsonUtils.objectToJson(itemDesc));
// 设置过期时间
jedisClient.expire(REDIS_ITEM_KEY + ":" + itemId + ":DESC", REDIS_ITEM_EXPIRE);
} catch (Exception e) {
e.printStackTrace();
}
return itemDesc;
}
@Override
public EasyUIDataGridResult getItemList(int page, int rows) {
// 分页处理
PageHelper.startPage(page, rows);
// 执行查询
TbItemExample example = new TbItemExample();
List list = itemMapper.selectByExample(example);
// 创建返回结果对象
EasyUIDataGridResult result = new EasyUIDataGridResult();
result.setRows(list);
// 取总记录数
PageInfo pageInfo = new PageInfo(list);
result.setTotal(pageInfo.getTotal());
return result;
}
@Override
public TaotaoResult addItem(TbItem item, String desc) {
// 先生成商品id
final long itemId = IDUtils.genItemId();
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);
// 商品添加完成后发送一个MQ消息
jmsTemplate.send(topicDestination, new MessageCreator() {
@Override
public Message createMessage(Session session) throws JMSException {
// 创建一个消息对象
// 要在匿名内部类访问局部变量itemId,itemId需要用final修饰
TextMessage message = session.createTextMessage(itemId + "");
return message;
}
});
return TaotaoResult.ok();
}
}
其中新注入的内容如下图红色大框框标注所示。
代码写好了,下面我们便要进行测试,重启taotao-manager这个工程,重启成功后,我们再来访问商品详情页面,第一次访问是查询数据库,然后我们再刷新页面,第二次访问就是查询的缓存了,缓存中存储的信息如下图所示。