下面我们来实现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)、下载安装包解压编译
(2)、编译完成后,在Src目录下,有四个可执行文件redis-server、redis-benchmark、redis-cli和redis.conf。然后拷贝到一个目录下$ 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
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服务(4)、用客户端测试下是否启动成功$ redis-server redis.conf
下面是Redis的Windows下安装,由于官网上不支持Redis安装,就有牛人造了一个能在windows环境下安装的,redis-2.4.5-win32-win64.zip,里面有32位和64位请根据自己的需求安装,下面是安装步骤:$ redis-cli redis> set uo bar OK redis> get uo "bar"
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的引用
redis.properties<?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.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
配置以及引用我们就大致配置好了,maven update 更新下<!-- Spring中引入其他配置文件 --> <import resource="classpath*:/spring/spring-redis.xml" />
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
6、编辑实现RedisTemplate的实现工具类(这一块想了解最好是去学习下RedisTemplate模板,和jdbcTemplate一样是Spring提供集成的模板)
CacheManage.java是我们的工具类相当于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; } }
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方式
很是费解;可能是哪里注解没有写对吧可能,在详细了解注解之后我再看下这个问题。。。
下面我们就测试下看看