(1)首先是Cache接口定义:
package org.apache.ibatis.cache;
import java.util.concurrent.locks.ReadWriteLock;
public interface Cache {
String getId();
int getSize();
void putObject(Object key, Object value);
Object getObject(Object key);
Object removeObject(Object key);
void clear();
ReadWriteLock getReadWriteLock();
}
(2)RedisCache接口实现:
package cn.lsoft.undoner.dao.cache;
import java.util.Set;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.ibatis.cache.Cache;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import cn.lsoft.undoner.util.SerializeUtil;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
/*
* 使用第三方缓存服务器,处理二级缓存
*/
public class RedisCache implements Cache {
private static Logger logger = LoggerFactory.getLogger(RedisCache.class);
/** The ReadWriteLock. */
private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
private String id;
private JedisPool jedisPool;
private static final int DB_INDEX = 1;
private final String COMMON_CACHE_KEY = "COM:";
private static final String UTF8 = "utf-8";
private ApplicationContext context;
/**
* 按照一定规则标识key
*/
private String getKey(Object key) {
StringBuilder accum = new StringBuilder();
accum.append(COMMON_CACHE_KEY);
accum.append(this.id).append(":");
accum.append(DigestUtils.md5Hex(String.valueOf(key)));
return accum.toString();
}
/**
* redis key规则前缀
*/
private String getKeys() {
return COMMON_CACHE_KEY + this.id + ":*";
}
public RedisCache() {
}
public RedisCache(final String id) {
if (id == null) {
throw new IllegalArgumentException("必须传入ID");
}
context = new ClassPathXmlApplicationContext("/spring/spring-db-redis-context.xml");
JedisPoolConfig jedisPoolConfig = (JedisPoolConfig) context.getBean("poolConfig");
jedisPool = new JedisPool(jedisPoolConfig, "23.45.6.7", 6379);
logger.debug(">>>>>>>>>>>>>>>>>>>>>MybatisRedisCache:id=" + id);
this.id = id;
}
@Override
public String getId() {
return this.id;
}
@Override
public int getSize() {
Jedis jedis = null;
int result = 0;
boolean borrowOrOprSuccess = true;
try {
jedis = jedisPool.getResource();
jedis.select(DB_INDEX);
Set<byte[]> keys = jedis.keys(getKeys().getBytes(UTF8));
if (null != keys && !keys.isEmpty()) {
result = keys.size();
}
logger.debug(this.id + "---->>>>总缓存数:" + result);
} catch (Exception 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) {
Jedis jedis = null;
boolean borrowOrOprSuccess = true;
try {
jedis = jedisPool.getResource();
jedis.select(DB_INDEX);
byte[] keys = getKey(key).getBytes(UTF8);
jedis.set(keys, SerializeUtil.serialize(value));
logger.debug("添加缓存--------" + this.id + " | " +keys.toString() + ":" + value.toString() );
getSize();
} catch (Exception e) {
borrowOrOprSuccess = false;
if (jedis != null)
jedisPool.returnBrokenResource(jedis);
} finally {
if (borrowOrOprSuccess)
jedisPool.returnResource(jedis);
}
}
@Override
public Object getObject(Object key) {
Jedis jedis = null;
Object value = null;
boolean borrowOrOprSuccess = true;
try {
jedis = jedisPool.getResource();
jedis.select(DB_INDEX);
byte[] keys = getKey(key).getBytes(UTF8);
value = SerializeUtil.unserialize(jedis.get(getKey(key).getBytes(UTF8)));
logger.debug("从缓存中获取-----" + this.id + " | "+keys.toString() + ":" + value.toString());
getSize();
} catch (Exception e) {
borrowOrOprSuccess = false;
if (jedis != null)
jedisPool.returnBrokenResource(jedis);
} finally {
if (borrowOrOprSuccess)
jedisPool.returnResource(jedis);
}
return value;
}
@Override
public Object removeObject(Object key) {
Jedis jedis = null;
Object value = null;
boolean borrowOrOprSuccess = true;
try {
jedis = jedisPool.getResource();
jedis.select(DB_INDEX);
byte[] keys = getKey(key).getBytes(UTF8);
value = jedis.del(getKey(key).getBytes(UTF8));
logger.debug("LRU算法从缓存中移除-----" + this.id + " | " +keys.toString() + ":" + value.toString());
getSize();
} catch (Exception e) {
borrowOrOprSuccess = false;
if (jedis != null)
jedisPool.returnBrokenResource(jedis);
} finally {
if (borrowOrOprSuccess)
jedisPool.returnResource(jedis);
}
return value;
}
@Override
public void clear() {
Jedis jedis = null;
boolean borrowOrOprSuccess = true;
try {
jedis = jedisPool.getResource();
jedis.select(DB_INDEX);
// 如果有删除操作,会影响到整个表中的数据,因此要清空一个mapper的缓存(一个mapper的不同数据操作对应不同的key)
Set<byte[]> keys = jedis.keys(getKeys().getBytes(UTF8));
logger.debug("出现CUD操作,清空对应Mapper缓存======>" + keys.size());
for (byte[] key : keys) {
jedis.del(key);
}
// 下面是网上流传的方法,极大的降低系统性能,没起到加入缓存应有的作用,这是不可取的。
// jedis.flushDB();
// jedis.flushAll();
} catch (Exception e) {
borrowOrOprSuccess = false;
if (jedis != null)
jedisPool.returnBrokenResource(jedis);
} finally {
if (borrowOrOprSuccess)
jedisPool.returnResource(jedis);
}
}
@Override
public ReadWriteLock getReadWriteLock() {
return readWriteLock;
}
}
(3)MemcachedCache接口实现:
package org.mybatis.caches.memcached;
import java.util.concurrent.locks.ReadWriteLock;
import org.apache.ibatis.cache.Cache;
/**
* The Memcached-based Cache implementation.
*
* @author Simone Tripodi
*/
public final class MemcachedCache implements Cache {
private static final MemcachedClientWrapper MEMCACHED_CLIENT = new MemcachedClientWrapper();
/**
* The {@link ReadWriteLock}.
*/
private final ReadWriteLock readWriteLock = new DummyReadWriteLock();
/**
* The cache id.
*/
private final String id;
/**
* Builds a new Memcached-based Cache.
*
* @param id the Mapper id.
*/
public MemcachedCache(final String id) {
this.id = id;
}
/**
* {@inheritDoc}
*/
public void clear() {
MEMCACHED_CLIENT.removeGroup(this.id);
}
/**
* {@inheritDoc}
*/
public String getId() {
return this.id;
}
/**
* {@inheritDoc}
*/
public Object getObject(Object key) {
return MEMCACHED_CLIENT.getObject(key);
}
/**
* {@inheritDoc}
*/
public ReadWriteLock getReadWriteLock() {
return this.readWriteLock;
}
/**
* {@inheritDoc}
*/
public int getSize() {
return Integer.MAX_VALUE;
}
/**
* {@inheritDoc}
*/
public void putObject(Object key, Object value) {
MEMCACHED_CLIENT.putObject(key, value, this.id);
}
/**
* {@inheritDoc}
*/
public Object removeObject(Object key) {
return MEMCACHED_CLIENT.removeObject(key);
}
}
(3)EhcacheCache接口实现:
package org.mybatis.caches.ehcache;
import java.io.IOException;
import java.io.InputStream;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import net.sf.ehcache.CacheManager;
import net.sf.ehcache.Ehcache;
import net.sf.ehcache.Element;
import org.apache.ibatis.cache.Cache;
import org.apache.ibatis.cache.CacheException;
/**
* Cache adapter for Ehcache.
*
* @version $Id: EhcacheCache.java 3454 2010-12-29 20:35:44Z simone.tripodi $
*/
public final class EhcacheCache implements Cache {
/**
* The cache manager reference.
*/
private static final CacheManager CACHE_MANAGER = createCacheManager();
/**
* Looks for "/ehcache.xml" classpath resource and builds the relative
* {@code CacheManager}; if it's no found or it is impossible to load it,
* returns the default manager.
*
* @return the application cache manager.
*/
private static CacheManager createCacheManager() {
CacheManager cacheManager;
InputStream input = EhcacheCache.class.getResourceAsStream("/ehcache.xml");
if (input != null) {
try {
cacheManager = CacheManager.create(input);
} catch (Throwable t) {
cacheManager = CacheManager.create();
} finally {
try {
input.close();
} catch (IOException e) {
}
}
} else {
cacheManager = CacheManager.create();
}
return cacheManager;
}
/**
* The {@code ReadWriteLock}.
*/
private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
/**
* The cache id.
*/
private final String id;
/**
*
*
* @param id
*/
public EhcacheCache(final String id) {
if (id == null) {
throw new IllegalArgumentException("Cache instances require an ID");
}
this.id = id;
if (!CACHE_MANAGER.cacheExists(this.id)) {
CACHE_MANAGER.addCache(this.id);
}
}
/**
* {@inheritDoc}
*/
public void clear() {
this.getCache().removeAll();
}
/**
* {@inheritDoc}
*/
public String getId() {
return this.id;
}
/**
* {@inheritDoc}
*/
public Object getObject(Object key) {
try {
Element cachedElement = this.getCache().get(key.hashCode());
if (cachedElement == null) {
return null;
}
return cachedElement.getObjectValue();
} catch (Throwable t) {
throw new CacheException(t);
}
}
/**
* {@inheritDoc}
*/
public ReadWriteLock getReadWriteLock() {
return this.readWriteLock;
}
/**
* {@inheritDoc}
*/
public int getSize() {
try {
return this.getCache().getSize();
} catch (Throwable t) {
throw new CacheException(t);
}
}
/**
* {@inheritDoc}
*/
public void putObject(Object key, Object value) {
try {
this.getCache().put(new Element(key.hashCode(), value));
} catch (Throwable t) {
throw new CacheException(t);
}
}
/**
* {@inheritDoc}
*/
public Object removeObject(Object key) {
try {
Object obj = this.getObject(key);
this.getCache().remove(key.hashCode());
return obj;
} catch (Throwable t) {
throw new CacheException(t);
}
}
/**
* Returns the ehcache manager for this cache.
*
* @return the ehcache manager for this cache.
*/
private Ehcache getCache() {
return CACHE_MANAGER.getCache(this.id);
}
/**
* {@inheritDoc}
*/
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (!(obj instanceof Cache)) {
return false;
}
Cache otherCache = (Cache) obj;
return this.id.equals(otherCache.getId());
}
/**
* {@inheritDoc}
*/
@Override
public int hashCode() {
return this.id.hashCode();
}
/**
* {@inheritDoc}
*/
@Override
public String toString() {
return "EHCache {"
+ this.id
+ "}";
}
}