下面我們來實現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方式
很是費解;可能是哪裏註解沒有寫對吧可能,在詳細瞭解註解之後我再看下這個問題。。。
下面我們就測試下看看