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

Mybatis+Redis纯注解方案实现缓存案例

2016-11-29 00:00 423 查看
在网络发展迅速,数据交互分分钟冲爆服务器的年代,三岁小孩都不满足拿着网页乱点还狂按F5了,他开始抢着红包点着赞,迷路了还会用百度地图。 作为一只关系型在后台苦不堪言啊! mysql:"你特么刷什么?",oracle:"都说了无聊也别乱点啊你!"。 所以就有了gzip压缩这种减小数据体积得玩意,也有了缓存这种东西。 但是频繁的抢啊刷啊关系型数据库亚历山大啊,于是追求更高更快更强的我们,这次试着用redis+mybatis来实现缓存。
想想Mybatis这只强大的框架,怎么可能没有缓存这玩意呢。人家随身自带一级缓存,可是呀也就个session级别,自认为速度杠杠的,客户端一关就游戏结束。 一级都出马了,二级也要登场呀。MyBatis开启二级缓存的方式也很简单,在其配置文件中加入以下即可。 [code lang="html"] <setting name="cacheEnabled" value="true"/> [/code] 再在其映射的xml文件中简单 [code lang="html"] <cache/> [/code] 如此,一只Application级别的二级缓存就完成了。
那么redis就可以在这个时候闪亮登场了,Mybatis默认的二级缓存一般的需求还是够用的,Redis想要强行插入那就得按它的规矩,其Cache接口。 [code lang="java"] package com.hcq.dao.mybatis.cache; import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock; import org.apache.ibatis.cache.Cache; import org.apache.log4j.LogManager; import org.apache.log4j.Logger; import com.hcq.dao.redis.RedisPool; import redis.clients.jedis.Jedis; public class RedisCache implements Cache{ private static Logger logger = LogManager.getLogger(RedisCache.class);//日志管理 private String id; private Jedis redisClient=createRedis(); //创建一个jedis连接 private ReadWriteLock readWriteLock = new ReentrantReadWriteLock(); //读写锁 public void setReadWriteLock(ReadWriteLock readWriteLock) { this.readWriteLock = readWriteLock; } public RedisCache(String id) { if(id==null){ throw new IllegalArgumentException("Cache instance requires an ID"); } logger.debug("create an cache instance with id"+id); this.id=id; } public String getId() { return this.id; } /**从连接池中取 *
@return */ private static Jedis createRedis() { //从连接池获取redis连接 Jedis jedis =RedisPool.getPool().getResource(); return jedis; } public void putObject(Object key, Object value) { byte[] keybyte=SerializableUtil.serialize(key); byte[]valuebyte=SerializableUtil.serialize(value); this.redisClient.set(keybyte, valuebyte); } public Object getObject(Object key) { //缓存穿透 byte[] values=this.redisClient.get(SerializableUtil.serialize(key)); //算法:计算一定时间内没有命中的键,存起来 key->value if(values==null){ return null; } Object obj =SerializableUtil.unserizlize(values); return obj; } public Object removeObject(Object key) { byte[]keybyte=SerializableUtil.serialize(key); return this.redisClient.expire(keybyte, 0); } public void clear() { this.redisClient.flushDB(); } public int getSize() { Long size = this.redisClient.dbSize(); int s =Integer.valueOf(size+""); return s; } public ReadWriteLock getReadWriteLock() { return readWriteLock; } } [/code] 然后就是一个redis连接池,方便获取redis连接和管理。 [code lang="java"] package com.hcq.dao.redis; import java.util.ResourceBundle; import redis.clients.jedis.JedisPool; import redis.clients.jedis.JedisPoolConfig; public class RedisPool { private static JedisPool pool; private RedisPool(){ ResourceBundle bundle =ResourceBundle.getBundle("redis"); //bundle就是一个map if(bundle==null){ throw new IllegalArgumentException("[redis.properties] is not find "); } JedisPoolConfig config = new JedisPoolConfig(); config.setMaxTotal(Integer.valueOf(bundle.getString("redis.pool.maxActive"))); config.setMaxIdle(Integer.valueOf(bundle.getString("redis.pool.maxIdle"))); config.setMaxWaitMillis(Long.valueOf(bundle.getString("redis.pool.maxWait"))); config.setTestOnBorrow(Boolean.valueOf(bundle.getString("redis.pool.testOnBorrow"))); config.setTestOnReturn(Boolean.valueOf(bundle.getString("redis.pool.testOnReturn"))); //创建连接池 pool =new JedisPool(config,bundle.getString("redis.ip"),Integer.valueOf(bundle.getString("redis.port"))); } public synchronized static JedisPool getPool() { if(pool==null){ new RedisPool(); } return pool; } } [/code] 连接池需要读取的文件配置,redis.properties。 [code lang="xml"] redis.pool.maxActive=1024 redis.pool.maxIdle=200 redis.pool.maxWait=1000 redis.pool.testOnBorrow=true redis.pool.testOnReturn=true redis.ip=127.0.0.1 //本机 redis.port=6379 //默认端口 [/code] 这里做一个简单的查询,查询所有的电影类型。在bean层,定义一个电影类型对象,必须实现序列化接口。 [code lang="java"] package com.hcq.bean; import java.io.Serializable; public class Mtype implements Serializable{ private static final long serialVersionUID = 1590366991914489696L; private int tid; private String tname; public int getTid() { return tid; } public void setTid(int tid) { this.tid = tid; } public String getTname() { return tname; } public void setTname(String tname) { this.tname = tname; } @Override public String toString() { return "Mtype [tid=" + tid + ", tname=" + tname + "]"; } } [/code] redis的存对象需将其序列化,而查到的数据又通过反序列化成为对象,下面是个序列化工具类。 [code lang="java"] package com.hcq.dao.mybatis.cache; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; public class SerializableUtil { //序列化 public static byte [] serialize(Object obj){ ObjectOutputStream obi=null; ByteArrayOutputStream bai=null; byte[] bs=null; try { bai=new ByteArrayOutputStream(); obi=new ObjectOutputStream(bai); obi.writeObject(obj); bs=bai.toByteArray(); } catch (IOException e) { e.printStackTrace(); }finally{ if(bai!=null){ try{ bai.close(); }catch(IOException e){ e.printStackTrace(); } } } return bs; } //反序列化 public static Object unserizlize(byte[] bs){ ByteArrayInputStream bis=null; Object obj=null; try { bis=new ByteArrayInputStream(bs); ObjectInputStream ois=new ObjectInputStream(bis); obj=ois.readObject(); } catch (Exception e) { e.printStackTrace(); }finally{ if(bis!=null){ try{ bis.close(); }catch (IOException e) { e.printStackTrace(); } } } return obj; } } [/code] 然后在Dao层,使用注解方案配置自定义二级缓存,及其实现类。 [code lang="java"] package com.hcq.dao; import java.util.List; import org.apache.ibatis.annotations.CacheNamespace; import org.apache.ibatis.annotations.Select; import com.hcq.bean.Ctype; @CacheNamespace(implementation=(com.hcq.dao.mybatis.cache.RedisCache.class)) public interface CtypeDao { @Select("select *from ctype") public List<Ctype>findAllCtype(); } [/code] 至此,一个用redis+mybatis做的缓存就基本实现了。最后的操作就剩下前台和action类的简单实现了,就不再贴代码了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: