redis+mybatis+spring

redis的安裝http://liuyieyer.iteye.com/blog/2078093

redis的主從高可用 http://liuyieyer.iteye.com/blog/2078095

Mybatis 的使用不多說。

Mybatis爲了方便我們擴展緩存定義了一個Cache接口,看看ehcache-mybatis的源碼就明白了。我們要使用自己的cache同樣的實現Cache接口即可。直接上代碼

Java代碼  收藏代碼
  1. public class RedisCache   implements Cache {  
  2.         private static Log logger = LogFactory.getLog(RedisCache.class);  
  3.         private Jedis redisClient = createClient();  
  4.         /** The ReadWriteLock. */  
  5.         private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock();  
  6.           
  7.         private String id;  
  8.         public RedisCache(final String id) {  
  9.                 if (id == null) {  
  10.                         throw new IllegalArgumentException("Cache instances require an ID");  
  11.                 }  
  12.                 logger.debug(">>>>>>>>>>>>>>>>>>>>>>>>MybatisRedisCache:id=" + id);  
  13.                 this.id = id;  
  14.         }  
  15.   
  16.         @Override  
  17.         public String getId() {  
  18.                 return this.id;  
  19.         }  
  20.   
  21.         @Override  
  22.         public int getSize() {  
  23.                 return Integer.valueOf(redisClient.dbSize().toString());  
  24.         }  
  25.   
  26.         @Override  
  27.         public void putObject(Object key, Object value) {  
  28.                 logger.debug(">>>>>>>>>>>>>>>>>>>>>>>>putObject:" + key + "=" + value);  
  29.                 redisClient.set(SerializeUtil.serialize(key.toString()), SerializeUtil.serialize(value));  
  30.         }  
  31.   
  32.         @Override  
  33.         public Object getObject(Object key) {  
  34.                 Object value = SerializeUtil.unserialize(redisClient.get(SerializeUtil.serialize(key.toString())));  
  35.                 logger.debug(">>>>>>>>>>>>>>>>>>>>>>>>getObject:" + key + "=" + value);  
  36.                 return value;  
  37.         }  
  38.   
  39.         @Override  
  40.         public Object removeObject(Object key) {  
  41.                 return redisClient.expire(SerializeUtil.serialize(key.toString()), 0);  
  42.         }  
  43.   
  44.         @Override  
  45.         public void clear() {  
  46.                 redisClient.flushDB();  
  47.         }  
  48.   
  49.         @Override  
  50.         public ReadWriteLock getReadWriteLock() {  
  51.                 return readWriteLock;  
  52.         }  
  53.          
  54.         protected  static Jedis createClient() {  
  55.                 try {  
  56.                         JedisPool pool = new JedisPool(new JedisPoolConfig(), "172.60.0.172");  
  57.                        return pool.getResource();  
  58.                 } catch (Exception e) {  
  59.                         e.printStackTrace();  
  60.                 }  
  61.                 throw new RuntimeException("初始化連接池錯誤");  
  62.         }  
  63.           
  64.     
  65.           
  66. }  
  67.   
  68.   
  69. class SerializeUtil {  
  70.         public static byte[] serialize(Object object) {  
  71.                 ObjectOutputStream oos = null;  
  72.                 ByteArrayOutputStream baos = null;  
  73.                 try {  
  74.                         // 序列化  
  75.                         baos = new ByteArrayOutputStream();  
  76.                         oos = new ObjectOutputStream(baos);  
  77.                         oos.writeObject(object);  
  78.                         byte[] bytes = baos.toByteArray();  
  79.                         return bytes;  
  80.                 } catch (Exception e) {  
  81.                         e.printStackTrace();  
  82.                 }  
  83.                 return null;  
  84.         }  
  85.   
  86.         public static Object unserialize(byte[] bytes) {  
  87.                 if(bytes == null)return null;  
  88.                 ByteArrayInputStream bais = null;  
  89.                 try {  
  90.                         // 反序列化  
  91.                         bais = new ByteArrayInputStream(bytes);  
  92.                         ObjectInputStream ois = new ObjectInputStream(bais);  
  93.                         return ois.readObject();  
  94.                 } catch (Exception e) {  
  95.                         e.printStackTrace();  
  96.                 }  
  97.                 return null;  
  98.         }  
  99. }  

 

在看ehcache-mybatis的源碼 它真正使用cache的方式是通過集成org.apache.ibatis.cache.decorators.LoggingCache 這個類實現的,照貓畫虎,直接我們也繼承

Java代碼  收藏代碼
  1. public class LoggingRedisCache extends LoggingCache {  
  2.   
  3.         public LoggingRedisCache(String id) {  
  4.                 super(new RedisCache(id));  
  5.         }  
  6.         
  7. }  

 

在mapper.xml中添加如下cache標籤

 

Xml代碼  收藏代碼
  1. <!-- 啓用緩存 -->  
  2.     <cache type="cn.seafood.cache.LoggingRedisCache" />   

 在mybatis的核心文件中開啓緩存

Xml代碼  收藏代碼
  1. <settings>  
  2.     <!-- 這個配置使全局的映射器啓用或禁用緩存 -->  
  3.     <setting name="cacheEnabled" value="true" />  
  4.  <!-- 對於未知的SQL查詢,允許返回不同的結果集以達到通用的效果 -->      
  5.         <setting name="multipleResultSetsEnabled" value="true"/>  
  6.     <!-- 配置默認的執行器。SIMPLE 執行器沒有什麼特別之處。REUSE 執行器重用預處理語句。BATCH 執行器重用語句和批量更新 -->  
  7.     <setting name="defaultExecutorType" value="REUSE" />  
  8.     <!-- 全局啓用或禁用延遲加載。當禁用時,所有關聯對象都會即時加載。 -->  
  9.     <setting name="lazyLoadingEnabled" value="false" />  
  10.     <setting name="aggressiveLazyLoading" value="true" />  
  11.     <!-- <setting name="enhancementEnabled" value="true"/> -->  
  12.     <!-- 設置超時時間,它決定驅動等待一個數據庫響應的時間。 -->  
  13.     <setting name="defaultStatementTimeout" value="25000" />  
  14. </settings>  

 

<setting name="lazyLoadingEnabled" value="false" />

<setting name="aggressiveLazyLoading" value="true" />

注意着兩個屬性,需要把屬性延遲加載和關聯對象加載給關閉了,不然放進redis中的cglib代理對象,在對數據發生更改的時候,會出錯。

 

 

在上一篇文中的Cahe類存在各種問題如:一直使用同一個連接,每次都創建新的Cache,項目中老是爆出connection timeout 的異常,存儲的key過長等等一系列的問題,解決問題最好的辦法就是看源碼和看官方的文檔說明,jedis的文檔還是夠用的,接下來把cache也改造以下附上代碼。

Java代碼  收藏代碼
  1. package cn.seafood.cache;  
  2.   
  3. import java.io.ByteArrayInputStream;  
  4. import java.io.ByteArrayOutputStream;  
  5. import java.io.ObjectInputStream;  
  6. import java.io.ObjectOutputStream;  
  7. import java.util.concurrent.locks.ReadWriteLock;  
  8. import java.util.concurrent.locks.ReentrantReadWriteLock;  
  9.   
  10. import org.apache.commons.logging.Log;  
  11. import org.apache.commons.logging.LogFactory;  
  12. import org.apache.ibatis.cache.Cache;  
  13.   
  14. import redis.clients.jedis.Jedis;  
  15. import redis.clients.jedis.JedisPool;  
  16. import redis.clients.jedis.JedisPoolConfig;  
  17. import redis.clients.jedis.exceptions.JedisConnectionException;  
  18. import cn.seafood.util.PropertiesLoader;  
  19.   
  20. /** 
  21.  *  
  22. * @ClassName: RedisCache 
  23. * @Description: TODO(使用第三方緩存服務器redis,處理二級緩存) 
  24. * @author LiuYi 
  25. * @date 2014年6月9日 下午1:37:46 
  26. * 
  27.  */  
  28. public class RedisCache   implements Cache {  
  29.         private static Log log = LogFactory.getLog(RedisCache.class);  
  30.         /** The ReadWriteLock. */  
  31.         private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock();  
  32.           
  33.         private String id;  
  34.         public RedisCache(final String id) {  
  35.                 if (id == null) {  
  36.                         throw new IllegalArgumentException("必須傳入ID");  
  37.                 }  
  38.                 log.debug("MybatisRedisCache:id=" + id);  
  39.                 this.id=id;  
  40.         }  
  41.           
  42.         @Override  
  43.         public String getId() {  
  44.                 return this.id;  
  45.         }  
  46.   
  47.         @Override  
  48.         public int getSize() {  
  49.                 Jedis jedis = null;  
  50.                 JedisPool jedisPool = null;  
  51.                 int result = 0;  
  52.                 boolean borrowOrOprSuccess = true;  
  53.                 try {  
  54.                         jedis   = CachePool.getInstance().getJedis();  
  55.                         jedisPool = CachePool.getInstance().getJedisPool();  
  56.                         result = Integer.valueOf(jedis.dbSize().toString());  
  57.                 } catch (JedisConnectionException e) {  
  58.                         borrowOrOprSuccess = false;  
  59.                         if (jedis != null)  
  60.                                 jedisPool.returnBrokenResource(jedis);  
  61.                 } finally {  
  62.                         if (borrowOrOprSuccess)  
  63.                                 jedisPool.returnResource(jedis);  
  64.                 }  
  65.                 return result;  
  66.                    
  67.         }  
  68.   
  69.         @Override  
  70.         public void putObject(Object key, Object value) {  
  71.                 if(log.isDebugEnabled())  
  72.                 log.debug("putObject:" + key.hashCode() + "=" + value);  
  73.                 if(log.isInfoEnabled())  
  74.                 log.info("put to redis sql :" +key.toString());  
  75.                 Jedis jedis = null;  
  76.                 JedisPool jedisPool = null;  
  77.                 boolean borrowOrOprSuccess = true;  
  78.                 try {  
  79.                         jedis   = CachePool.getInstance().getJedis();  
  80.                         jedisPool = CachePool.getInstance().getJedisPool();  
  81.                         jedis.set(SerializeUtil.serialize(key.hashCode()), SerializeUtil.serialize(value));  
  82.                 } catch (JedisConnectionException e) {  
  83.                         borrowOrOprSuccess = false;  
  84.                         if (jedis != null)  
  85.                                 jedisPool.returnBrokenResource(jedis);  
  86.                 } finally {  
  87.                         if (borrowOrOprSuccess)  
  88.                                 jedisPool.returnResource(jedis);  
  89.                 }  
  90.                   
  91.         }  
  92.   
  93.         @Override  
  94.         public Object getObject(Object key) {  
  95.                 Jedis jedis = null;  
  96.                 JedisPool jedisPool = null;  
  97.                 Object value = null;  
  98.                 boolean borrowOrOprSuccess = true;  
  99.                 try {  
  100.                         jedis   = CachePool.getInstance().getJedis();  
  101.                         jedisPool = CachePool.getInstance().getJedisPool();  
  102.                         value  = SerializeUtil.unserialize(jedis.get(SerializeUtil.serialize(key.hashCode())));  
  103.                 } catch (JedisConnectionException e) {  
  104.                         borrowOrOprSuccess = false;  
  105.                         if (jedis != null)  
  106.                                 jedisPool.returnBrokenResource(jedis);  
  107.                 } finally {  
  108.                         if (borrowOrOprSuccess)  
  109.                                 jedisPool.returnResource(jedis);  
  110.                 }  
  111.                 if(log.isDebugEnabled())  
  112.                 log.debug("getObject:" + key.hashCode() + "=" + value);  
  113.                 return value;  
  114.         }  
  115.   
  116.         @Override  
  117.         public Object removeObject(Object key) {  
  118.                 Jedis jedis = null;  
  119.                 JedisPool jedisPool = null;  
  120.                 Object value = null;  
  121.                 boolean borrowOrOprSuccess = true;  
  122.                 try {  
  123.                         jedis   = CachePool.getInstance().getJedis();  
  124.                         jedisPool = CachePool.getInstance().getJedisPool();  
  125.                         value  = jedis.expire(SerializeUtil.serialize(key.hashCode()), 0);  
  126.                 } catch (JedisConnectionException e) {  
  127.                         borrowOrOprSuccess = false;  
  128.                         if (jedis != null)  
  129.                                 jedisPool.returnBrokenResource(jedis);  
  130.                 } finally {  
  131.                         if (borrowOrOprSuccess)  
  132.                                 jedisPool.returnResource(jedis);  
  133.                 }  
  134.                 if(log.isDebugEnabled())  
  135.                 log.debug("getObject:" + key.hashCode() + "=" + value);  
  136.                 return value;  
  137.         }  
  138.   
  139.         @Override  
  140.         public void clear() {  
  141.                 Jedis jedis = null;  
  142.                 JedisPool jedisPool = null;  
  143.                 boolean borrowOrOprSuccess = true;  
  144.                 try {  
  145.                         jedis   = CachePool.getInstance().getJedis();  
  146.                         jedisPool = CachePool.getInstance().getJedisPool();  
  147.                         jedis.flushDB();  
  148.                         jedis.flushAll();  
  149.                 } catch (JedisConnectionException e) {  
  150.                         borrowOrOprSuccess = false;  
  151.                         if (jedis != null)  
  152.                                 jedisPool.returnBrokenResource(jedis);  
  153.                 } finally {  
  154.                         if (borrowOrOprSuccess)  
  155.                                 jedisPool.returnResource(jedis);  
  156.                 }  
  157.         }  
  158.   
  159.         @Override  
  160.         public ReadWriteLock getReadWriteLock() {  
  161.                 return readWriteLock;  
  162.         }  
  163.        /** 
  164.         *  
  165.        * @ClassName: CachePool 
  166.        * @Description: TODO(單例Cache池) 
  167.        * @author LiuYi 
  168.        * @date 2014年6月17日 上午10:50:52 
  169.        * 
  170.         */  
  171.         public static class CachePool {  
  172.                 JedisPool pool;  
  173.                 private static final CachePool cachePool = new CachePool();  
  174.                   
  175.                 public static CachePool getInstance(){  
  176.                         return cachePool;  
  177.                 }  
  178.                 private CachePool() {  
  179.                         JedisPoolConfig config = new JedisPoolConfig();  
  180.                         config.setMaxIdle(100);  
  181.                         config.setMaxWaitMillis(1000l);  
  182.                          PropertiesLoader pl =  new PropertiesLoader("classpath:config/redis.properties");  
  183.                          pool = new JedisPool(config,pl.getProperty("redisvip"));  
  184.                 }  
  185.                 public  Jedis getJedis(){  
  186.                         Jedis jedis = null;  
  187.                         boolean borrowOrOprSuccess = true;  
  188.                         try {  
  189.                                 jedis = pool.getResource();  
  190.                         } catch (JedisConnectionException e) {  
  191.                                 borrowOrOprSuccess = false;  
  192.                                 if (jedis != null)  
  193.                                         pool.returnBrokenResource(jedis);  
  194.                         } finally {  
  195.                                 if (borrowOrOprSuccess)  
  196.                                         pool.returnResource(jedis);  
  197.                         }  
  198.                         jedis = pool.getResource();  
  199.                         return jedis;  
  200.                 }  
  201.                   
  202.                 public JedisPool getJedisPool(){  
  203.                         return this.pool;  
  204.                 }  
  205.                   
  206.         }  
  207.           
  208.           
  209.         public static class SerializeUtil {  
  210.                 public static byte[] serialize(Object object) {  
  211.                         ObjectOutputStream oos = null;  
  212.                         ByteArrayOutputStream baos = null;  
  213.                         try {  
  214.                                 // 序列化  
  215.                                 baos = new ByteArrayOutputStream();  
  216.                                 oos = new ObjectOutputStream(baos);  
  217.                                 oos.writeObject(object);  
  218.                                 byte[] bytes = baos.toByteArray();  
  219.                                 return bytes;  
  220.                         } catch (Exception e) {  
  221.                                 e.printStackTrace();  
  222.                         }  
  223.                         return null;  
  224.                 }  
  225.   
  226.                 public static Object unserialize(byte[] bytes) {  
  227.                         if(bytes == null)return null;  
  228.                         ByteArrayInputStream bais = null;  
  229.                         try {  
  230.                                 // 反序列化  
  231.                                 bais = new ByteArrayInputStream(bytes);  
  232.                                 ObjectInputStream ois = new ObjectInputStream(bais);  
  233.                                 return ois.readObject();  
  234.                         } catch (Exception e) {  
  235.                                 e.printStackTrace();  
  236.                         }  
  237.                         return null;  
  238.                 }  
  239.         }  
  240. }  

 參考鏈接:http://liuyieyer.iteye.com/blog/2081382

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