1. 程式人生 > >SSM框架上集合Redis技術

SSM框架上集合Redis技術

為了完成畢業設計,將之前做的電商網站進行整改,目前需要整合上Redis,說明一下步驟,為到時候答辯做個筆記

前言:Redis簡介(簡單概述)

  • key-value儲存系統
  • 支援string,list連結串列,set集合,hash表
  • 符合原子性(成功則提交,失敗則回滾),要麼就完成,要麼就不完成,當作什麼都沒做,就是一定要完成一整套的操作,不可中途退出
  • 無需考慮多執行緒的併發問題
  • 快取在記憶體中

以上是一些簡述,我只用到這些,用到哪些寫哪些,沒用過的就沒有寫,(寫上也不一定會用,額,到時候再補充)

第一步:下載Redis(跟沒說一樣,但是這裡有關於Redis閃退的問題)

安裝好Redis後,開啟Redis服務有時會發現彈出一個視窗就閃退;

  • 目前已知的原因只發現一個:已經有Redis程序在啟動

       解決方案:工作管理員  ----->  找到Redis程序 -----> 結束關閉它  ----->  再次重啟

  • 還有一種情況閃退,有解決方案,但是還沒弄清問題產生的原因,所以先放上解決方案:

    更改redis資料夾中的 redis.windows.conf

    #bind 127.0.0.1 去掉#

    然後重啟Redis,或者CMD上 cd 到 Redis儲存路徑  執行  redis-server.exe redis.windows.conf

有的時候還是會報錯,講道理,這裡真不知道為什麼!!(百度了好久,看來還是不夠認真)

    如果還有錯,那就這樣:

    redis-cli.exe  ----->   shutdown   ----->    exit  ----->   edis-server.exe redis.windows.conf

    依次執行命令列,難受(希望有人告訴我),額,繼續整合步驟!

第二步:編寫Redis配置檔案(redis.properties、spring-redis.xml)

這裡說明一下redis.properties。後續會有SpringBoot的更換,換成yml的格式,先說一下,以免到時候忘掉

還有,我的配置檔案目錄形式如下:

將spring的配置檔案放入spring資料夾中,方便管理,在spring-dao.xml

中,這裡載入了redis.properites的配置:

<bean class="com.zhaoyu.shop.util.EncryptPropertyPlaceholderConfigurer">
	<property name="locations">
		<list>
			<value>classpath:jdbc.properties</value>
			<value>classpath:redis.properties</value>
		</list>
	</property>
	<property name="fileEncoding" value="UTF-8" />
</bean>

這裡一個是jdbc的配置,一個是redis的配置;

  • redis.properties的編寫:
redis.hostname=127.0.0.1
redis.port=6379
redis.database=0
redis.pool.maxActive=600
redis.pool.maxIdle=300
redis.pool.maxWait=3000
redis.pool.testOnBorrow=true

這裡不做過多的說明了,強調一下預設埠號 6379 (之前被問過,竟然忘了。。)

這個properties的編寫和資料庫連線(jdbc.properties)的一樣

  • spring-redis.xml的編寫
  • <beans xmlns="http://www.springframework.org/schema/beans"
    	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    	xmlns:context="http://www.springframework.org/schema/context"
    	xsi:schemaLocation="http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
            http://www.springframework.org/schema/context 
            http://www.springframework.org/schema/context/spring-context-3.2.xsd">
    	<!-- Redis連線池的設定 -->
    	<bean id="jedisPoolConfig"
    		class="redis.clients.jedis.JedisPoolConfig">
    		<!-- 控制一個pool可分配多少個Jedis例項 -->
    		<property name="maxTotal" value="${redis.pool.maxActive}" />
    		<!-- 連線池中最多可空閒maxIdle個連線,這裡取值為20,表示即使沒有資料庫連線時依然可以保持20個空閒的連線,而不被清除,隨時處於待命狀態 -->
    		<property name="maxIdle" value="${redis.pool.maxIdle}" />
    		<!-- 最大連線時間,當沒有可用連線時 -->
    		<property name="maxWaitMillis" value="${redis.pool.maxWait}" />
    		<!-- 在獲取連線時檢查有效性 -->
    		<property name="testOnBorrow"
    			value="${redis.pool.testOnBorrow}" />
    	</bean>
    	<!-- 建立Redis連線池,並作相關配置 -->
    	<bean id="jedisWritePool"
    		class="com.zhaoyu.shop.cache.JedisPoolWriper"
    		depends-on="jedisPoolConfig">
    		<constructor-arg index="0" ref="jedisPoolConfig" />
    		<constructor-arg index="1" value="${redis.hostname}" />
    		<constructor-arg index="2" value="${redis.port}"
    			type="int" />
    	</bean>
    	<bean id="jedisKeys" class="com.zhaoyu.shop.cache.JedisUtil$Keys"
    		scope="singleton">
    		<constructor-arg ref="jedisUtil"></constructor-arg>
    	</bean>
    	<bean id="jedisStrings"
    		class="com.zhaoyu.shop.cache.JedisUtil$Strings" scope="singleton">
    		<constructor-arg ref="jedisUtil"></constructor-arg>
    	</bean>
    	<bean id="jedisLists"
    		class="com.zhaoyu.shop.cache.JedisUtil$Lists" scope="singleton">
    		<constructor-arg ref="jedisUtil"></constructor-arg>
    	</bean>
    	<bean id="jedisSets" class="com.zhaoyu.shop.cache.JedisUtil$Sets"
    		scope="singleton">
    		<constructor-arg ref="jedisUtil"></constructor-arg>
    	</bean>
    	<bean id="jedisHash" class="com.zhaoyu.shop.cache.JedisUtil$Hash"
    		scope="singleton">
    		<constructor-arg ref="jedisUtil"></constructor-arg>
    	</bean>
    	<!-- 建立Redis工具類,封裝好Redis的連線並進行相關操作 -->
    	<bean id="jedisUtil" class="com.zhaoyu.shop.cache.JedisUtil"
    		scope="singleton">
    		<property name="jedisPool">
    			<ref bean="jedisWritePool" />
    		</property>
    	</bean>
    </beans>    

     說明一下上述的配置檔案:

  • 首先設定Redis連線池
<!-- Redis連線池的設定 -->
	<bean id="jedisPoolConfig"
		class="redis.clients.jedis.JedisPoolConfig">
		<!-- 控制一個pool可分配多少個Jedis例項 -->
		<property name="maxTotal" value="${redis.pool.maxActive}" />
		<!-- 連線池中最多可空閒maxIdle個連線,這裡取值為20,表示即使沒有資料庫連線時依然可以保持20個空閒的連線,而不被清除,隨時處於待命狀態 -->
		<property name="maxIdle" value="${redis.pool.maxIdle}" />
		<!-- 最大連線時間,當沒有可用連線時 -->
		<property name="maxWaitMillis" value="${redis.pool.maxWait}" />
		<!-- 在獲取連線時檢查有效性 -->
		<property name="testOnBorrow"
			value="${redis.pool.testOnBorrow}" />
	</bean>

           <property name="maxTotal" value="${redis.pool.maxActive}" />

           這裡有個value,和jdbc的連線池一樣,動態獲取redis.properties中的對應值

  • 建立Redis連線池,配置其屬性
<!-- 建立Redis連線池,並作相關配置 -->
	<bean id="jedisWritePool"
		class="com.zhaoyu.shop.cache.JedisPoolWriper"
		depends-on="jedisPoolConfig">
		<constructor-arg index="0" ref="jedisPoolConfig" />
		<constructor-arg index="1" value="${redis.hostname}" />
		<constructor-arg index="2" value="${redis.port}"
			type="int" />
	</bean>

            <constructor-arg index="2" value="${redis.port}"  type="int" />

            這裡的value和上面一樣

  • 建立Redis工具類,封裝好Redis的連線並進行相關操作
<!-- 建立Redis工具類,封裝好Redis的連線並進行相關操作 -->
	<bean id="jedisUtil" class="com.zhaoyu.shop.cache.JedisUtil"
		scope="singleton">
		<property name="jedisPool">
			<ref bean="jedisWritePool" />
		</property>
	</bean>
<bean id="jedisKeys" class="com.zhaoyu.shop.cache.JedisUtil$Keys"
		scope="singleton">
		<constructor-arg ref="jedisUtil"></constructor-arg>
	</bean>

	<bean id="jedisStrings"
		class="com.zhaoyu.shop.cache.JedisUtil$Strings" scope="singleton">
		<constructor-arg ref="jedisUtil"></constructor-arg>
	</bean>

	<bean id="jedisLists"
		class="com.zhaoyu.shop.cache.JedisUtil$Lists" scope="singleton">
		<constructor-arg ref="jedisUtil"></constructor-arg>
	</bean>

	<bean id="jedisSets" class="com.zhaoyu.shop.cache.JedisUtil$Sets"
		scope="singleton">
		<constructor-arg ref="jedisUtil"></constructor-arg>
	</bean>

	<bean id="jedisHash" class="com.zhaoyu.shop.cache.JedisUtil$Hash"
		scope="singleton">
		<constructor-arg ref="jedisUtil"></constructor-arg>
	</bean>

這塊的配置就是對於Redis的相關操作,分別為key,String,List,set,hash

現在配置檔案就完成了;

第三步:編寫redis連線池類(jedisWritePool)管理連線

這裡說到了jedis,我的理解就是jedis就是集成了redis的一些命令操作,封裝了redis的java客戶端。提供了連線池管理;

話句話說,jedis就是redis的客戶端;

jedisWritePool.java程式碼如下:

/**
 * 強指定redis的JedisPool介面建構函式,這樣才能在centos成功建立jedispool
 * 
 * @author xiangze
 *
 */
public class JedisPoolWriper {
	/**
	 * redis連線池物件
	 */
	private JedisPool jedisPool;

	public JedisPoolWriper(final JedisPoolConfig poolConfig, final String host,
			final int port) {
		try {
			jedisPool = new JedisPool(poolConfig, host, port);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	/**
	 * 獲取	redis連線池物件
	 * @return
	 */
	public JedisPool getJedisPool() {
		return jedisPool;
	}
	/**
	 * 注入redis連線池物件
	 * @param jedisPool
	 */
	public void setJedisPool(JedisPool jedisPool) {
		this.jedisPool = jedisPool;
	}

}

這裡就是實現構造方法,傳參連線池配置資訊,host地址,port埠號,然後通過get和set方法,實現對連線池的獲取和注入

第四步:編寫redis操作類(JedisUtil)操作Redis資料庫

JedisUtil.java:程式碼如下

public class JedisUtil {
	/** 操作Key的方法 */
	public Keys KEYS;
	/** 對儲存結構為String型別的操作 */
	public Strings STRINGS;
	/** 對儲存結構為List型別的操作 */
	public Lists LISTS;
	/** 對儲存結構為Set型別的操作 */
	public Sets SETS;
	/** 對儲存結構為HashMap型別的操作 */
	public Hash HASH;

	private JedisPool jedisPool;
	/**
	 * 從Jedis連線池中獲取redis連線池
	 * @return
	 */
	public JedisPool getJedisPool() {
		return jedisPool;
	}
    /**
	 * 設定redis連線池
	 * @param jedisPoolWriper
	 */
	public void setJedisPool(JedisPoolWriper jedisPoolWriper) {
		this.jedisPool = jedisPoolWriper.getJedisPool();
	}
    /**
	 * 從jedis連線池中獲取獲取jedis物件
	 * 
	 * @return
	 */
	public Jedis getJedis() {
		return jedisPool.getResource();
	}
}

這就是一個簡易的Jedis連線池工具類,比如像快取生存時間等一些其他功能沒有設定。。。

第五步:Redis快取技術實現

這裡就簡述一個我的商品類別一覽資訊獲取的redis快取技術

public class ShopCategoryServiceImpl implements ShopCategoryService {
	@Autowired
	private JedisUtil.Strings jedisStrings;
	@Autowired
	private JedisUtil.Keys jedisKeys;
	@Autowired
	private ShopCategoryDao shopCategoryDao;
	
	private static String SCLISTKEY = "shopcategorylist";

	@Override
	public List<ShopCategory> getFirstLevelShopCategoryList()
			throws IOException {
		//定義redis的key字首
		String key = SCLISTKEY;
		//定義接受物件
		List<ShopCategory> shopCategoryList = null;
		//定義jackson資料轉換操作類
		ObjectMapper mapper = new ObjectMapper();
		if (!jedisKeys.exists(key)) {
			ShopCategory shopCategoryCondition = new ShopCategory();
			// 當shopCategoryId不為空的時候,查詢的條件會變為 where parent_id is null
			shopCategoryCondition.setShopCategoryId(-1L);
			shopCategoryList = shopCategoryDao
					.queryShopCategory(shopCategoryCondition);
			String jsonString = mapper.writeValueAsString(shopCategoryList);
			jedisStrings.set(key, jsonString);
		} else {
			String jsonString = jedisStrings.get(key);
			JavaType javaType = mapper.getTypeFactory()
					.constructParametricType(ArrayList.class,
							ShopCategory.class);
			shopCategoryList = mapper.readValue(jsonString, javaType);
		}
		return shopCategoryList;
	}
}
  • 首先,注入JedisUtil工具類中的String,key欄位屬性
  • 定義一個key 為 SCLISTKEY,值是shopcategorylist
  • 判斷redis中是否有需要的資料,若為true,則查詢出資料,通過ObjectMapper類將ArrayList物件轉換成ShopCategory(商品類別)類的物件
  • 若redis中沒有相關資料,則從資料庫中查詢,並將其準換成(查出的資料是list)string,然後set到redis中對應的key值