1、缓存管理接口定义
public interface CacheManager {
/**
* 设置缓存.
*
* @param type
* @param key
* @param data
* @param expired 缓存有效时间,单位ms
*/
void put(CacheEnum type, String key, Object data, long cacheTime);
/**
* 获取数据.
* <p>
* <B>返回实际缓存数据,非封装数据.</B>
* 当数据过期,返回<code>NULL</code>
* </p>
* @param type
* @param key
* @return
*/
Object get(CacheEnum type, String key);
/**
* 删除本地KEY.
*
* @param type
* @param key
*/
void remove(CacheEnum type, String key);
/**
* 删除某一类本地缓存.
*
* @param type
*/
void clean(CacheEnum type);
/**
* dump数据.
*
* @return
*/
Map<String, String> dump();
}
2、定义缓存类别
</pre><p><pre name="code" class="java">public enum CacheEnum {
/** 默认枚举. */
DEFAULT("DEFAULT"),
……
private String code;
CacheEnum(String code) {
this.code = code;
}
/**
* 根据code获取枚举.
*
* @param code
* @return
*/
public static CacheEnum getEnumByCode(String code) {
if (StringUtils.isEmpty(code)) {
return null;
}
for (CacheEnum cache : values()) {
if (StringUtils.equals(code, cache.getCode())) {
return cache;
}
}
return null;
}
/**
* Getter method for property <tt>code</tt>.
*
* @return property value of code
*/
public String getCode() {
return code;
}
}
3、本地缓存实际存储位置
public class LRULinkedHashMap<K, V> extends LinkedHashMap<K, V> {
/** serialVersionUID. */
private static final long serialVersionUID = -8176202087056001991L;
/** 加载因子. */
private static final float DEFAULT_LOAD_FACTOR = 0.75f;
/** 最大容量. */
private int maxCapacity;
/** 植入锁. */
private final Lock lock = new ReentrantLock();
/**
* 构造器.
* @param maxCapacity 最大容量
*/
public LRULinkedHashMap(int maxCapacity) {
super(maxCapacity, DEFAULT_LOAD_FACTOR, Boolean.TRUE);
this.maxCapacity = maxCapacity;
}
/**
*
* @see java.util.LinkedHashMap#removeEldestEntry(java.util.Map.Entry)
*/
protected boolean removeEldestEntry(Map.Entry<K, V> eldest) {
return size() > maxCapacity;
}
/**
*
* @see java.util.HashMap#containsKey(java.lang.Object)
*/
public boolean containsKey(Object key) {
lock.lock();
try {
return super.containsKey(key);
} finally {
lock.unlock();
}
}
/**
*
* @see java.util.LinkedHashMap#get(java.lang.Object)
*/
public V get(Object key) {
lock.lock();
try {
return super.get(key);
} finally {
lock.unlock();
}
}
/**
*
* @see java.util.HashMap#put(java.lang.Object, java.lang.Object)
*/
public V put(K key, V value) {
lock.lock();
try {
return super.put(key, value);
} finally {
lock.unlock();
}
}
/**
*
* @see java.util.HashMap#size()
*/
public int size() {
lock.lock();
try {
return super.size();
} finally {
lock.unlock();
}
}
/**
*
* @see java.util.LinkedHashMap#clear()
*/
public void clear() {
lock.lock();
try {
super.clear();
} finally {
lock.unlock();
}
}
/**
*
* @see java.util.HashMap#remove(java.lang.Object)
*/
public V remove(Object key) {
lock.lock();
try {
return super.remove(key);
} finally {
lock.unlock();
}
}
/**
* 批量删除对象.
*
* @param objArrs
*/
public void batchDelete(Object[] objArrs) {
lock.lock();
try {
for (int i = 0; i < objArrs.length; i++) {
remove(objArrs[i]);
}
} finally {
lock.unlock();
}
}
}
4、Cache对象
class CacheData {
/** 缓存实际数据. */
private Object data;
/** 过期时间. */
private long expired;
/**
* Getter method for property <tt>data</tt>.
*
* @return property value of data
*/
public Object getData() {
return data;
}
/**
* Setter method for property <tt>data</tt>.
*
* @param data value to be assigned to property data
*/
public void setData(Object data) {
this.data = data;
}
/**
* Getter method for property <tt>expired</tt>.
*
* @return property value of expired
*/
public long getExpired() {
return expired;
}
/**
* Setter method for property <tt>expired</tt>.
*
* @param expired value to be assigned to property expired
*/
public void setExpired(long expired) {
this.expired = expired;
}
}
5、实际本地缓存类
public class LocalCacheManager implements CacheManager, InitializingBean {
private final Logger logger = LoggerFactory
.getLogger(LocalCacheManager.class);
private static final int DEFAULT_SIZE = 1000;
/** 缓存模块及对应模块缓存数据上限的配置. */
private Map<String, Integer> cacheConfigs;
private Map<CacheEnum, LRULinkedHashMap<String, CacheData>> instances;
private static final String TIPS = "invalid cache type=";
public LocalCacheManager() {
this(CacheEnum.DEFAULT, DEFAULT_SIZE);
}
public LocalCacheManager(CacheEnum type, int size) {
if (null == type || size <= 0) {
throw new IllegalArgumentException("type=" + type + ",size=" + size);
}
cacheConfigs = new HashMap<String, Integer>();
cacheConfigs.put(type.getCode(), Integer.valueOf(size));
try {
afterPropertiesSet();
} catch (Exception e) {
logger.error("init local cache failed!", e);
}
}
/**
*
* @see com.lenovo.appstore.biz.cache.CacheManager#put(com.lenovo.appstore.biz.cache.CacheEnum, java.lang.String, java.lang.Object, long)
*/
@Override
public void put(CacheEnum type, String key, Object data, long cacheTime) {
if (null == type || null == data || StringUtils.isEmpty(key)) {
LoggerUtil.warn(logger, "put fail,key=" + key + ",type=" + type + ",data=" + data);
return;
}
if (null == instances) {
return;
}
LRULinkedHashMap<String, CacheData> instance = instances.get(type);
if (null == instance) {
LoggerUtil.warn(logger, TIPS + type);
return;
}
CacheData cache = new CacheData();
cache.setData(data);
cache.setExpired(cacheTime + System.currentTimeMillis());
instance.put(key, cache);
}
/**
* @see com.lenovo.appstore.biz.cache.CacheManager#get(com.lenovo.appstore.biz.cache.CacheEnum, java.lang.String)
*/
@Override
public Object get(CacheEnum type, String key) {
if (null == type || StringUtils.isEmpty(key)) {
LoggerUtil.warn(logger, "get failed,key=" + key, ",type=" + type);
return null;
}
if (null == instances) {
LoggerUtil.warn(logger, "no cache config");
return null;
}
LRULinkedHashMap<String, CacheData> instance = instances.get(type);
if (null == instance) {
LoggerUtil.warn(logger, TIPS + type);
return null;
}
CacheData data = instance.get(key);
//没有缓存
if (null == data) {
return null;
}
//缓存过期
if (System.currentTimeMillis() > data.getExpired()) {
//从本地缓存删除
instance.remove(key);
LoggerUtil.info(logger, "cache expire,key=" + key + ",data=" + data.getData(), ",type=" + type);
return null;
}
return data.getData();
}
/**
*
* @see com.lenovo.appstore.biz.cache.CacheManager#remove(com.lenovo.appstore.biz.cache.CacheEnum, java.lang.String)
*/
@Override
public void remove(CacheEnum type, String key) {
if (null == type || StringUtils.isEmpty(key)) {
return;
}
if (null == instances) {
LoggerUtil.warn(logger, "no cache config");
return;
}
LRULinkedHashMap<String, CacheData> instance = instances.get(type);
if (null == instance) {
LoggerUtil.warn(logger, TIPS + type);
return;
}
LoggerUtil.info(logger, "delete key=" + key, "|type=" + type);
instance.remove(key);
}
/**
* @see com.lenovo.appstore.biz.cache.CacheManager#clean(com.lenovo.appstore.biz.cache.CacheEnum)
*/
@Override
public void clean(CacheEnum type) {
if (null == type) {
return;
}
if (null == instances) {
LoggerUtil.warn(logger, "no cache config");
return;
}
LRULinkedHashMap<String, CacheData> instance = instances.get(type);
if (null == instance) {
LoggerUtil.warn(logger, TIPS + type);
return;
}
LoggerUtil.warn(logger, "clean local cache for type=" + type);
instance.clear();
}
/**
*
* @see com.lenovo.appstore.biz.cache.CacheManager#dump()
*/
public Map<String, String> dump() {
Map<String, String> stats = new HashMap<String, String>();
if (null == instances || instances.size() == 0) {
LoggerUtil.info(logger, "no local cache");
stats.put("msg", "no local cache");
return stats;
}
for (Map.Entry<CacheEnum, LRULinkedHashMap<String, CacheData>> entry : instances.entrySet()) {
LoggerUtil.info(logger, "cache type=" + entry.getKey(), "|current cache size=" + entry.getValue().size());
stats.put("cache type=" + entry.getKey(), " current cache size=" + entry.getValue().size());
}
return stats;
}
}
6、配置初始化
@Override
public void afterPropertiesSet() throws Exception {
if (null == cacheConfigs || cacheConfigs.size() == 0) {
LoggerUtil.warn(logger, "no local cache config");
return;
}
instances = new HashMap<CacheEnum, LRULinkedHashMap<String, CacheData>>();
for (Map.Entry<String, Integer> entry : cacheConfigs.entrySet()) {
String key = entry.getKey();
Integer value = entry.getValue();
CacheEnum cache = CacheEnum.getEnumByCode(key);
if (null == cache) {
LoggerUtil.warn(logger, "invalid cache type");
continue;
}
if (null == value) {
LoggerUtil.warn(logger, "invalid cache capacity");
continue;
}
LRULinkedHashMap<String, CacheData> instance = new LRULinkedHashMap<String, CacheData>(value.intValue());
instances.put(cache, instance);
}
dump();
}
/**
* Setter method for property <tt>cacheConfigs</tt>.
*
* @param cacheConfigs value to be assigned to property cacheConfigs
*/
public void setCacheConfigs(Map<String, Integer> cacheConfigs) {
this.cacheConfigs = cacheConfigs;
}