项目中需要用到redis,主要用来作为缓存,redis的客户端有两种实现方式,一是可以直接调用jedis来实现,二是可以使用spring data redis,通过spring的封装来调用。应该使用哪一个呢?基于当前版本spring data redis 1.0.1和jedis 2.0.0,分析如下:
Spring Data Redis 1.0.1 优点
1.对具体redis客户端做了封装,客户端可在jedis,jredis,rjc等Java客户端中做出选择和切换
2.用template对调用做了封装,省去了建立连接,释放连接等繁琐代码。
3.对对象的序列化也可自由选择工具。
4.提供对spring cache的支持,可用注解实现Cache —— 但是无法设定缓存失效时间。
Jedis 2.0.0优点
1.可用到Jedis本身提供的更多的特性,比如sharded,比如Masater/Slaver。
2.Jedis经过我们之前项目的使用,对其稳定性有验证。
1.在Maven中添加依赖
1 <properties> 2 <spring.data.redis.version>1.6.0.RELEASE</spring.data.redis.version> 3 <jedis.version>2.9.0</jedis.version> 4 </properties> 5 <dependencies> 6 <dependency> 7 <groupId>org.springframework.data</groupId> 8 <artifactId>spring-data-redis</artifactId> 9 <version>${spring.data.redis.version}</version> 10 </dependency> 11 <dependency> 12 <groupId>redis.clients</groupId> 13 <artifactId>jedis</artifactId> 14 <version>${jedis.version}</version> 15 </dependency> 16 </dependencies>
2. 配置文件
1 import java.util.HashMap; 2 import java.util.Map; 3 4 import org.springframework.beans.factory.annotation.Qualifier; 5 import org.springframework.beans.factory.annotation.Value; 6 import org.springframework.cache.annotation.CachingConfigurerSupport; 7 import org.springframework.cache.annotation.EnableCaching; 8 import org.springframework.context.annotation.Bean; 9 import org.springframework.context.annotation.Configuration; 10 import org.springframework.context.annotation.DependsOn; 11 import org.springframework.core.env.MapPropertySource; 12 import org.springframework.data.redis.connection.RedisClusterConfiguration; 13 import org.springframework.data.redis.connection.RedisConnectionFactory; 14 import org.springframework.data.redis.connection.jedis.JedisConnectionFactory; 15 import org.springframework.data.redis.core.RedisTemplate; 16 import org.springframework.data.redis.core.StringRedisTemplate; 17 import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer; 18 import org.springframework.data.redis.serializer.StringRedisSerializer; 19 20 import com.gta.train.platform.common.util.SpringContextHolder; 21 22 import redis.clients.jedis.JedisPoolConfig; 23 24 @Configuration 25 @EnableCaching 26 public class RedisClusterConfig extends CachingConfigurerSupport { 27 28 private JedisPoolConfig poolConfig(int maxIdle, int maxTotal, long maxWaitMillis, boolean testOnBorrow, 29 boolean testOnReturn) { 30 JedisPoolConfig jedisPoolConfig = new JedisPoolConfig(); 31 jedisPoolConfig.setMaxIdle(maxIdle); 32 jedisPoolConfig.setMaxTotal(maxTotal); 33 jedisPoolConfig.setMaxWaitMillis(maxWaitMillis); 34 jedisPoolConfig.setTestOnBorrow(testOnBorrow); 35 jedisPoolConfig.setTestOnReturn(testOnReturn); 36 return jedisPoolConfig; 37 } 38 39 private RedisClusterConfiguration redisCluterConfig(String clusterNodes, Long timeout, int redirects, 40 String password) { 41 Map<String, Object> source = new HashMap<String, Object>(); 42 source.put("spring.redis.cluster.nodes", clusterNodes); 43 // source.put("spring.redis.cluster.timeout", timeout); 44 // source.put("spring.redis.cluster.max-redirects", redirects); 45 return new RedisClusterConfiguration(new MapPropertySource("RedisClusterConfiguration", source)); 46 } 47 48 @Bean(name = "redisConnectionFactory") 49 public JedisConnectionFactory redisConnectionFactory(@Value("${spring.redis.cluster.maxIdle}") int maxIdle, 50 @Value("${spring.redis.cluster.maxTotal}") int maxTotal, 51 @Value("${spring.redis.cluster.maxWaitMillis}") long maxWaitMillis, 52 @Value("${spring.redis.cluster.testOnBorrow}") boolean testOnBorrow, 53 @Value("${spring.redis.cluster.testOnReturn}") boolean testOnReturn, 54 @Value("${spring.redis.cluster.nodes}") String clusterNodes, 55 @Value("${spring.redis.cluster.timeout}") Long timeout, 56 @Value("${spring.redis.cluster.max-redirects}") int redirects, 57 @Value("${spring.redis.cluster.password}") String password) { 58 JedisConnectionFactory connectionFactory = new JedisConnectionFactory( 59 redisCluterConfig(clusterNodes, timeout, redirects, password), 60 poolConfig(maxIdle, maxTotal, maxWaitMillis, testOnBorrow, testOnReturn)); 61 connectionFactory.setPassword(password); 62 return connectionFactory; 63 } 64 65 @Bean(name = "stringRedisTemplate") 66 public StringRedisTemplate stringRedisTemplate() { 67 StringRedisTemplate template = new StringRedisTemplate(); 68 JedisConnectionFactory jedisConnectionFactory = SpringContextHolder.getBean("redisConnectionFactory"); 69 template.setConnectionFactory(jedisConnectionFactory); 70 return template; 71 } 72 73 @SuppressWarnings("rawtypes") 74 @Bean(name = "redisTemplate") 75 @DependsOn("redisConnectionFactory") 76 public RedisTemplate redisTemplate(JedisConnectionFactory redisConnectionFactory) { 77 RedisTemplate<String, Object> template = new RedisTemplate<String, Object>(); 78 // JedisConnectionFactory jedisConnectionFactory = SpringContextHolder.getBean("redisConnectionFactory"); 79 template.setConnectionFactory(redisConnectionFactory); 80 template.setKeySerializer(new StringRedisSerializer()); 81 template.setValueSerializer(new JdkSerializationRedisSerializer()); 82 template.setHashKeySerializer(new StringRedisSerializer()); 83 template.setHashValueSerializer(new JdkSerializationRedisSerializer()); 84 return template; 85 } 86 87 @Bean(name = "shiroRedisConnectionFactory") 88 public JedisConnectionFactory shiroRedisConnectionFactory(@Value("${spring.redis.cluster.maxIdle}") int maxIdle, 89 @Value("${spring.redis.cluster.maxTotal}") int maxTotal, 90 @Value("${spring.redis.cluster.maxWaitMillis}") long maxWaitMillis, 91 @Value("${spring.redis.cluster.testOnBorrow}") boolean testOnBorrow, 92 @Value("${spring.redis.cluster.testOnReturn}") boolean testOnReturn, 93 @Value("${spring.redis.cluster.nodes}") String clusterNodes, 94 @Value("${spring.redis.cluster.timeout}") Long timeout, 95 @Value("${spring.redis.cluster.max-redirects}") int redirects, 96 @Value("${spring.redis.cluster.password}") String password) { 97 JedisConnectionFactory connectionFactory = new JedisConnectionFactory( 98 redisCluterConfig(clusterNodes, timeout, redirects, password), 99 poolConfig(maxIdle, maxTotal, maxWaitMillis, testOnBorrow, testOnReturn)); 100 connectionFactory.setPassword(password); 101 return connectionFactory; 102 } 103 104 105 106 /** 107 * @description 108 * @author wbh 109 * @date 2018年11月12日 下午3:45:29 110 * @param shiroRedisConnectionFactory 111 * @return 112 * RedisTemplate 113 */ 114 @SuppressWarnings("rawtypes") 115 @Bean(name = "shiroRedisTemplate") 116 @DependsOn("shiroRedisConnectionFactory") 117 public RedisTemplate shiroRedisTemplate(@Qualifier("shiroRedisConnectionFactory")JedisConnectionFactory shiroRedisConnectionFactory) { 118 RedisTemplate<byte[], Object> template = new RedisTemplate<byte[], Object>(); 119 // JedisConnectionFactory jedisConnectionFactory = SpringContextHolder.getBean("redisConnectionFactory"); 120 template.setConnectionFactory(shiroRedisConnectionFactory); 121 //template.setKeySerializer(new StringRedisSerializer()); 122 //template.setValueSerializer( new RedisObjectSerializer()); 123 template.setDefaultSerializer(new JdkSerializationRedisSerializer()); 124 //template.setHashKeySerializer(new StringRedisSerializer()); 125 //template.setHashValueSerializer(new JdkSerializationRedisSerializer()); 126 return template; 127 } 128 }
application-dev.properties对配置的重写
1 ######################################redis-start################################## 2 #redis-cluster\u914d\u7f6e 3 #spring.redis.cluster.nodes=10.1.129.64:6401,10.1.129.64:6402,10.1.129.64:6403,10.1.129.64:6404,10.1.129.64:6405,10.1.129.64:6406 4 #redis-cluster\u914d\u7f6e 5 spring.redis.cluster.nodes=10.10.130.150:1501,10.10.130.150:1502,10.10.130.150:1503,10.10.130.150:1504,10.10.130.150:1505,10.10.130.150:1506 6 spring.redis.cluster.timeout=2000 7 spring.redis.cluster.max-redirects=100 8 spring.redis.cluster.password=123456 9 spring.redis.cluster.maxIdle=200 10 spring.redis.cluster.maxTotal=1000 11 spring.redis.cluster.maxWaitMillis=2000 12 spring.redis.cluster.testOnBorrow=true 13 spring.redis.cluster.testOnReturn=true 14 15 16 ######################################redis-end#####################################
3.静态方法
1 import java.util.ArrayList; 2 import java.util.List; 3 import java.util.Map; 4 import java.util.Set; 5 import java.util.concurrent.TimeUnit; 6 7 import com.gta.train.platform.fs.vo.qts.IndexInfo; 8 import com.gta.train.platform.fs.vo.qts.StockA; 9 import org.springframework.data.redis.core.HashOperations; 10 import org.springframework.data.redis.core.ListOperations; 11 import org.springframework.data.redis.core.RedisTemplate; 12 import org.springframework.data.redis.core.StringRedisTemplate; 13 14 import com.gta.train.platform.common.util.SpringContextHolder; 15 16 import com.gta.train.platform.common.util.StringUtils; 17 18 public class JedisClusterUtil { 19 private static StringRedisTemplate stringRedisTemplate = SpringContextHolder.getBean("stringRedisTemplate"); 20 private static RedisTemplate<String, Object> redisTemplate = SpringContextHolder.getBean("redisTemplate"); 21 22 private JedisClusterUtil() { 23 } 24 25 /** 26 * @description 根据键值取redis缓存中的数据 27 * @date 2017年6月27日 下午4:02:07 28 * @param key 29 * @return 30 * @return String 31 */ 32 public static final String get(String key) { 33 if (StringUtils.isNullOrEmpty(key)) { 34 return null; 35 } 36 return stringRedisTemplate.opsForValue().get(key); 37 } 38 39 /** 40 * @description 根据键值从redis中获取对象 41 * @date 2018年6月1日 上午10:52:23 42 * @param key 43 * @return 44 * @return Object 45 */ 46 public static final Object getObject(String key) { 47 if (StringUtils.isNullOrEmpty(key)) { 48 return null; 49 } 50 return redisTemplate.opsForValue().get(key); 51 } 52 53 /** 54 * @description 往redis服务器中,写数据 55 * @author fengya 56 * @date 2017年6月27日 下午4:04:12 57 * @param key 58 * @param value 59 * @return void 60 */ 61 public static final void set(String key, String value) { 62 stringRedisTemplate.opsForValue().set(key, value); 63 } 64 65 /** 66 * @description 往redis中设置对象,对象必须进行序列化 67 * @date 2018年6月1日 上午10:28:41 68 * @param key 69 * @param value 70 * @return void 71 */ 72 public static final void set(String key, Object value) { 73 redisTemplate.opsForValue().set(key, value); 74 } 75 76 /** 77 * @description 对缓存中的键key进行设置有效期限 78 * @date 2017年6月29日 下午4:00:01 79 * @param key 80 * @param seconds 81 * 必须大于0 82 * @return void 83 */ 84 public static final void expire(String key, long seconds) { 85 if (seconds > 0) { 86 stringRedisTemplate.expire(key, seconds, TimeUnit.SECONDS); 87 } 88 } 89 90 /** 91 * @description 写缓存数据,并规定过期时间 92 * @date 2017年6月27日 下午4:07:02 93 * @param key 94 * @param value 95 * @param seconds 96 * 过期时间,单位:秒 97 * @return void 98 */ 99 public static final void set(String key, String value, long seconds) { 100 stringRedisTemplate.opsForValue().set(key, value, seconds, TimeUnit.SECONDS); 101 } 102 103 /** 104 * @description 判断redis缓存中是否存在键为key的数据 105 * @date 2017年6月29日 下午3:56:32 106 * @param key 107 * @return 108 * @return boolean 109 */ 110 public static final boolean exists(String key) { 111 String value = get(key); 112 if (StringUtils.isNullOrEmpty(value)) { 113 return false; 114 } 115 return true; 116 } 117 118 /** 119 * @description 删除一个key 120 * @date 2017年6月27日 下午5:02:56 121 * @param key 122 * @return void 123 */ 124 public static final void del(String... keys) { 125 for (String key : keys) { 126 stringRedisTemplate.delete(key); 127 } 128 } 129 130 /** 131 * @description 从redis缓存中,删除对象 132 * @date 2018年6月1日 上午11:09:08 133 * @param keys 134 * @return void 135 */ 136 public static final void delObject(String... keys) { 137 for (String key : keys) { 138 redisTemplate.delete(key); 139 } 140 } 141 142 /** 143 * @description 往缓存中添加一个list数据 144 * @date 2017年8月10日 下午2:10:24 145 * @param key 146 * @param dataList 147 * @return 148 * @return ListOperations<String,Object> 149 */ 150 public static final ListOperations<String, Object> setCacheList(String key, List<Object> dataList) { 151 ListOperations<String, Object> listOperation = redisTemplate.opsForList(); 152 if (null != dataList) { 153 listOperation.rightPushAll(key, dataList); 154 } 155 return listOperation; 156 } 157 158 /** 159 * @description 读取缓存集合中所有的数据信息 160 * @date 2017年8月10日 下午4:10:37 161 * @param key 162 * @return 163 * @return List<Object> 164 */ 165 public static final List<Object> getCacheList(String key) { 166 return redisTemplate.opsForList().range(key, 0, -1); 167 } 168 169 /** 170 * @description 根据键值获得该键对应的集合数据,并对所有的记录数据进行出栈 171 * @date 2017年8月10日 下午2:18:02 172 * @param key 173 * @return 174 * @return List<Object> 175 */ 176 public static final List<Object> listPopAll(String key) { 177 List<Object> dataList = new ArrayList<Object>(); 178 ListOperations<String, Object> listOperation = redisTemplate.opsForList(); 179 Long size = listOperation.size(key); 180 for (int i = 0; i < size; i++) { 181 dataList.add(listOperation.leftPop(key)); 182 } 183 return dataList; 184 } 185 186 /** 187 * @description 对缓存集合中的元素按照下标位置进行出栈操作 188 * @date 2017年8月10日 下午4:07:44 189 * @param key 190 * @param start 191 * 下标开始位置 192 * @param end 193 * 下标结束位置 ,-1代表最后一个元素下标 194 * @return 195 * @return List<Object> 196 */ 197 public static final List<Object> listPopRange(String key, int start, long end) { 198 List<Object> dataList = new ArrayList<Object>(); 199 ListOperations<String, Object> listOperation = redisTemplate.opsForList(); 200 long size = listOperation.size(key); 201 end = end > size ? size : end; 202 for (int i = start; i < end; i++) { 203 dataList.add(listOperation.leftPop(key)); 204 } 205 return dataList; 206 } 207 208 /** 209 * @description 获得缓存键值为Key集合中的下标范围内的集合数据 210 * @date 2017年8月10日 下午2:19:26 211 * @param key 212 * @param start 213 * @param end 214 * @return 215 * @return List<Object> 216 */ 217 public static final List<Object> range(String key, long start, long end) { 218 ListOperations<String, Object> listOperation = redisTemplate.opsForList(); 219 return listOperation.range(key, start, end); 220 } 221 222 /** 223 * @description 获得缓存中集合的长度 224 * @date 2017年8月10日 下午2:21:51 225 * @param key 226 * @return 227 * @return Long 228 */ 229 public static final Long listSize(String key) { 230 return redisTemplate.opsForList().size(key); 231 } 232 233 /** 234 * @description 在集合指定下标内进行数据覆盖 235 * @date 2017年8月10日 下午2:22:58 236 * @param key 237 * @param index 238 * @param obj 239 * @return void 240 */ 241 public static final void listSet(String key, int index, Object obj) { 242 redisTemplate.opsForList().set(key, index, obj); 243 } 244 245 /** 246 * @description 向集合缓存的头部插入记录 247 * @date 2017年8月10日 下午2:24:10 248 * @param key 249 * @param obj 250 * @return 251 * @return long 252 */ 253 public static final long leftPush(String key, Object obj) { 254 return redisTemplate.opsForList().leftPush(key, obj); 255 } 256 257 /** 258 * @description 向集合缓存的尾部插入记录 259 * @date 2017年8月10日 下午2:25:31 260 * @param key 261 * @param obj 262 * @return 263 * @return long 264 */ 265 public static final long rightPush(String key, Object obj) { 266 return redisTemplate.opsForList().rightPush(key, obj); 267 } 268 269 /** 270 * @description 缓存集合中的数据,只保留start到end位置的元素 271 * @date 2017年8月10日 下午2:27:05 272 * @param key 273 * @param start 274 * 记录的开始位置(0表示第一条记录) 275 * @param end 276 * 记录的结束位置(如果为-1则表示最后一个,-2,-3以此类推) 277 * @return void 278 */ 279 public static final void trim(String key, int start, int end) { 280 redisTemplate.opsForList().trim(key, start, end); 281 } 282 283 /** 284 * @description 删除缓存集合中指定位置的元素 285 * @date 2017年8月10日 下午2:28:55 286 * @param key 287 * @param i 288 * 要删除的数量,如果为负数则从List的尾部检查并删除符合的记录 289 * @param obj 290 * 要匹配的值 291 * @return 292 * @return long 删除后的List中的记录数 293 */ 294 public static final long remove(String key, long i, Object obj) { 295 return redisTemplate.opsForList().remove(key, i, obj); 296 } 297 298 /** 299 * @description 在缓存中存储set集合, 300 * @date 2017年8月10日 下午4:53:06 301 * @param key 302 * @param dataSet 303 * @return 304 * @return void 305 */ 306 public static final void setCacheSet(String key, Set<Object> dataSet) { 307 redisTemplate.opsForSet().add(key, dataSet.toArray()); 308 } 309 310 /** 311 * @description 得到集合中所有的元素 312 * @date 2017年8月10日 下午5:10:35 313 * @param key 314 * @return 315 * @return Set<Object> 316 */ 317 public static final Set<Object> getCacheSet(String key) { 318 return redisTemplate.opsForSet().members(key); 319 } 320 321 /** 322 * @description 对缓存中的集合进行出栈操作 323 * @date 2017年8月10日 下午5:13:29 324 * @param key 325 * @return 326 * @return Object 327 */ 328 public static final Object setPop(String key) { 329 return redisTemplate.opsForSet().pop(key); 330 } 331 332 /** 333 * @description 对缓存中的集合元素进行删除操作 334 * @date 2017年8月10日 下午5:14:36 335 * @param key 336 * @param values 待删除的元素集合 337 * @return 338 * @return long 删除元素的个数 339 */ 340 public static final long setPop(String key,Object...values) { 341 return redisTemplate.opsForSet().remove(key, values); 342 } 343 344 /** 345 * @description 往缓存写入map数据 346 * @date 2017年8月10日 下午5:17:48 347 * @param key 348 * @param dataMap 349 * @return void 350 */ 351 public static final void setCacheMap(String key,Map<String, Object> dataMap) { 352 redisTemplate.opsForHash().putAll(key, dataMap); 353 } 354 355 /** 356 * @description 根据键值从缓存中取map数据 357 * @date 2017年8月10日 下午5:20:40 358 * @param key 359 * @return 360 * @return Map<Object,Object> 361 */ 362 public static final Map<Object, Object> getCacheMap(String key) { 363 return redisTemplate.opsForHash().entries(key); 364 } 365 366 /** 367 * @description 从缓存中取根据Map中的键取值对象 368 * @date 2017年8月10日 下午5:23:11 369 * @param key 370 * @param mapKey 371 * @return 372 * @return Object 373 */ 374 public static final Object getMapValue(String key,String mapKey) { 375 return redisTemplate.opsForHash().get(key, mapKey); 376 } 377 378 /** 379 * @description 往缓存Map中,添加一组元素 380 * @date 2017年8月10日 下午5:25:11 381 * @param key 缓存中对应的键 382 * @param mapKey map中的键 383 * @param mapValue map中的值 384 * @return void 385 */ 386 public static final void mapPush(String key,String mapKey,Object mapValue) { 387 redisTemplate.opsForHash().put(key, mapKey, mapValue); 388 } 389 390 /** 391 * @description 从缓存中对应键的key中的map中,根据map中的键进行删除该键对应的元素 392 * @date 2017年8月10日 下午5:29:53 393 * @param key 缓存中的键 394 * @param mapKey map中的键 395 * @return void 396 */ 397 public static final void deleteMapByMapKey(String key,String mapKey) { 398 redisTemplate.opsForHash().delete(key, mapKey); 399 } 400 401 /** 402 * @description 往缓存写入map数据 403 * @date 2017年8月10日 下午5:17:48 404 * @param key 405 * @param dataMap 406 * @return void 407 */ 408 public static final void setMap(String key,Map<String, String> dataMap) { 409 redisTemplate.opsForHash().putAll(key, dataMap); 410 } 411 412 public static final Map<String, String> getMap(String key) { 413 HashOperations<String, String, String> hps = redisTemplate.opsForHash(); 414 return hps.entries(key); 415 } 416 417 public static final void setIndexMap(String key,Map<String, IndexInfo> dataMap) { 418 redisTemplate.opsForHash().putAll(key, dataMap); 419 } 420 421 public static final Map<String, IndexInfo> getIndexMap(String key) { 422 HashOperations<String, String, IndexInfo> hps = redisTemplate.opsForHash(); 423 return hps.entries(key); 424 } 425 426 }
4.具体使用
1 JedisClusterUtil.set("lkjlkjjklasdf", "11111111111"); 2 System.out.println(JedisClusterUtil.get("lkjlkjjklasdf")); 3 4 SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(); 5 byte[] bkey = getByteKey("c0233b04e18a11e8984cd4ae52b618b7"); 6 shiroRedisTemplate.opsForValue().set(bkey,info); 7 Object o=shiroRedisTemplate.opsForValue().get(bkey); 8 System.out.println(o);