本篇文章主要介绍了" redis mybatis spring整合",主要涉及到方面的内容,对于其他数据库感兴趣的同学可以参考一下:
最近想在框架里面加入redis,替换原因呢其实也没有,就是单纯的想替换掉 ---维基百科:redis介绍一般开发中用户状态使用session或者cookie,两...
最近想在框架里面加入redis,替换原因呢其实也没有,就是单纯的想替换掉 
---维基百科:redis介绍
一般开发中用户状态使用session或者cookie,两种方式各种利弊。
Session:在InProc模式下容易丢失,并且引起并发问题。如果使用SQLServer或者SQLServer模式又消耗了性能
Cookie则容易将一些用户信息暴露,加解密同样也消耗了性能。
Redis采用这样的方案解决了几个问题,
1.Redis存取速度快。
2.用户数据不容易丢失。
3.用户多的情况下容易支持集群。
4.能够查看在线用户。
5.能够实现用户一处登录。(通过代码实现,后续介绍)
6.支持持久化。(当然可能没什么用)
然后研究了2天怎么去整合spring mybatis和redis...
新创建一个redis工具类
package cx.common.utils.redis;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.apache.log4j.Logger;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
/**
*
* @ClassName RedisUtils
* @Description Redis缓存工具类
* @author K
* @Date 2016年6月22日 下午6:08:52
* @version 1.0.0
*/
public class RedisUtils {
private static Logger logger = Logger.getLogger(RedisUtils.class);
/** 默认缓存时间 */
private static final int DEFAULT_CACHE_SECONDS = 60 * 60 * 1;// 单位秒 设置成一个钟
/** 连接池 **/
private static JedisPool jedisPool;
static {
if (jedisPool == null) {
JedisPoolConfig config = new JedisPoolConfig();
//控制一个pool可分配多少个jedis实例,通过pool.getResource()来获取;
//如果赋值为-1,则表示不限制;如果pool已经分配了maxActive个jedis实例,则此时pool的状态为exhausted(耗尽)。
config.setMaxIdle(8);
//控制一个pool最多有多少个状态为idle(空闲的)的jedis实例。
config.setMaxTotal(8);
//表示当borrow(引入)一个jedis实例时,最大的等待时间,如果超过等待时间,则直接抛出JedisConnectionException;
config.setMaxWaitMillis(1000 * 100);
//在borrow一个jedis实例时,是否提前进行validate操作;如果为true,则得到的jedis实例均是可用的;
config.setTestOnBorrow(true);
config.setMinEvictableIdleTimeMillis(60000);
config.setTimeBetweenEvictionRunsMillis(30000);
config.setNumTestsPerEvictionRun(-1);
config.setMinIdle(0);
jedisPool = new JedisPool(config, "192.168.11.247", 6379);
}
}
/**
* 释放redis资源
*
* @param jedis
*/
private static void releaseResource(Jedis jedis) {
if (jedis != null) {
jedisPool.returnResource(jedis);
}
}
/**
* 删除Redis中的所有key
*
* @param jedis
* @throws Exception
*/
public static void flushAll() {
Jedis jedis = null;
try {
jedis = jedisPool.getResource();
jedis.flushAll();
} catch (Exception e) {
logger.error("Cache清空失败:" + e);
} finally {
releaseResource(jedis);
}
}
/**
* 保存一个对象到Redis中(缓存过期时间:使用此工具类中的默认时间) .
*
* @param key
* 键 .
* @param object
* 缓存对象 .
* @return true or false .
* @throws Exception
*/
public static Boolean save(Object key, Object object) {
return save(key, object, DEFAULT_CACHE_SECONDS);
}
/**
* 保存一个对象到redis中并指定过期时间
*
* @param key
* 键 .
* @param object
* 缓存对象 .
* @param seconds
* 过期时间(单位为秒).
* @return true or false .
*/
public static Boolean save(Object key, Object object, int seconds) {
Jedis jedis = null;
try {
jedis = jedisPool.getResource();
jedis.set(SerializeUtils.serialize(key), SerializeUtils.serialize(object));
jedis.expire(SerializeUtils.serialize(key), seconds);
return true;
} catch (Exception e) {
logger.error("Cache保存失败:" + e);
return false;
} finally {
releaseResource(jedis);
}
}
/**
* 根据缓存键获取Redis缓存中的值.
*
* @param key
* 键.
* @return Object .
* @throws Exception
*/
public static Object get(Object key) {
Jedis jedis = null;
try {
jedis = jedisPool.getResource();
byte[] obj = jedis.get(SerializeUtils.serialize(key));
return obj == null ? null : SerializeUtils.unSerialize(obj);
} catch (Exception e) {
logger.error("Cache获取失败:" + e);
return null;
} finally {
releaseResource(jedis);
}
}
/**
* 根据缓存键清除Redis缓存中的值.
*
* @param key
* @return
* @throws Exception
*/
public static Boolean del(Object key) {
Jedis jedis = null;
try {
jedis = jedisPool.getResource();
jedis.del(SerializeUtils.serialize(key));
return true;
} catch (Exception e) {
logger.error("Cache删除失败:" + e);
return false;
} finally {
releaseResource(jedis);
}
}
/**
* 根据缓存键清除Redis缓存中的值.
*
* @param keys
* @return
* @throws Exception
*/
public static Boolean del(Object... keys) {
Jedis jedis = null;
try {
jedis = jedisPool.getResource();
jedis.del(SerializeUtils.serialize(keys));
return true;
} catch (Exception e) {
logger.error("Cache删除失败:" + e);
return false;
} finally {
releaseResource(jedis);
}
}
/**
*
* @param key
* @param seconds
* 超时时间(单位为秒)
* @return
*/
public static Boolean expire(Object key, int seconds) {
Jedis jedis = null;
try {
jedis = jedisPool.getResource();
jedis.expire(SerializeUtils.serialize(key), seconds);
return true;
} catch (Exception e) {
logger.error("Cache设置超时时间失败:" + e);
return false;
} finally {
releaseResource(jedis);
}
}
/**
* 添加一个内容到指定key的hash中
*
* @param key
* @param field
* @param value
* @return
*/
public static Boolean addHash(String key, Object field, Object value) {
Jedis jedis = null;
try {
jedis = jedisPool.getResource();
jedis.hset(SerializeUtils.serialize(key), SerializeUtils.serialize(field), SerializeUtils.serialize(value));
return true;
} catch (Exception e) {
logger.error("Cache保存失败:" + e);
return false;
} finally {
releaseResource(jedis);
}
}
/**
* 从指定hash中拿一个对象
*
* @param key
* @param field
* @return
*/
public static Object getHash(Object key, Object field) {
Jedis jedis = null;
try {
jedis = jedisPool.getResource();
byte[] obj = jedis.hget(SerializeUtils.serialize(key), SerializeUtils.serialize(field));
return SerializeUtils.unSerialize(obj);
} catch (Exception e) {
logger.error("Cache读取失败:" + e);
return null;
} finally {
releaseResource(jedis);
}
}
/**
* 从hash中删除指定filed的值
*
* @param key
* @param field
* @return
*/
public static Boolean delHash(Object key, Object field) {
Jedis jedis = null;
try {
jedis = jedisPool.getResource();
long result = jedis.hdel(SerializeUtils.serialize(key), SerializeUtils.serialize(field));
return result == 1 ? true : false;
} catch (Exception e) {
logger.error("Cache删除失败:" + e);
return null;
} finally {
releaseResource(jedis);
}
}
/**
* 拿到缓存中所有符合pattern的key
*
* @param pattern
* @return
*/
public static Set keys(String pattern) {
Jedis jedis = null;
try {
jedis = jedisPool.getResource();
Set allKey = jedis.keys(("*" + pattern + "*").getBytes());
return allKey;
} catch (Exception e) {
logger.error("Cache获取失败:" + e);
return new HashSet();
} finally {
releaseResource(jedis);
}
}
/**
* 获得hash中的所有key value
*
* @param key
* @return
*/
public static Map getAllHash(Object key) {
Jedis jedis = null;
try {
jedis = jedisPool.getResource();
Map map = jedis.hgetAll(SerializeUtils.serialize(key));
return map;
} catch (Exception e) {
logger.error("Cache获取失败:" + e);
return null;
} finally {
releaseResource(jedis);
}
}
/**
* 判断一个key是否存在
*
* @param key
* @return
*/
public static Boolean exists(Object key) {
Jedis jedis = null;
Boolean result = false;
try {
jedis = jedisPool.getResource();
result = jedis.exists(SerializeUtils.serialize(key));
return result;
} catch (Exception e) {
logger.error("Cache获取失败:" + e);
return false;
} finally {
releaseResource(jedis);
}
}
public void setjedisPool(JedisPool jedisPool) {
RedisUtils.jedisPool = jedisPool;
}
public static JedisPool getjedisPool() {
return jedisPool;
}
}
创建一个序列化工具类
package cx.common.utils.redis;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import org.apache.log4j.Logger;
/**
*
* @ClassName SerializeUtils
* @Description 序列化工具
* @author K
* @Date 2016年6月24日 上午9:44:38
* @version 1.0.0
*/
public class SerializeUtils {
private static Logger logger = Logger.getLogger(SerializeUtils.class);
/**
*
* @Description 序列化
* @param object
* @return
* @throws Exception
*/
public static byte[] serialize(Object object) throws Exception {
if(object == null) return null;
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) {
logger.error(e);
throw e;
}
}
/**
*
* @Description 反序列化
* @param bytes
* @return
* @throws Exception
*/
public static Object unSerialize(byte[] bytes) throws Exception {
if(bytes == null) return null;
ByteArrayInputStream bais = null;
try {
// 反序列化
bais = new ByteArrayInputStream(bytes);
ObjectInputStream ois = new ObjectInputStream(bais);
return ois.readObject();
} catch (Exception e) {
logger.error(e);
throw e;
}
}
}
redis 管理
package cx.common.utils.redis.springImpl;
import java.util.Collection;
import org.springframework.cache.Cache;
import org.springframework.cache.support.AbstractCacheManager;
/**
*
* @ClassName CacheManager
* @Description 继承了 spring 的 AbstractCacheManager 管理 RedisCache 类缓存管理
* @author K
* @Date 2016年6月27日 下午1:55:49
* @version 1.0.0
* @param
*/
public class CacheManager extends AbstractCacheManager {
private Collection extends RedisCache> caches;
public void setCaches(Collection extends RedisCache> caches) {
this.caches = caches;
}
@Override
protected Collection extends Cache> loadCaches() {
return this.caches;
}
}
继承spring缓存来实现redis
package cx.service.shiro.mybatis.cache.redis;
import org.apache.ibatis.cache.decorators.LoggingCache;
/**
*
* @ClassName MybatiesRedisCache
* @Description 根据SPring API 自定义一个缓存类 ,实现Redis 缓存
* @author K
* @Date 2016年6月27日 下午3:30:52
* @version 1.0.0
*/
public class MybatiesRedisCache extends LoggingCache {
public MybatiesRedisCache(String id) {
super(new RedisCache(id));
}
}
redis初始化 和连接池
package cx.service.shiro.mybatis.cache.redis;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.exceptions.JedisConnectionException;
import cx.common.utils.redis.RedisUtils;
/**
*
* @ClassName CachePool
* @Description redis 初始化
* 由于需结合Mybatis实现 不与Spring redis注解实现混用。
* 与Spring redis注解实现 各独立实现各自功能。
* @author K
* @Date 2016年6月27日 下午3:29:03
* @version 1.0.0
*/
public class CachePool {
JedisPool pool;
private static final CachePool cachePool = new CachePool();
private RedisUtils readisUtils = new RedisUtils();
/**单例模式*/
public static CachePool getInstance(){
return cachePool;
}
/**初始化*/
private CachePool() {
pool = readisUtils.getjedisPool();
}
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;
}
}
实现
package cx.service.shiro.mybatis.cache.redis;
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 cx.common.utils.redis.SerializeUtils;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.exceptions.JedisConnectionException;
/**
*
* @ClassName RedisCache
* @Description Mybatis 接口 实现 redis 功能 类
* @author K
* @Date 2016年6月27日 下午3:29:45
* @version 1.0.0
*/
public class RedisCache implements Cache {
private static Log log = LogFactory.getLog(RedisCache.class);
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(SerializeUtils.serialize(key.hashCode()), SerializeUtils.serialize(value));
} catch (JedisConnectionException e) {
borrowOrOprSuccess = false;
if (jedis != null)
jedisPool.returnBrokenResource(jedis);
} catch (Exception e) {
e.printStackTrace();
} 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();
System.out.println(key.hashCode());
System.out.println(SerializeUtils.serialize(key.hashCode()));
System.out.println(jedis.get(SerializeUtils.serialize(key.hashCode())));
value = SerializeUtils.unSerialize(jedis.get(SerializeUtils.serialize(key.hashCode())));
} catch (JedisConnectionException e) {
borrowOrOprSuccess = false;
if (jedis != null)
jedisPool.returnBrokenResource(jedis);
} catch (Exception e) {
e.printStackTrace();
} 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(SerializeUtils.serialize(key.hashCode()), 0);
} catch (JedisConnectionException e) {
borrowOrOprSuccess = false;
if (jedis != null)
jedisPool.returnBrokenResource(jedis);
} catch (Exception e) {
e.printStackTrace();
} 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;
}
}
redis配置文件spring-jedis.xml
mybatis配置文件mybatis-config.xml中开启缓存
添加缓存到mybatis.mapper sql文中
SYS_CONFIG
and id = #{id}
and name = #{name}
and config_keys = #{configKeys}
and config_value = #{configValue}
and description = #{description}
and is_sys = #{isSys}
and create_by = #{createBy}
and create_date = #{createDate}
and update_by = #{updateBy}
and update_date = #{updateDate}
and status = #{status}
flushCache="true">
insert into
(id,name,config_keys,config_value,description,is_sys,create_by,create_date,update_by,update_date,status)
values (
#{id},#{name},#{configKeys},#{configValue},#{description},#{isSys},#{createBy},#{createDate},#{updateBy},#{updateDate},#{status})
flushCache="true">
update
id = #{id},
name = #{name},
config_keys = #{configKeys},
config_value = #{configValue},
description = #{description},
is_sys = #{isSys},
create_by = #{createBy},
create_date = #{createDate},
update_by = #{updateBy},
update_date = #{updateDate},
status = #{status}
flushCache="false" useCache="true">
SELECT * FROM
flushCache="true">
insert into
(id,name,config_keys,config_value,description,is_sys,create_by,create_date,update_by,update_date,status)
values (
#{id},#{name},#{configKeys},#{configValue},#{description},#{isSys},#{createBy},#{createDate},#{updateBy},#{updateDate},#{status})
flushCache="false" useCache="true">
SELECT * FROM
在MyBatis中有flushCache、useCache这两个配置属性,分为下面几种情况:
(1)当为select语句时:
flushCache默认为false,表示任何时候语句被调用,都不会去清空本地缓存和二级缓存。
useCache默认为true,表示会将本条语句的结果进行二级缓存。
(2)当为insert、update、delete语句时:
flushCache默认为true,表示任何时候语句被调用,都会导致本地缓存和二级缓存被清空。
useCache属性在该情况下没有。
上面的信息我是从MyBatis官方文档中找到的,会发现当为select语句的时候,如果没有去配置flushCache、useCache,那么默认是启用缓存的,所以,如果有必要,那么就需要人工修改配置,修改结果类似下面:
然后编写测试类