1. 程式人生 > >學習淘淘商城第六十六課(商品詳情快取的實現)

學習淘淘商城第六十六課(商品詳情快取的實現)

       上節課我們一起分析了下商品詳情快取策略,這節課我們一起實現商品詳情快取的新增。

       首先,我們要想清楚快取應該加到哪個工程當中,現在我們有兩個工程可以選擇,第一個工程是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工程,重啟後,我們再來訪問商品詳情頁面,第一次訪問是查詢資料庫,然後我們再重新整理頁面,第二次訪問就是查詢的快取了。快取中儲存的資訊如下圖所示。