redis+mybatis+spring

cary_25 8年前發布 | 23K 次閱讀 JEE框架

來自: http://canann.iteye.com/blog/2170933


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

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

Mybatis 的使用不多說。

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

public class RedisCache   implements Cache {  
        private static Log logger = LogFactory.getLog(RedisCache.class);  
        private Jedis redisClient = createClient();  
        /** The ReadWriteLock. */  
        private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock();  
          
        private String id;  
        public RedisCache(final String id) {  
                if (id == null) {  
                        throw new IllegalArgumentException("Cache instances require an ID");  
                }  
                logger.debug(">>>>>>>>>>>>>>>>>>>>>>>>MybatisRedisCache:id=" + id);  
                this.id = id;  
        }  
  
        @Override  
        public String getId() {  
                return this.id;  
        }  
  
        @Override  
        public int getSize() {  
                return Integer.valueOf(redisClient.dbSize().toString());  
        }  
  
        @Override  
        public void putObject(Object key, Object value) {  
                logger.debug(">>>>>>>>>>>>>>>>>>>>>>>>putObject:" + key + "=" + value);  
                redisClient.set(SerializeUtil.serialize(key.toString()), SerializeUtil.serialize(value));  
        }  
  
        @Override  
        public Object getObject(Object key) {  
                Object value = SerializeUtil.unserialize(redisClient.get(SerializeUtil.serialize(key.toString())));  
                logger.debug(">>>>>>>>>>>>>>>>>>>>>>>>getObject:" + key + "=" + value);  
                return value;  
        }  
  
        @Override  
        public Object removeObject(Object key) {  
                return redisClient.expire(SerializeUtil.serialize(key.toString()), 0);  
        }  
  
        @Override  
        public void clear() {  
                redisClient.flushDB();  
        }  
  
        @Override  
        public ReadWriteLock getReadWriteLock() {  
                return readWriteLock;  
        }  
         
        protected  static Jedis createClient() {  
                try {  
                        JedisPool pool = new JedisPool(new JedisPoolConfig(), "172.60.0.172");  
                       return pool.getResource();  
                } catch (Exception e) {  
                        e.printStackTrace();  
                }  
                throw new RuntimeException("初始化連接池錯誤");  
        }  
          
    
          
}  
  
  
class SerializeUtil {  
        public static byte[] serialize(Object object) {  
                ObjectOutputStream oos = null;  
                ByteArrayOutputStream baos = null;  
                try {  
                        // 序列化  
                        baos = new ByteArrayOutputStream();  
                        oos = new ObjectOutputStream(baos);  
                        oos.writeObject(object);  
                        byte[] bytes = baos.toByteArray();  
                        return bytes;  
                } catch (Exception e) {  
                        e.printStackTrace();  
                }  
                return null;  
        }  
  
        public static Object unserialize(byte[] bytes) {  
                if(bytes == null)return null;  
                ByteArrayInputStream bais = null;  
                try {  
                        // 反序列化  
                        bais = new ByteArrayInputStream(bytes);  
                        ObjectInputStream ois = new ObjectInputStream(bais);  
                        return ois.readObject();  
                } catch (Exception e) {  
                        e.printStackTrace();  
                }  
                return null;  
        }  
}

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

public class LoggingRedisCache extends LoggingCache {  
  
        public LoggingRedisCache(String id) {  
                super(new RedisCache(id));  
        }  
        
}

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

<!-- 啟用緩存 -->  
    <cache type="cn.seafood.cache.LoggingRedisCache" />

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

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

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

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

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

 

 

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

package cn.seafood.cache;  
  
import java.io.ByteArrayInputStream;  
import java.io.ByteArrayOutputStream;  
import java.io.ObjectInputStream;  
import java.io.ObjectOutputStream;  
import java.util.concurrent.locks.ReadWriteLock;  
import java.util.concurrent.locks.ReentrantReadWriteLock;  
  
import org.apache.commons.logging.Log;  
import org.apache.commons.logging.LogFactory;  
import org.apache.ibatis.cache.Cache;  
  
import redis.clients.jedis.Jedis;  
import redis.clients.jedis.JedisPool;  
import redis.clients.jedis.JedisPoolConfig;  
import redis.clients.jedis.exceptions.JedisConnectionException;  
import cn.seafood.util.PropertiesLoader;  
  
/** 
 *  
* @ClassName: RedisCache 
* @Description: TODO(使用第三方緩存服務器redis,處理二級緩存) 
* @author LiuYi 
* @date 2014年6月9日 下午1:37:46 
* 
 */  
public class RedisCache   implements Cache {  
        private static Log log = LogFactory.getLog(RedisCache.class);  
        /** The ReadWriteLock. */  
        private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock();  
          
        private String id;  
        public RedisCache(final String id) {  
                if (id == null) {  
                        throw new IllegalArgumentException("必須傳入ID");  
                }  
                log.debug("MybatisRedisCache:id=" + id);  
                this.id=id;  
        }  
          
        @Override  
        public String getId() {  
                return this.id;  
        }  
  
        @Override  
        public int getSize() {  
                Jedis jedis = null;  
                JedisPool jedisPool = null;  
                int result = 0;  
                boolean borrowOrOprSuccess = true;  
                try {  
                        jedis   = CachePool.getInstance().getJedis();  
                        jedisPool = CachePool.getInstance().getJedisPool();  
                        result = Integer.valueOf(jedis.dbSize().toString());  
                } catch (JedisConnectionException e) {  
                        borrowOrOprSuccess = false;  
                        if (jedis != null)  
                                jedisPool.returnBrokenResource(jedis);  
                } finally {  
                        if (borrowOrOprSuccess)  
                                jedisPool.returnResource(jedis);  
                }  
                return result;  
                   
        }  
  
        @Override  
        public void putObject(Object key, Object value) {  
                if(log.isDebugEnabled())  
                log.debug("putObject:" + key.hashCode() + "=" + value);  
                if(log.isInfoEnabled())  
                log.info("put to redis sql :" +key.toString());  
                Jedis jedis = null;  
                JedisPool jedisPool = null;  
                boolean borrowOrOprSuccess = true;  
                try {  
                        jedis   = CachePool.getInstance().getJedis();  
                        jedisPool = CachePool.getInstance().getJedisPool();  
                        jedis.set(SerializeUtil.serialize(key.hashCode()), SerializeUtil.serialize(value));  
                } catch (JedisConnectionException e) {  
                        borrowOrOprSuccess = false;  
                        if (jedis != null)  
                                jedisPool.returnBrokenResource(jedis);  
                } finally {  
                        if (borrowOrOprSuccess)  
                                jedisPool.returnResource(jedis);  
                }  
                  
        }  
  
        @Override  
        public Object getObject(Object key) {  
                Jedis jedis = null;  
                JedisPool jedisPool = null;  
                Object value = null;  
                boolean borrowOrOprSuccess = true;  
                try {  
                        jedis   = CachePool.getInstance().getJedis();  
                        jedisPool = CachePool.getInstance().getJedisPool();  
                        value  = SerializeUtil.unserialize(jedis.get(SerializeUtil.serialize(key.hashCode())));  
                } catch (JedisConnectionException e) {  
                        borrowOrOprSuccess = false;  
                        if (jedis != null)  
                                jedisPool.returnBrokenResource(jedis);  
                } finally {  
                        if (borrowOrOprSuccess)  
                                jedisPool.returnResource(jedis);  
                }  
                if(log.isDebugEnabled())  
                log.debug("getObject:" + key.hashCode() + "=" + value);  
                return value;  
        }  
  
        @Override  
        public Object removeObject(Object key) {  
                Jedis jedis = null;  
                JedisPool jedisPool = null;  
                Object value = null;  
                boolean borrowOrOprSuccess = true;  
                try {  
                        jedis   = CachePool.getInstance().getJedis();  
                        jedisPool = CachePool.getInstance().getJedisPool();  
                        value  = jedis.expire(SerializeUtil.serialize(key.hashCode()), 0);  
                } catch (JedisConnectionException e) {  
                        borrowOrOprSuccess = false;  
                        if (jedis != null)  
                                jedisPool.returnBrokenResource(jedis);  
                } finally {  
                        if (borrowOrOprSuccess)  
                                jedisPool.returnResource(jedis);  
                }  
                if(log.isDebugEnabled())  
                log.debug("getObject:" + key.hashCode() + "=" + value);  
                return value;  
        }  
  
        @Override  
        public void clear() {  
                Jedis jedis = null;  
                JedisPool jedisPool = null;  
                boolean borrowOrOprSuccess = true;  
                try {  
                        jedis   = CachePool.getInstance().getJedis();  
                        jedisPool = CachePool.getInstance().getJedisPool();  
                        jedis.flushDB();  
                        jedis.flushAll();  
                } catch (JedisConnectionException e) {  
                        borrowOrOprSuccess = false;  
                        if (jedis != null)  
                                jedisPool.returnBrokenResource(jedis);  
                } finally {  
                        if (borrowOrOprSuccess)  
                                jedisPool.returnResource(jedis);  
                }  
        }  
  
        @Override  
        public ReadWriteLock getReadWriteLock() {  
                return readWriteLock;  
        }  
       /** 
        *  
       * @ClassName: CachePool 
       * @Description: TODO(單例Cache池) 
       * @author LiuYi 
       * @date 2014年6月17日 上午10:50:52 
       * 
        */  
        public static class CachePool {  
                JedisPool pool;  
                private static final CachePool cachePool = new CachePool();  
                  
                public static CachePool getInstance(){  
                        return cachePool;  
                }  
                private CachePool() {  
                        JedisPoolConfig config = new JedisPoolConfig();  
                        config.setMaxIdle(100);  
                        config.setMaxWaitMillis(1000l);  
                         PropertiesLoader pl =  new PropertiesLoader("classpath:config/redis.properties");  
                         pool = new JedisPool(config,pl.getProperty("redisvip"));  
                }  
                public  Jedis getJedis(){  
                        Jedis jedis = null;  
                        boolean borrowOrOprSuccess = true;  
                        try {  
                                jedis = pool.getResource();  
                        } catch (JedisConnectionException e) {  
                                borrowOrOprSuccess = false;  
                                if (jedis != null)  
                                        pool.returnBrokenResource(jedis);  
                        } finally {  
                                if (borrowOrOprSuccess)  
                                        pool.returnResource(jedis);  
                        }  
                        jedis = pool.getResource();  
                        return jedis;  
                }  
                  
                public JedisPool getJedisPool(){  
                        return this.pool;  
                }  
                  
        }  
          
          
        public static class SerializeUtil {  
                public static byte[] serialize(Object object) {  
                        ObjectOutputStream oos = null;  
                        ByteArrayOutputStream baos = null;  
                        try {  
                                // 序列化  
                                baos = new ByteArrayOutputStream();  
                                oos = new ObjectOutputStream(baos);  
                                oos.writeObject(object);  
                                byte[] bytes = baos.toByteArray();  
                                return bytes;  
                        } catch (Exception e) {  
                                e.printStackTrace();  
                        }  
                        return null;  
                }  
  
                public static Object unserialize(byte[] bytes) {  
                        if(bytes == null)return null;  
                        ByteArrayInputStream bais = null;  
                        try {  
                                // 反序列化  
                                bais = new ByteArrayInputStream(bytes);  
                                ObjectInputStream ois = new ObjectInputStream(bais);  
                                return ois.readObject();  
                        } catch (Exception e) {  
                                e.printStackTrace();  
                        }  
                        return null;  
                }  
        }  
}

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


 本文由用戶 cary_25 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!