您的位置:首页 > 数据库 > Redis

spring整合redis客户端及缓存接口设计

2016-08-10 15:24 429 查看


一、写在前面

缓存作为系统性能优化的一大杀手锏,几乎在每个系统或多或少的用到缓存。有的使用本地内存作为缓存,有的使用本地硬盘作为缓存,有的使用缓存服务器。但是无论使用哪种缓存,接口中的方法都是差不多。笔者最近的项目使用的是memcached作为缓存服务器,由于memcached的一些限制,现在想换redis作为缓存服务器。思路就是把memached的客户端换成redis客户端,接口依然是原来的接口,这样对系统可以无损替换,接口不变,功能不变,只是客户端变了。本文不介绍缓存的用法,不介绍redis使用方法,不介绍memcached与redis有何区别。只是实现一个redis客户端,用了jedis作为第三方连接工具。


二、一些想法

首先贴一下现项目中同事编写的缓存接口:

这个接口用起来总有一些别扭,我总结了一下:

1、接口名称命名为DispersedCachClient 这个命名含义是分布式缓存客户端(cache少了一个字母),其实这个接口跟分布式一点关系都没有,其实就是缓存接口;

2、接口方法太多了,实际在项目中并没有方法使用率只有20%左右,所有有精简的必要;

3、这个接口很多方法设计是套用memcached客户端设计的,也就是说换成redis后会不通用。

这里没有说这个接口写的不好,而是说还有优化的空间,其次也给自己提个醒,在设计一些使用公共的接口时有必要多花些心思,因为一旦设计后,后面改动的可能性比较小。


三、代码实现

使用jedis客户端需要使用连接池,使用连接后需要将连接放回连接池,失效的连接要放到失效的连接池,类似jdbc需要进行连接的处理,为了避免写重复恶心的代码,参照了spring的JdbcTemple模板设计方式。废话没有,直接上代码吧。

1、重新设计的缓存客户端接口,这个接口就一个特点“简单”,目的是为了做到通用,故命名为SimpleCache。

  

2、JedisTemple :Jedis 操作模板类,请参照Spring的JdbcTemple封装重复但又必要的操作

1 /**
2  * @ClassName: JedisTemple
3  * @Description: Jedis 操作模板类,为啥要这个?请参照{@link JdbcTemple} 封装重复不必要的操作
4  * @author 徐飞
5  * @date 2016年1月26日 下午2:37:24
6  *
7  */
8 public class JedisTemple {
9
10     /** 缓存客户端 **/
11     private JedisPool jedisPool;// 非切片连接池
12
13     public JedisTemple(JedisPool jedisPool) {
14         this.jedisPool = jedisPool;
15     }
16
17     /**
18      * @Title: execute
19      * @Description: 执行{@link RedisPoolCallback#doInJedis(Jedis)}的方法
20      * @param action
21      * @return
22      * @author 徐飞
23      */
24     public <T> T execute(RedisPoolCallback<T> action) {
25         T value = null;
26         Jedis jedis = null;
27         try {
28             jedis = jedisPool.getResource();
29             return action.doInJedis(jedis);
30         } catch (Exception e) {
31             // 释放redis对象
32             jedisPool.returnBrokenResource(jedis);
33             e.printStackTrace();
34         } finally {
35             // 返还到连接池
36             returnResource(jedisPool, jedis);
37         }
38
39         return value;
40     }
41
42     /**
43     * 返还到连接池
44     * @param pool
45     * @param redis
46     */
47     private void returnResource(JedisPool pool, Jedis redis) {
48         // 如果redis为空不返回
49         if (redis != null) {
50             pool.returnResource(redis);
51         }
52     }
53
54     public JedisPool getJedisPool() {
55         return jedisPool;
56     }
57
58     public void setJedisPool(JedisPool jedisPool) {
59         this.jedisPool = jedisPool;
60     }
61
62 }


3、RedisPoolCallback:redis操作回调接口,此接口主要为JedisTemple模板使用

1 import redis.clients.jedis.Jedis;
2
3 /**
4  * @ClassName: RedisPoolCallback
5  * @Description: redis操作回调接口,此接口主要为JedisTemple模板使用
6  * @author 徐飞
7  * @date 2016年1月26日 下午2:35:41
8  *
9  * @param <T>
10  */
11 public interface RedisPoolCallback<T> {
12     /**
13      * @Title: doInJedis
14      * @Description: 回调执行方法,需要重新此方法,一般推荐使用匿名内部类
15      * @param jedis
16      * @return
17      * @author 徐飞
18      */
19     T doInJedis(Jedis jedis);
20 }


4、RedisCacheClient :redis客户端实现类

1 import redis.clients.jedis.Jedis;
2 import redis.clients.util.SafeEncoder;
3
4 import com.cxypub.baseframework.sdk.util.ObjectUtils;
5
6 /**
7  * @ClassName: RedisCacheClient
8  * @Description: redis缓存客户端
9  * @author 徐飞
10  * @date 2015-4-16 上午10:42:32
11  *
12  */
13 public class RedisCacheClient implements SimpleCache {
14
15     private JedisTemple jedisTemple;
16
17     public RedisCacheClient(JedisTemple jedisTemple) {
18         this.jedisTemple = jedisTemple;
19     }
20
21     @Override
22     public boolean add(final String key, final Object valueObject) {
23         try {
24             jedisTemple.execute(new RedisPoolCallback<Boolean>() {
25                 @Override
26                 public Boolean doInJedis(Jedis jedis) {
27                     jedis.set(SafeEncoder.encode(key), ObjectUtils.object2Byte(valueObject));
28                     return true;
29                 }
30
31             });
32         } catch (Exception e) {
33             e.printStackTrace();
34             return false;
35         }
36         return true;
37     }
38
39     @Override
40     public Object get(final String key) {
41
42         return jedisTemple.execute(new RedisPoolCallback<Object>() {
43             @Override
44             public Object doInJedis(Jedis jedis) {
45                 byte[] cacheValue = jedis.get(SafeEncoder.encode(key));
46                 if (cacheValue != null) {
47                     return ObjectUtils.byte2Object(cacheValue);
48                 }
49                 return null;
50             }
51
52         });
53     }
54
55     @Override
56     public long delete(final String key) {
57         return jedisTemple.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: