最近在修改之前旧项目的时候,将spring-data-redis的版本升级到了2.X以上,查看了官方的文档之后,发现新版本有一些新特性和新的使用方法,这里记录整理一下,并附上自己在使用的时候遇到的一点坑。spring-data-redis最新版官方文档
<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}" /><!-- 连接池中最多可空闲链接个数,这里取值20,表示即使没有用数据库链接依然保持20个空闲链接 --><property name="maxIdle" value="${redis.pool.maxIdle}" /><!-- 最大等待时间,当没有可用连接时,连接池等待链接被归还的最大时间ms,超过时间就抛出异常 --><property name="maxWaitMillis" value="${redis.pool.maxWait}" /><!-- 在获取连接的时候检查链接的有效性 --><property name="testOnBorrow" value="${redis.pool.testOnBorrow}" /></bean><!-- 配置redis连接密码 --><bean id="redisPassword" class="org.springframework.data.redis.connection.RedisPassword"><constructor-arg name="thePassword" value="${redis.auth}"></constructor-arg></bean><!-- redis单机配置,地址等在这配置 2.0以上的新特性 --><bean id="redisStandaloneConfiguration" class="org.springframework.data.redis.connection.RedisStandaloneConfiguration"><property name="hostName" value="${redis.hostname}"/><property name="port" value="${redis.port}"/><property name="password" ref="redisPassword"/><property name="database" value="${redis.database}"/></bean><!--配置jedis链接工厂 spring-data-redis2.0中 建议改为构造器传入一个RedisStandaloneConfiguration 单机 RedisSentinelConfiguration 主从复制 RedisClusterConfiguration 集群--><bean id="connectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"><constructor-arg name="standaloneConfig" ref="redisStandaloneConfiguration"></constructor-arg></bean><!--手动设置 key 与 value的序列化方式--><!-- 序列化器:能够把我们储存的key与value做序列化处理的对象,是一个类似于converter的工具。 可以实现传入的java对象->redis可以识别的数据类型。 如:字符串。 默认的Serializer是StringRedisSerializer。 设定默认的序列化器是字符串序列化器,原因是redis可以存储的数据只有字符串和字节数组。 一般来说,我们代码中操作的数据对象都是java对象。 如果代码中,使用的数据载体就是字符串对象,那么使用Jackson2JsonRedisSerializer来做序列化器是否会有问题? 如果jackson插件的版本不合适,有错误隐患的话,可能将字符串数据转换为json字符串 ->{chars:[], bytes:[]} 使用StringRedisSerializer就没有这个问题。不处理字符串转换的。认为代码中操作的key和value都是字符串。 --><!-- 配置默认的序列化器 --><!-- keySerializer、valueSerializer 配置Redis中的String类型key与value的序列化器 --><!-- HashKeySerializer、HashValueSerializer 配置Redis中的Hash类型key与value的序列化器 --><bean id="keySerializer" class="org.springframework.data.redis.serializer.StringRedisSerializer"/><bean id="valueSerializer" class="org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer"/><!-- 配置jedis模板 --><bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate"><property name="connectionFactory" ref="connectionFactory"/><property name="keySerializer" ref="keySerializer"/><property name="valueSerializer" ref="valueSerializer"/><property name="hashKeySerializer" ref="keySerializer"/><property name="hashValueSerializer" ref="valueSerializer"/></bean></beans>
这里首先有几点注意的地方:
虽然RedisTemplate提供了很多操作的API,但毕竟只是API,这里将一些常用操作进行封装并加入logger日志记录,方便后面进行定位。
import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.data.redis.core.RedisTemplate;import org.springframework.data.redis.core.ValueOperations;import org.springframework.stereotype.Component;import java.util.Set;import java.util.concurrent.TimeUnit;/** * 对SDR接口进行封装的工具类,来对redis进行操作 */@ComponentpublicclassRedisUtil{private Logger logger= LoggerFactory.getLogger(this.getClass());@Autowiredprivate RedisTemplate<String, String> redisTemplate;/** * 缓存value * * @param key * @param value * @param time * @return */publicbooleancacheValue(String k, String value,long time){ String key= k;try{ ValueOperations<String, String> valueOperations= redisTemplate.opsForValue(); valueOperations.set(key, value);if(time>0){// 如果有设置超时时间的话 redisTemplate.expire(key, time, TimeUnit.SECONDS);}returntrue;}catch(Throwable e){ logger.error("缓存["+ key+"]失败, value["+ value+"] "+ e.getMessage());}returnfalse;}/** * 缓存value,没有设置超时时间 * * @param k * @param value * @return */publicbooleancacheValue(String k, String value){returncacheValue(k, value,-1);}/** * 判断缓存是否存在 * * @param key * @return */publicbooleancontainsKey(String key){try{return redisTemplate.hasKey(key);}catch(Throwable e){ logger.error("判断缓存是否存在时失败key["+ key+"]","err["+ e.getMessage()+"]");}returnfalse;}/** * 根据key,获取缓存 * * @param key * @return */public StringgetValue(String key){try{ ValueOperations<String, String> valueOperations= redisTemplate.opsForValue();return valueOperations.get(key);}catch(Throwable e){ logger.error("获取缓存时失败key["+ key+"]","err["+ e.getMessage()+"]");}return null;}/** * 移除缓存 * * @param key * @return */publicbooleanremoveValue(String key){try{ redisTemplate.delete(key);returntrue;}catch(Throwable e){ logger.error("移除缓存时失败key["+ key+"]","err["+ e.getMessage()+"]");}returnfalse;}/** * 根据前缀移除所有以传入前缀开头的key-value * * @param pattern * @return */publicbooleanremoveKeys(String pattern){try{ Set<String> keySet= redisTemplate.keys(pattern+"*"); redisTemplate.delete(keySet);returntrue;}catch(Throwable e){ logger.error("移除key["+ pattern+"]前缀的缓存时失败","err["+ e.getMessage()+"]");}returnfalse;}}
@Override@Transactionalpublic List<Area>getAreaLsit(){ String key= AREALISTKEY; List<Area> areaList= null;// 将list转换成string,利用jackson ObjectMapper objectMapper=newObjectMapper();if(!redisUtil.containsKey(key)){// 如果不存在这个缓存,就从数据库取 areaList= areaDao.queryArea();// 转换成string缓存 String jsonValue= null;try{ jsonValue= objectMapper.writeValueAsString(areaList);}catch(JsonProcessingException e){ e.printStackTrace(); logger.error("Json转换失败"+ e.toString());// 由于开启了事务,这里需要抛异常来触发回滚thrownewAreaOperationException(e.getMessage());}// 没有问题就缓存 redisUtil.cacheValue(key, jsonValue);}else{// 如果缓存中存在 String jsonValue= redisUtil.getValue(key);// 定义要将json转换成的类型 JavaType javaType= objectMapper.getTypeFactory().constructParametricType(ArrayList.class, Area.class);try{ areaList= objectMapper.readValue(jsonValue, javaType);}catch(JsonProcessingException e){ e.printStackTrace(); logger.error("Json转换失败"+ e.toString());// 由于开启了事务,这里需要抛异常来触发回滚thrownewAreaOperationException(e.getMessage());}}return areaList;}
1.首先遇到了一个版本不兼容的问题,一开始我用的版本如下
但是这两个版本会报一个找不到类的异常
NoClassDefFoundError: redis/clients/jedis/util/Pool
但是jar包中其实是有这个类的,查询了之后认为是版本不兼容的问题,这里我选择将Spring-Data-Redis降级,改成2.1.9之后就可以正常工作了。
Chile Address 版权所有
Powered by WordPress