redis+mybatis+spring
redis的安装http://liuyieyer.iyunv.com/blog/2078093redis的主从高可用 http://liuyieyer.iyunv.com/blog/2078095
Mybatis 的使用不多说。
Mybatis为了方便我们扩展缓存定义了一个Cache接口,看看ehcache-mybatis的源码就明白了。我们要使用自己的cache同样的实现Cache接口即可。直接上代码
Java代码
[*]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 这个类实现的,照猫画虎,直接我们也继承
Java代码
[*]public class LoggingRedisCache extends LoggingCache {
[*]
[*] public LoggingRedisCache(String id) {
[*] super(new RedisCache(id));
[*] }
[*]
[*]}
在mapper.xml中添加如下cache标签
Xml代码
[*]<!-- 启用缓存 -->
[*] <cache type="cn.seafood.cache.LoggingRedisCache" />
在mybatis的核心文件中开启缓存
Xml代码
[*]<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也改造以下附上代码。
Java代码
[*]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.iyunv.com/blog/2081382
页:
[1]