學習淘淘商城第六十六課(商品詳情快取的實現)
上節課我們一起分析了下商品詳情快取策略,這節課我們一起實現商品詳情快取的新增。
首先,我們要想清楚快取應該加到哪個工程當中,現在我們有兩個工程可以選擇,第一個工程是taotao-item-web(商品詳情工程),如果把快取加到這個工程的話,由於該工程是個web工程,不被其它工程所共用,那麼這塊快取的功能只能被它自己使用。第二個工程是taotao-manager(商品工程),由於多個工程都依賴taotao-manager,因此快取的功能可以被多個工程所共用。顯然,我們應該選擇第二個工程來新增快取。
要使用Redis快取技術,就要先新增Redis的依賴,如下圖所示。
依賴程式碼如下:
<!-- Redis客戶端 -->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
新增完依賴之後,需要新增對Redis操作的介面及實現類,由於我們在taotao-content工程已經實現過了,因此我們只需要把taotao-content-interface工程中關於jedis介面的包及介面類拷貝過來,然後把taotao-content-service工程中jedis的包及實現類拷貝過來,如下圖所示。
下面還需要把taotao-conent-service工程中關於jedis的配置檔案給複製過來,如下圖所示。
我們開啟applicationContext-jedis.xml檔案,如下圖所示,可以看到有單機版和叢集版兩種配置,現在我用的是單機版redis,因此我們開啟的是單機版的redis配置。
在上節課中我們制定了通過新增redis快取字首來區分key的策略,而這個key我們是不能寫死到程式碼當中的,應該配置到配置檔案當中,還有就是商品的過期時間,這個也應該是可配置的,因此我們需要在taotao-manager-service工程新增一個配置檔案resource.properties,如下圖所示。不過需要提醒的是,剛建的配置檔案預設編碼是iso8859-1,是不能寫中文註釋的,因此為了能夠寫中文註釋,我們把該檔案的編碼改成UTF-8。
配置檔案中的內容如下:
#商品資料在redis中快取的字首
ITEM_INFO=ITEM_INFO
#商品快取的過期時間,預設設定成一天,可以根據實際情況修改
ITEM_EXPIRE=86400
添加了配置檔案,要讓Spring容器能夠掃描到,因此我們開啟applicationContext-dao.xml檔案,把關於載入配置檔案的配置由原來的db.properties修改為*.properties,這樣properties目錄下的所有配置檔案都可以被掃描到了。
下面我們真正開始寫快取程式碼,在ItemServiceImpl類中的獲取商品基本資訊方法(getItemById)和獲取商品描述資訊方法(getItemDescById)中新增快取程式碼,新增完快取後,ItemServiceImplement類的所有程式碼如下:
package com.taotao.service.impl;
import java.util.Date;
import java.util.List;
import javax.annotation.Resource;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.Session;
import javax.jms.TextMessage;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.jms.core.MessageCreator;
import org.springframework.stereotype.Service;
import com.alibaba.fastjson.JSON;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.taotao.common.pojo.EasyUIDataGridResult;
import com.taotao.common.pojo.TaotaoResult;
import com.taotao.common.utils.IDUtils;
import com.taotao.jedis.service.JedisClient;
import com.taotao.mapper.TbItemDescMapper;
import com.taotao.mapper.TbItemMapper;
import com.taotao.pojo.TbItem;
import com.taotao.pojo.TbItemDesc;
import com.taotao.pojo.TbItemExample;
import com.taotao.service.ItemService;
@Service
public class ItemServiceImpl implements ItemService {
@Autowired
private TbItemMapper itemMapper;
@Autowired
private TbItemDescMapper itemDescMapper;
@Autowired
private JedisClient jedisClient;
@Value("${ITEM_INFO}")
private String ITEM_INFO;
@Value("${ITEM_EXPIRE}")
private Integer ITEM_EXPIRE;
@Autowired
private JmsTemplate jmsTemplate;
@Resource(name="itemAddTopic")
private Destination destination;
@Override
public TbItem getItemById(long itemId) {
//查詢資料庫之前先查詢快取
try {
String json = jedisClient.get(ITEM_INFO+":"+itemId+":BASE");
if(!StringUtils.isBlank(json)){
//把json轉換成物件
return JSON.parseObject(json, TbItem.class);
}
} catch (Exception e) {
e.printStackTrace();
}
TbItem tbItem = itemMapper.selectByPrimaryKey(itemId);
//把查詢結果新增到快取
try {
//把查詢結果新增到快取
jedisClient.set(ITEM_INFO+":"+itemId+":BASE", JSON.toJSONString(tbItem));
//設定過期時間,提高快取的利用率
jedisClient.expire(ITEM_INFO+":"+itemId+":BASE", ITEM_EXPIRE);
} catch (Exception e) {
e.printStackTrace();
}
return tbItem;
}
@Override
public TbItemDesc getItemDescById(long itemId) {
//查詢資料庫之前先查詢快取
try {
String json = jedisClient.get(ITEM_INFO+":"+itemId+":DESC");
if(!StringUtils.isBlank(json)){
//把json轉換成物件
return JSON.parseObject(json, TbItemDesc.class);
}
} catch (Exception e) {
e.printStackTrace();
}
TbItemDesc tbItemDesc = itemDescMapper.selectByPrimaryKey(itemId);
//把查詢結果新增到快取
try {
//把查詢結果新增到快取
jedisClient.set(ITEM_INFO+":"+itemId+":DESC", JSON.toJSONString(tbItemDesc));
//設定過期時間,提高快取的利用率
jedisClient.expire(ITEM_INFO+":"+itemId+":DESC", ITEM_EXPIRE);
} catch (Exception e) {
e.printStackTrace();
}
return tbItemDesc;
}
@Override
public EasyUIDataGridResult getItemList(int page, int rows) {
//設定分頁資訊
PageHelper.startPage(page, rows);
//執行查詢
TbItemExample example = new TbItemExample();
List<TbItem> list = itemMapper.selectByExample(example);
//獲取查詢結果
PageInfo<TbItem> pageInfo = new PageInfo<>(list);
EasyUIDataGridResult result = new EasyUIDataGridResult();
result.setRows(list);
result.setTotal(pageInfo.getTotal());
//返回結果
return result;
}
@Override
public TaotaoResult createItem(TbItem tbItem, String desc) throws Exception{
//生成商品ID
long itemId = IDUtils.genItemId();
//補全item的屬性
tbItem.setId(itemId);
//商品狀態,1-正常,2-下架,3-刪除
tbItem.setStatus(((byte) 1));
tbItem.setCreated(new Date());
tbItem.setUpdated(new Date());
itemMapper.insert(tbItem);
//新增商品描述
insertItemDesc(itemId, desc);
//傳送activemq訊息
jmsTemplate.send(destination,new MessageCreator() {
@Override
public Message createMessage(Session session) throws JMSException {
TextMessage textMessage = session.createTextMessage(itemId+"");
return textMessage;
}
});
return TaotaoResult.ok();
}
//新增商品描述
private void insertItemDesc(long itemId,String desc){
//建立一個商品描述表對應的pojo
TbItemDesc itemDesc = new TbItemDesc();
//補全pojo的屬性
itemDesc.setItemId(itemId);
itemDesc.setItemDesc(desc);
itemDesc.setCreated(new Date());
itemDesc.setUpdated(new Date());
//向商品描述表插入資料
itemDescMapper.insert(itemDesc);
}
}
其中新注入的內容如下圖藍色標註所示。
程式碼寫好了,下面我們便要進行測試,由於我們修改了taotao-manager工程,最好我們重新打包taotao-manager工程到本地Maven倉庫,然後我們重啟taotao-manager工程,重啟後,我們再來訪問商品詳情頁面,第一次訪問是查詢資料庫,然後我們再重新整理頁面,第二次訪問就是查詢的快取了。快取中儲存的資訊如下圖所示。