Spring集成Redis緩存實現

下面我們來實現Spring集成Redis緩存如何實現的。一般有一下幾個步驟

 

Spring集成Redis的幾個步驟:
		1、搭建Redis 服務器環境(windows環境下搭建\Linux環境下搭建)
		2、啓動Redis服務
		3、maven項目中添加依賴
		4、配置Spring對Redis相關bean的引用
		5、配置Redis基本屬性
		6、編輯實現RedisTemplate的實現工具類
		7、遇到的問題

1、搭建Redis服務器環境

     在Redis官網上下載的包redis-4.0.1.tar,只能在linux環境下搭建,無法在windows環境下使用。但是呢我們只有windows環境,想着弄個虛擬機來模擬,但是感覺有點費事兒麻煩,主要還是電腦配置有點低,所以嘿嘿,就想辦法找了個能在windows環境下實現Redis服務的辦法。廢話不多說先說下Linux換下如何裝redis

Linux:(1)、下載安裝包解壓編譯

         
$ wget http://download.redis.io/releases/redis-2.8.3.tar.gz
$ tar xzf redis-2.8.3.tar.gz
$ cd redis-2.8.3
$ make


  (2)、編譯完成後,在Src目錄下,有四個可執行文件redis-server、redis-benchmark、redis-cli和redis.conf。然後拷貝到一個目錄下
mkdir /usr/redis
cp redis-server  /usr/redis
cp redis-benchmark /usr/redis
cp redis-cli  /usr/redis
cp redis.conf  /usr/redis
cd /usr/redis


 (3)、開始啓動Redis服務

$ redis-server   redis.conf

(4)、用客戶端測試下是否啓動成功

$ redis-cli
redis> set uo bar
OK
redis> get uo
"bar"
下面是Redis的Windows下安裝,由於官網上不支持Redis安裝,就有牛人造了一個能在windows環境下安裝的,redis-2.4.5-win32-win64.zip,裏面有32位和64位請根據自己的需求安裝,下面是安裝步驟:

1、下載包redis-2.4.5-win32-win64.zip.鏈接:https://pan.baidu.com/s/1pL5gywV

2、開始解壓

在d盤下新建d:\lamp\redis目錄文件夾。
	1、把64位包裏的文件全部拷貝到redis目錄下
	2、接下來在cmd控制檯切換到redis目錄下,或者在redis目錄下按shift+右擊
	   用命令行打開
	3、redis-server.exe redis.conf
	4、 此時表示服務器開始成功,一定不要關閉該控制檯,否則後面就無法連接成功了!!!


3、鏈接測試下

1、重新打開一個新的cmd控制檯切換到redis目錄
	2、執行: redis-cli.exe -h 127.0.0.1 -p 6379
	
	此時,表示redis連接成功了。我們可以在redis.conf中配置
	
    (1)port 6379 //端口
    (2)bind 127.0.0.1 //環回網絡

	此時,就不用添加-h -p參數了,使用redis-cli.exe即可連接成功

這樣我們就已經在windows環境下搭建好redis服務器了,第一個cmd要一直保留,第二個cmd只是測試用,關掉後不影響redis服務

---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

3、在Maven+Spring項目中添加相關依賴

<!-- redis 依賴開始 -->
		<dependency>
			<groupId>redis.clients</groupId>
			<artifactId>jedis</artifactId>
			<version>2.9.0</version>
		</dependency>
		<dependency>
			<groupId>org.springframework.data</groupId>
			<artifactId>spring-data-redis</artifactId>
			<version>1.6.1.RELEASE</version>
		</dependency>
		
		<!-- redis 依賴結束 -->

注意Spring-data-redis版本問題,一開始用的是最新的版本2.4.0啓動一直報版本太高不適配,具體哪裏不適配沒找到。我們可以用稍微低版本的穩定版的就可以。

--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

4、配置Spring對Redis相關bean的引用

<?xml version="1.0" encoding="UTF-8"?>
<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
        classpath:org/springframework/beans/factory/xml/spring-beans-4.2.xsd">
	<!-- ↓↓↓↓↓redis 的配置信息 ↓↓↓↓↓ -->
	<bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
		<!-- 最大連接數 -->
		<property name="maxTotal" value="${redis.pool.maxTotal}"></property>
		<!-- 最大空閒數:空閒鏈接數大於maxIdle時,將進行回收 -->
		<property name="maxIdle" value="${redis.pool.maxIdle}"></property>
		<!-- 最大等待時間:單位ms -->
		<property name="maxWaitMillis" value="${redis.pool.maxWait}"></property>
		<!-- 逐出連接的最小空閒時間 :單位ms -->
		<property name="minEvictableIdleTimeMillis" value="${redis.pool.minEvictableIdleTimeMillis}"></property>
		<!-- 每次逐出檢查時 逐出的最大數目 -->
		<property name="numTestsPerEvictionRun" value="${redis.pool.numTestsPerEvictionRun}"></property>
		<!-- 逐出掃描的時間間隔(毫秒) -->
		<property name="timeBetweenEvictionRunsMillis" value="${redis.pool.timeBetweenEvictionRunsMillis}"></property>
	</bean>
	<!-- ↑↑↑↑↑redis 的配置信息↑↑↑↑↑ -->
	<!-- ↓↓↓↓↓redis 服務器中心 ↓↓↓↓↓ -->
	<bean id="jedisConnectionFactory"
		class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"
		destroy-method="destroy">
		<property name="poolConfig" ref="jedisPoolConfig"></property>
		<!-- Redis服務器地址 -->
		<property name="hostName" value="${redis.host}"></property>
		<!-- 服務端口 -->
		<property name="port" value="${redis.port}"></property>
		<!-- 授權密碼 -->
		<property name="password" value=""></property>
		<!-- 超時時間:單位ms -->
		<property name="timeout" value="${redis.timeout}"></property>
		<!--啓用用戶線程池 -->
		<property name="usePool" value="true"></property>
	</bean>
	<!-- ↑↑↑↑↑redis 服務器中心 ↑↑↑↑↑ -->
	<!-- ☂☂☂redis操作模板,面向對象的模板☂ ☂☂ -->
	<bean id="jedisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
		<property name="connectionFactory" ref="jedisConnectionFactory"></property>
		<property name="keySerializer">
			<bean
				class="org.springframework.data.redis.serializer.StringRedisSerializer" />
		</property>
		<property name="valueSerializer">
			<bean
				class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer" />
		</property>
	</bean>
	<!-- ♨♨♨redis操作模板,面向對象的模板♨♨♨ -->
	<bean id="redisCache" class="com.zpl.cache.rediscache.RedisCache">
		<property name="jedisTemplate" ref="jedisTemplate"></property>
	</bean>
	<bean id="cacheManage" class="com.zpl.cache.CacheManage">
		<property name="cache" ref="redisCache"></property>
	</bean>
</beans>
redis.properties

redis.host=127.0.0.1
redis.port=6379
redis.timeout=3000
#redis.password=123//沒有密碼就不用設置
redis.pool.maxTotal=200
redis.pool.maxIdle=20
redis.pool.minIdle=5
redis.pool.maxWait=15000
redis.pool.minEvictableIdleTimeMillis=30000
redis.pool.numTestsPerEvictionRun=3
redis.pool.timeBetweenEvictionRunsMillis=60000
redis.pool.testOnBorrow=true

dispatcher-servlet-xml應用spring-redis.xml

<!-- Spring中引入其他配置文件 -->
    <import resource="classpath*:/spring/spring-redis.xml" />
配置以及引用我們就大致配置好了,maven update 更新下
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

6、編輯實現RedisTemplate的實現工具類(這一塊想了解最好是去學習下RedisTemplate模板,和jdbcTemplate一樣是Spring提供集成的模板)

package com.zpl.cache.rediscache;

import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.serializer.support.SerializingConverter;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.RedisSerializer;

import com.zpl.cache.Cache;

/**
 * 實現緩存功能
 * <p>
 * 通過jedisTemplate來實現將我們的數據以及數據結構保存到緩存redis中, <br>
 * 這個是由Spring封裝的模板
 * 
 * @author zhangpengliang
 *
 */
public class RedisCache implements Cache {
	private RedisTemplate<String, Object> jedisTemplate;
	@Value("${redis.host}")
	private String redishost;

	/**
	 * 按鍵值的方式存儲
	 * 
	 * @param key
	 *            鍵
	 * @param value
	 *            值
	 */
	public void put(String key, Object value) {
		jedisTemplate.opsForValue().set(key, value);
	}

	@Override
	public void put(String key, Object value, int timeout) {
		jedisTemplate.opsForValue().set(key, value, timeout, TimeUnit.SECONDS);// TimeUnit.SECONDS秒
	}

	@Override
	public Object get(String key) {
		return jedisTemplate.opsForValue().get(key);
	}

	/**
	 * 獲取key對應的值,並轉換爲指定類型
	 * 
	 * @param key
	 *            鍵
	 * @param requiredType
	 *            類型
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public <T> T get(String key, Class<T> requiredType) {

		return (T) jedisTemplate.opsForValue().get(key);
	}

	/**
	 * 移出
	 * 
	 * @param key
	 */
	public void remove(String key) {
		jedisTemplate.delete(key);
	}

	@Override
	public Set<String> keys(String pattern) {
		return jedisTemplate.keys(pattern);
	}

	@Override
	public void putHash(String key, Map<?, ?> value) {
		jedisTemplate.opsForHash().putAll(key, value);
	}

	/**
	 * 以Hash的方式將對象存入緩存中
	 * 
	 * @param key
	 *            緩存中的key
	 * @param hashKey
	 *            hash中的key
	 * @param value
	 *            hash中的value
	 */
	public void putHash(String key, String hashKey, Object value) {
		jedisTemplate.opsForHash().put(key, hashKey, value);

	}

	@Override
	public Map<?, Object> getHash(String key) {
		// TODO Auto-generated method stub
		return jedisTemplate.opsForHash().entries(key);
	}

	@Override
	public Object getHash(String key, String hashKey) {
		// TODO Auto-generated method stub
		return jedisTemplate.opsForHash().get(key, hashKey);
	}

	@SuppressWarnings("unchecked")
	@Override
	public <T> T getHash(String key, String hashKey, Class<T> requiredType) {
		// TODO Auto-generated method stub
		return (T) jedisTemplate.opsForHash().get(key, hashKey);
	}

	@Override
	public void removeHash(String key) {
		jedisTemplate.opsForHash().delete(key);

	}

	@Override
	public void removeHash(String key, Object... hashKeys) {
		jedisTemplate.opsForHash().delete(key, hashKeys);

	}

	@Override
	public void put(final Map<String, ?> data) {
		RedisCallback<Map<String, ?>> pipCallBack = new RedisCallback<Map<String, ?>>() {
			@Override
			public Map<String, ?> doInRedis(RedisConnection connection) throws DataAccessException {
				connection.openPipeline();
				RedisSerializer<String> rs = jedisTemplate.getStringSerializer();
				SerializingConverter sc = new SerializingConverter();
				for (String key : data.keySet()) {
					connection.append(rs.serialize(key), sc.convert(data.get(key)));
				}
				connection.closePipeline();
				return null;
			}
		};
		jedisTemplate.execute(pipCallBack);
	}

	public boolean zAdd(String key, Object value) {
		return this.zAdd(key, value, System.currentTimeMillis());
	}

	public boolean zAdd(String key, Object value, double score) {
		return jedisTemplate.opsForZSet().add(key, value, score);
	}

	public Set<Object> zGetByRank(String key, long start, long end) {
		return jedisTemplate.opsForZSet().range(key, start, end);
	}

	public Set<Object> zGetByScore(String key, double min, double max) {
		return jedisTemplate.opsForZSet().rangeByScore(key, min, max);
	}

	public Long zRemove(String key, Object... values) {
		return jedisTemplate.opsForZSet().remove(key, values);
	}

	public Long zRemoveByRank(String key, long start, long end) {
		return jedisTemplate.opsForZSet().removeRange(key, start, end);
	}

	public Long zRemoveByScore(String key, double min, double max) {
		return jedisTemplate.opsForZSet().removeRangeByScore(key, min, max);
	}

	public RedisTemplate<String, Object> getJedisTemplate() {
		return jedisTemplate;
	}

	public void setJedisTemplate(RedisTemplate<String, Object> jedisTemplate) {
		this.jedisTemplate = jedisTemplate;
	}

}
CacheManage.java是我們的工具類相當於
package com.zpl.cache;

import java.util.Map;
import java.util.Set;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;

/**
 * 緩存管理工具
 * @author zhangpengliang
 *
 */
public class CacheManage {
	private static Cache cache;
	
	public static Cache getCache() {
		return cache;
	}
	@Autowired
	public static void setCache(Cache cache) {
		CacheManage.cache = cache;
	}
	/*public CacheManage(Cache cache){
		CacheManage.cache=cache;
	}*/
	/**
	 * 按鍵值的方式存儲
	 * @param key
	 * @param value
	 */
	public static void put(String key, Object value) {
		CacheManage.cache.put(key, value);
	}
	/**
	 * 按鍵值方式存儲,可以設置超時
	 * 
	 * @param key
	 *            鍵
	 * @param value
	 *            值
	 * @param timeout
	 *            超時時間
	 */
	public static void put(String key, Object value, int timeout) {
		CacheManage.cache.put(key, value, timeout);
	}
	
	/**
	 * 獲取key對應的值
	 * 
	 * @param key
	 *            鍵
	 * @return
	 */
	public static Object get(String key){
		return CacheManage.cache.get(key);
	}
	/**
	 * 獲取key對應的值,並轉換爲指定類型
	 * 
	 * @param key
	 *            鍵
	 * @param requiredType
	 *            類型
	 * @return
	 */
	public static <T> T get(String key,Class<T> requiredType){
		return CacheManage.cache.get(key, requiredType);
	}
	/**
	 * 移除對應值
	 * 
	 * @param key
	 *            鍵
	 */
	public static void remove(String key){
		CacheManage.cache.remove(key);
	}
	
	//爲手動
	public static Set<String> keys(String pattern) {
		return CacheManage.cache.keys(pattern);
	}

	public static void putHash(String key, Map<?, ?> value) {
		CacheManage.cache.putHash(key, value);
	}

	public static void putHash(String key, String hashKey, Object value) {
		CacheManage.cache.putHash(key, hashKey, value);
	}

	public static Map<?, ?> getHash(String key) {
		return CacheManage.cache.getHash(key);
	}

	public static Object getHash(String key, String hashKey) {
		return CacheManage.cache.getHash(key, hashKey);
	}

	public static <T> T getHash(String key, String hashKey, Class<T> requiredType) {
		return CacheManage.cache.getHash(key, hashKey, requiredType);
	}

	public static void removeHash(String key) {
		CacheManage.cache.removeHash(key);
	}

	public static void removeHash(String key, Object... hashKeys) {
		CacheManage.cache.removeHash(key, hashKeys);
	}

	/**
	 * 使用pipeline的方式插入批量數據
	 * <p>
	 * 使用get相關方法獲取,請勿使用getHash方法取值
	 * 
	 * @param data
	 *            需要被插入的批量數據
	 */
	public static void put(Map<String, ?> data) {
		CacheManage.cache.put(data);
	}

	public boolean zAdd(String key, Object value) {
		return CacheManage.cache.zAdd(key, value);
	}

	public boolean zAdd(String key, Object value, double score) {
		return CacheManage.cache.zAdd(key, value, score);
	}

	public Set<Object> zGetByRank(String key, long start, long end) {
		return CacheManage.cache.zGetByRank(key, start, end);
	}

	public Set<Object> zGetByScore(String key, double min, double max) {
		return CacheManage.cache.zGetByScore(key, min, max);
	}

	public Long zRemove(String key, Object... values) {
		return CacheManage.cache.zRemove(key, values);
	}

	public Long zRemoveByRank(String key, long start, long end) {
		return CacheManage.cache.zRemoveByRank(key, start, end);
	}

	public Long zRemoveByScore(String key, double min, double max) {
		return CacheManage.cache.zRemoveByScore(key, min, max);
	}
	
	
	
}

7、遇到的問題:

使用註解無法裝配實例。如:cacheManage中的Cache實例沒法裝配解決辦法--添加set 方法並在xml裏添加配置

在cacheMange中用註解無法獲取到cache接口的實例。

但是我用xml的方式就可以實現:去掉上面的註解用下面的xml方式



很是費解;可能是哪裏註解沒有寫對吧可能,在詳細瞭解註解之後我再看下這個問題。。。


下面我們就測試下看看





發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章