redis做緩存的簡單實例

由於之前對redis有了一個系統的研究,在公司的多個項目中使用redis當做數據緩存;所以趁着這些天晚上的時間,自己寫了一個demo;這裏僅供自己後期學習筆記參考,若有不對的地方,請輕拍磚!

redis 官網推薦給java 使用的客戶端很多:Jedis、Redisson、JRedis、JDBC-Redis 等,當然首推是jedis;可以參考redis客戶端官網查看。

接下來來講下我的這個demo,我這個案例不是通過spring進行整合的redis,這個將會在之後的demo中講到的。

(1).創建一個maven 功臣,在工程的pom 中引入jedis客戶端;還有要依賴spring管理,所以也要引入spring相關jar包。

[html] view plain copy
  1. <span style="white-space:pre">        </span><dependency>  
  2.                 <groupId>redis.clients</groupId>  
  3.                 <artifactId>jedis</artifactId>  
  4.                 <version>${jedis-version}</version>  
  5.             </dependency>  
  6.         <dependency>  

(2).一般一個(系統)項目所用的redis服務器 多節點的集羣服務器,所以會自己對(jedis)redis客戶端進行封裝,由於本例我自己寫的是單節點,但是我還是按多節點的思路對客戶端進行了封裝。

redisClient類

[java] view plain copy
  1. /** 
  2.  * redis 客戶端封裝 
  3.  * @author leo 
  4.  * 
  5.  */  
  6. public class RedisClient  {  
  7.     /** 
  8.      * 日誌記錄 
  9.      */  
  10.     private static final Log LOG = LogFactory.getLog(RedisClient.class);  
  11.     /** 
  12.      * redis 連接池 
  13.      */  
  14.     private JedisPool pool;  
  15.       
  16.     public void setPool(JedisPool pool) {  
  17.         this.pool = pool;  
  18.     }  
  19.     /** 
  20.      * 獲取jedis  
  21.      * @return 
  22.      */  
  23.     public Jedis getResource(){  
  24.         Jedis jedis =null;  
  25.         try {  
  26.             jedis =pool.getResource();  
  27.         } catch (Exception e) {  
  28.             LOG.info("can't  get  the redis resource");  
  29.         }  
  30.         return jedis;  
  31.     }  
  32.     /** 
  33.      * 關閉連接 
  34.      * @param jedis 
  35.      */  
  36.     public void disconnect(Jedis jedis){  
  37.         jedis.disconnect();  
  38.     }  
  39.     /** 
  40.      * 將jedis 返還連接池 
  41.      * @param jedis 
  42.      */  
  43.     public void returnResource(Jedis jedis){  
  44.         if(null != jedis){  
  45.             try {  
  46.                 pool.returnResource(jedis);  
  47.             } catch (Exception e) {  
  48.                 LOG.info("can't return jedis to jedisPool");  
  49.             }  
  50.         }  
  51.     }  
  52.     /** 
  53.      * 無法返還jedispool,釋放jedis客戶端對象, 
  54.      * @param jedis 
  55.      */  
  56.     public void brokenResource(Jedis jedis){  
  57.         if (jedis!=null) {  
  58.             try {  
  59.                 pool.returnBrokenResource(jedis);  
  60.             } catch (Exception e) {  
  61.                 LOG.info("can't release jedis Object");  
  62.             }  
  63.         }  
  64.     }  
  65. }  
然後 通過spring的bean.xml 來管理 連接池,和連接池參數配置,以及redisClient 的依賴注入。

[html] view plain copy
  1. <!-- jedis 連接池配置參數:  -->  
  2.         <bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig">  
  3.             <property name="maxActive" value="100"></property>  
  4.             <property name="maxIdle" value="25"></property>  
  5.             <property name="maxWait" value="15000"></property>  
  6.             <property name="testOnBorrow" value="false"></property>  
  7.             <property name="testOnReturn" value="false"></property>  
  8.         </bean>  
  9.         <!-- jedis 連接池  連接本地redis服務 構造器注入-->  
  10.         <bean id="pool" class="redis.clients.jedis.JedisPool">  
  11.             <constructor-arg index="0"  ref="poolConfig"/>   
  12.             <constructor-arg index="1" value="10.224.68.46"/>   
  13.             <constructor-arg index="2" value="6379"/>  
  14.             <constructor-arg index="3" value="2000"/>   
  15.         </bean>  
  16.         <!-- cleint-->  
  17.         <bean id="redisClient" class="com.deppon.cache.redis.RedisClient">  
  18.             <property name="pool" ref="pool"/>  
  19.         </bean>  
(3).創建好redisClient 之後,我要創造一個存儲器,即一個對redis操作的工具容器。由於是公共容器,所以我創建接口是的容器接口就不該是封閉的,應該是開封的,保證存入數據庫中對象類型的多態性。

存儲器接口:

[java] view plain copy
  1. /** 
  2.  *  
  3.  * @author leo 
  4.  *緩存存儲接口 
  5.  * @param <K> key 
  6.  * @param <V> value 
  7.  */  
  8. public interface RedisCacheStorage<K, V> {  
  9.     /** 
  10.      * 在redis數據庫中插入 key  和value 
  11.      * @param key 
  12.      * @param value 
  13.      * @return 
  14.      */  
  15.     boolean set(K key,V value);  
  16.     /** 
  17.      * 在redis數據庫中插入 key  和value 並且設置過期時間 
  18.      * @param key 
  19.      * @param value 
  20.      * @param exp 過期時間 s 
  21.      * @return 
  22.      */  
  23.     boolean set(K key, V value, int exp);  
  24.     /** 
  25.      * 根據key 去redis 中獲取value 
  26.      * @param key 
  27.      * @return 
  28.      */  
  29.     V get(K key);  
  30.     /** 
  31.      * 刪除redis庫中的數據 
  32.      * @param key 
  33.      * @return 
  34.      */  
  35.     boolean remove(K key);  
  36.     /** 
  37.      * 設置哈希類型數據到redis 數據庫 
  38.      * @param cacheKey 可以看做一張表 
  39.      * @param key   表字段 
  40.      * @param value   
  41.      * @return 
  42.      */  
  43.     boolean hset(String cacheKey,K key,V value);  
  44.     /** 
  45.      * 獲取哈希表數據類型的值 
  46.      * @param cacheKey 
  47.      * @param key 
  48.      * @return 
  49.      */  
  50.     V hget(String cacheKey,K key);  
  51.     /** 
  52.      * 獲取哈希類型的數據 
  53.      * @param cacheKey 
  54.      * @return 
  55.      */  
  56.     Map<K,V> hget(String cacheKey);  
以及存儲實現類:

[java] view plain copy
  1. /** 
  2.  * redis 緩存存儲器實現 
  3.  * @author leo 
  4.  * 
  5.  * @param <V> 
  6.  */  
  7. public class RedisCacheStorageImpl<V> implements RedisCacheStorage<String, V> {  
  8.     /** 
  9.      * 日誌記錄 
  10.      */  
  11.     public static final Log LOG = LogFactory.getLog(RedisCacheStorageImpl.class);  
  12.     /** 
  13.      * redis 客戶端 
  14.      */  
  15.     private RedisClient redisClient;  
  16.     /** 
  17.      * 默認過時時間 
  18.      */  
  19.     private static final int EXPRIE_TIME =3600*24;   
  20.       
  21.     public void setRedisClient(RedisClient redisClient) {  
  22.         this.redisClient = redisClient;  
  23.     }  
  24.     /** 
  25.      * 在redis數據庫中插入 key  和value 
  26.      * @param key 
  27.      * @param value 
  28.      * @return 
  29.      */  
  30.     @Override  
  31.     public boolean set(String key, V value) {  
  32.         //設置默認過時時間  
  33.         return set(key, value, EXPRIE_TIME);  
  34.     }  
  35.     /** 
  36.      * 在redis數據庫中插入 key  和value 並且設置過期時間 
  37.      * @param key 
  38.      * @param value 
  39.      * @param exp 過期時間 s 
  40.      * @return 
  41.      */  
  42.     @SuppressWarnings("finally")  
  43.     @Override  
  44.     public boolean set(String key, V value, int exp) {  
  45.         Jedis jedis =null;  
  46.         //將key 和value  轉換成 json 對象  
  47.         String jKey =CacheUtils.toJsonString(key);  
  48.         String jValue =CacheUtils.toJsonString(value);  
  49.         //操作是否成功  
  50.         boolean isSucess =true;  
  51.         if(StringUtils.isNotEmpty(jKey)){  
  52.             LOG.info("key is empty");  
  53.             return false;  
  54.         }  
  55.         try {  
  56.             //獲取客戶端對象  
  57.             jedis =redisClient.getResource();  
  58.             //執行插入  
  59.             jedis.setex(jKey, exp, jValue);  
  60.         } catch (JedisException e) {  
  61.             LOG.info("client can't connect server");  
  62.             isSucess =false;  
  63.             if(null !=jedis){  
  64.                 //釋放jedis對象  
  65.                 redisClient.brokenResource(jedis);  
  66.             }  
  67.             return false;  
  68.         }finally{  
  69.             if(isSucess){  
  70.                 //返還連接池  
  71.                 redisClient.returnResource(jedis);  
  72.             }  
  73.             return true;  
  74.         }  
  75.     }  
  76.     /** 
  77.      * 根據key 去redis 中獲取value 
  78.      * @param key 
  79.      * @return 
  80.      */  
  81.     @SuppressWarnings("unchecked")  
  82.     @Override  
  83.     public V get(String key) {  
  84.         Jedis jedis =null;  
  85.         //將key 和value  轉換成 json 對象  
  86.         String jKey =CacheUtils.toJsonString(key);  
  87.         V jValue =null;  
  88.         //key 不能爲空  
  89.         if(StringUtils.isEmpty(jKey)){  
  90.             LOG.info("key is empty");  
  91.             return null;  
  92.         }  
  93.         try {  
  94.             //獲取客戶端對象  
  95.             jedis =redisClient.getResource();  
  96.             //執行查詢  
  97.             String value =  jedis.get(jKey);  
  98.             //判斷值是否非空  
  99.             if(StringUtils.isEmpty(value)){  
  100.                 return null;  
  101.             }else{  
  102.                 jValue= (V) CacheUtils.jsonParseObject(value);  
  103.             }  
  104.             //返還連接池  
  105.             redisClient.returnResource(jedis);  
  106.         } catch (JedisException e) {  
  107.             LOG.info("client can't connect server");  
  108.             if(null !=jedis){  
  109.                 //釋放jedis 對象  
  110.                 redisClient.brokenResource(jedis);  
  111.             }  
  112.         }  
  113.         return jValue;  
  114.     }  
  115.     /** 
  116.      * 刪除redis庫中的數據 
  117.      * @param key 
  118.      * @return 
  119.      */  
  120.     @SuppressWarnings("finally")  
  121.     @Override  
  122.     public boolean remove(String key) {  
  123.         Jedis jedis =null;  
  124.         //將key 和value  轉換成 json 對象  
  125.         String jKey =CacheUtils.toJsonString(key);  
  126.         //操作是否成功  
  127.         boolean isSucess =true;  
  128.         if(StringUtils.isEmpty(jKey)){  
  129.             LOG.info("key is empty");  
  130.             return false;  
  131.         }  
  132.         try {  
  133.             jedis =redisClient.getResource();  
  134.             //執行刪除  
  135.             jedis.del(jKey);  
  136.         } catch (JedisException e) {  
  137.             LOG.info("client can't connect server");  
  138.             isSucess =false;  
  139.             if(null !=jedis){  
  140.                 //釋放jedis 對象  
  141.                 redisClient.brokenResource(jedis);  
  142.             }  
  143.             return false;  
  144.         }finally{  
  145.             if (isSucess) {  
  146.                 //返還連接池  
  147.                 redisClient.returnResource(jedis);  
  148.             }  
  149.             return true;  
  150.         }  
  151.     }  
  152.     /** 
  153.      * 設置哈希類型數據到redis 數據庫 
  154.      * @param cacheKey 可以看做一張表 
  155.      * @param key   表字段 
  156.      * @param value   
  157.      * @return 
  158.      */  
  159.     @SuppressWarnings("finally")  
  160.     @Override  
  161.     public boolean hset(String cacheKey, String key, V value) {  
  162.         Jedis jedis =null;  
  163.         //將key 和value  轉換成 json 對象  
  164.         String jKey =CacheUtils.toJsonString(key);  
  165.         String jCacheKey =CacheUtils.toJsonString(cacheKey);  
  166.         String jValue =CacheUtils.toJsonString(value);  
  167.         //操作是否成功  
  168.         boolean isSucess =true;  
  169.         if(StringUtils.isEmpty(jCacheKey)){  
  170.             LOG.info("cacheKey is empty");  
  171.             return false;  
  172.         }  
  173.         try {  
  174.             jedis =redisClient.getResource();  
  175.             //執行插入哈希  
  176.             jedis.hset(jCacheKey, jKey, jValue);  
  177.         } catch (JedisException e) {  
  178.             LOG.info("client can't connect server");  
  179.             isSucess =false;  
  180.             if(null !=jedis){  
  181.                 //釋放jedis 對象  
  182.                 redisClient.brokenResource(jedis);  
  183.             }  
  184.             return false;  
  185.         }finally{  
  186.             if (isSucess) {  
  187.                 //返還連接池  
  188.                 redisClient.returnResource(jedis);  
  189.             }  
  190.             return true;  
  191.         }  
  192.     }  
  193.     /** 
  194.      * 獲取哈希表數據類型的值 
  195.      * @param cacheKey 
  196.      * @param key 
  197.      * @return 
  198.      */  
  199.     @SuppressWarnings("unchecked")  
  200.     @Override  
  201.     public V hget(String cacheKey, String key) {  
  202.         Jedis jedis =null;  
  203.         //將key 和value  轉換成 json 對象  
  204.         String jKey =CacheUtils.toJsonString(key);  
  205.         String jCacheKey =CacheUtils.toJsonString(cacheKey);  
  206.         V jValue =null;  
  207.         if(StringUtils.isEmpty(jCacheKey)){  
  208.             LOG.info("cacheKey is empty");  
  209.             return null;  
  210.         }  
  211.         try {  
  212.             //獲取客戶端對象  
  213.             jedis =redisClient.getResource();  
  214.             //執行查詢  
  215.             String value =  jedis.hget(jCacheKey, jKey);  
  216.             //判斷值是否非空  
  217.             if(StringUtils.isEmpty(value)){  
  218.                 return null;  
  219.             }else{  
  220.                 jValue= (V) CacheUtils.jsonParseObject(value);  
  221.             }  
  222.             //返還連接池  
  223.             redisClient.returnResource(jedis);  
  224.         } catch (JedisException e) {  
  225.             LOG.info("client can't connect server");  
  226.             if(null !=jedis){  
  227.                 //釋放jedis 對象  
  228.                 redisClient.brokenResource(jedis);  
  229.             }  
  230.         }  
  231.         return jValue;  
  232.     }  
  233.     /** 
  234.      * 獲取哈希類型的數據 
  235.      * @param cacheKey 
  236.      * @return 
  237.      */  
  238.     @Override  
  239.     public Map<String, V> hget(String cacheKey) {  
  240.         String jCacheKey =CacheUtils.toJsonString(cacheKey);  
  241.         //非空校驗  
  242.         if(StringUtils.isEmpty(jCacheKey)){  
  243.             LOG.info("cacheKey is empty!");  
  244.             return null;  
  245.         }  
  246.         Jedis jedis =null;  
  247.         Map<String,V> result =null;  
  248.         try {  
  249.             jedis =redisClient.getResource();  
  250.             //獲取列表集合  
  251.             Map<String,String> map = jedis.hgetAll(jCacheKey);   
  252.               
  253.             if(null !=map){  
  254.                 for(Map.Entry<String, String> entry : map.entrySet()){  
  255.                     if(result ==null){  
  256.                         result =new HashMap<String,V>();  
  257.                     }  
  258.                     result.put((String) CacheUtils.jsonParseObject(entry.getKey()), (V)CacheUtils.jsonParseObject(entry.getValue()));  
  259.                 }  
  260.             }  
  261.         } catch (JedisException e) {  
  262.             LOG.info("client can't connect server");  
  263.             if(null !=jedis){  
  264.                 //釋放jedis 對象  
  265.                 redisClient.brokenResource(jedis);  
  266.             }  
  267.         }  
  268.         return result;  
  269.     }  
  270.   
  271. }  
(4),接下來要把寫個具體的業務UserService,來測試redis的存儲器在具體業務中的使用,即實現(非關係型數據庫的持久化操作)。本例中的例子是經常項目中對user的操作

創建UserEntity實體類:

[java] view plain copy
  1. /** 
  2.  * 用戶實體類 
  3.  * @author leo 
  4.  * 
  5.  */  
  6. public class UserEntity {  
  7.     //用戶id  
  8.     private String userId;  
  9.     //用戶賬號  
  10.     private String EmpCode;  
  11.     //用戶名稱  
  12.     private String EmpName;  
  13.     //用戶角色  
  14.     private String role;  
  15.     //職位  
  16.     private String title;  
  17.     public String getUserId() {  
  18.         return userId;  
  19.     }  
  20.     public void setUserId(String userId) {  
  21.         this.userId = userId;  
  22.     }  
  23.     public String getEmpCode() {  
  24.         return EmpCode;  
  25.     }  
  26.     public void setEmpCode(String empCode) {  
  27.         EmpCode = empCode;  
  28.     }  
  29.     public String getEmpName() {  
  30.         return EmpName;  
  31.     }  
  32.     public void setEmpName(String empName) {  
  33.         EmpName = empName;  
  34.     }  
  35.     public String getRole() {  
  36.         return role;  
  37.     }  
  38.     public void setRole(String role) {  
  39.         this.role = role;  
  40.     }  
  41.     public String getTitle() {  
  42.         return title;  
  43.     }  
  44.     public void setTitle(String title) {  
  45.         this.title = title;  
  46.     }  
然後創建用戶操作的業務層Service;由於這裏主要是測試NOSQL的數據持久化,所以就忽略了對數據庫持久化層(DAO)的操作。

userServiceImpl類:

[java] view plain copy
  1. /** 
  2.  * 業務層接口實現 
  3.  * @author leo 
  4.  * 
  5.  */  
  6. public class UserServiceImpl implements IUserService {  
  7.     private static final String  cacheKey  ="userEntity";  
  8.     /** 
  9.      * 緩存存儲 
  10.      */  
  11.     private RedisCacheStorageImpl<UserEntity> storageCache;  
  12.       
  13.     public void setStorageCache(RedisCacheStorageImpl<UserEntity> storageCache) {  
  14.         this.storageCache = storageCache;  
  15.     }  
  16.     /** 
  17.      * 新增 
  18.      * @param entity 
  19.      * @return 
  20.      */  
  21.     @Override  
  22.     public boolean addUserEntity(UserEntity entity) {  
  23.         //非空  
  24.         if(entity ==null || StringUtils.isEmpty(entity.getUserId())){  
  25.             return false;  
  26.         }  
  27.         /** 
  28.          * 做數據庫持久化,這裏就無需再申明瞭 
  29.          */  
  30.         System.out.println("先插入數據庫中,.........");  
  31.         //然後接下來做非關係型數據庫持久化  
  32.         return storageCache.hset(cacheKey, entity.getUserId(), entity);  
  33.     }  
  34.   
  35.     @Override  
  36.     public boolean deleteUserEntity(UserEntity entity) {  
  37.           
  38.         return false;  
  39.     }  
  40.     /** 
  41.      * 根據id 查詢 
  42.      * @return 
  43.      */  
  44.     @Override  
  45.     public UserEntity queryUserEntityByUserId(UserEntity userEntity) {  
  46.         //非空  
  47.         if(userEntity ==null || StringUtils.isEmpty(userEntity.getUserId())){  
  48.             return null;  
  49.         }  
  50.         //先去緩存中查詢 是否存在,不存在在查詢  
  51.          UserEntity reslut = storageCache.hget(cacheKey, userEntity.getUserId());  
  52.         if(reslut!=null){  
  53.             return reslut;  
  54.         }else{  
  55.             //查詢數據庫  
  56.             System.out.println("查詢數據庫");  
  57.         }  
  58.         return null;  
  59.     }  
  60.   
  61. }  
以及spring-bean.xml的配置對業務層的管理:

[html] view plain copy
  1. <!-- storge Cache 存儲器-->  
  2.         <bean id="storageCache" class="com.deppon.cache.storage.impl.RedisCacheStorageImpl">  
  3.             <property name="redisClient" ref="redisClient" />  
  4.         </bean>  
  5.         <bean id="userServiceImpl" class="com.deppon.cache.service.impl.UserServiceImpl">  
  6.             <property name="storageCache" ref="storageCache"/>  
  7.         </bean>  
(6).最後寫個junit 測下,查看是否有沒有插入到redis庫中

[html] view plain copy
  1. public class TestUserServiceImpl {  
  2.     /**  
  3.      * 用戶接口  
  4.      */  
  5.     private IUserService userServiceImpl;  
  6.       
  7.     public void setUserServiceImpl(IUserService userServiceImpl) {  
  8.         this.userServiceImpl = userServiceImpl;  
  9.     }  
  10.     @Before  
  11.     public void setUp() throws Exception {  
  12.         userServiceImpl = (IUserService) SpringTestHelper.get().getBeanByClass(UserServiceImpl.class);  
  13.     }  
  14.   
  15.     @After  
  16.     public void tearDown() throws Exception {  
  17.     }  
  18.     @Test  
  19.     public void testAdd(){  
  20.         UserEntity entity = new UserEntity();  
  21.         entity.setUserId("000001");  
  22.         entity.setEmpCode("130566");  
  23.         entity.setEmpName("leonardo-zeng");  
  24.         entity.setRole("Java Development Engineer");  
  25.         entity.setTitle("PM");  
  26.         boolean isTrue =userServiceImpl.addUserEntity(entity);  
  27.         Assert.assertTrue(isTrue);  
  28.     }  
  29.       
  30.     @Test  
  31.     public void testQueryById(){  
  32.         UserEntity entity = new UserEntity();  
  33.         entity.setUserId("000001");  
  34.         UserEntity userEntity =userServiceImpl.queryUserEntityByUserId(entity);  
  35.         System.out.println(userEntity);  
  36.     }  
  37. }  
連接redis庫,查詢出來的確值在庫中存在

redis 127.0.0.1:6379> hkeys "\"userEntity\""
1) "\"000001\""
redis 127.0.0.1:6379> hget "\"userEntity\"" "\"000001\""
"{\"@type\":\"com.deppon.cache.entity.UserEntity\",\"empCode\":\"130566\",\"empN
ame\":\"leonardo-zeng\",\"role\":\"Java Development Engineer\",\"title\":\"PM\",
\"userId\":\"000001\"}"
redis 127.0.0.1:6379>
整個demo就這樣了

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章