package com.walker.cache;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.walker.cache.util.KeyUtils;
import com.walker.infrastructure.core.ApplicationBeanDestroied;
import com.walker.infrastructure.core.ApplicationBeanInitialized;
import com.walker.infrastructure.utils.Assert;
import com.walker.infrastructure.utils.ObjectStreamUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
/**
*
抽象的内存缓存对象,以纯内存方式管理缓存的基类
* @author MikeShi
*
*/
public abstract class AbstractMemoryCache implements Cache, ApplicationBeanInitialized, ApplicationBeanDestroied {
/**
*
*/
private static final long serialVersionUID = 2575070748765281205L;
// protected final transient Log logger = LogFactory.getLog(this.getClass());
protected final transient Logger logger = LoggerFactory.getLogger(this.getClass());
ConcurrentHashMap cacheMap = new ConcurrentHashMap(CacheConfig.INIT_CACHEMAP_SIZE);
private String cacheName;
public long expiredTime = 0;
private boolean writeOnDiskAfterShutdown = false;
private CacheOperateListener cacheOperateListener = null;
private boolean hasCacheListener = false;
public void setCacheOperateListener(CacheOperateListener cacheOperateListener) {
if(cacheOperateListener != null){
hasCacheListener = true;
}
this.cacheOperateListener = cacheOperateListener;
}
public AbstractMemoryCache(){}
public String getCacheName() {
return cacheName;
}
public void setCacheName(String name) {
this.cacheName = name;
}
public long getExpiredTime() {
return expiredTime;
}
public void setExpiredTime(int seconds) {
this.expiredTime = seconds*1000;
}
public Iterator getIterator(){
synchronized (cacheMap) {
return cacheMap.values().iterator();
}
}
@SuppressWarnings("unchecked")
public void startup() {
logger.debug("........ execute startup in AbstractMemoryCache! cacheName = " + cacheName);
Assert.isTrue(cacheName != null && !cacheName.equals(""));
if(writeOnDiskAfterShutdown){
Object obj = ObjectStreamUtils.readObjectFromFile(CacheConfig.WRITE_TEMP_CACHEFILE + cacheName);
if(obj != null){
logger.info("load cache data from disk! cache name: " + cacheName);
cacheMap = (ConcurrentHashMap)obj;
}
}
}
public void shutdown() {
logger.debug("........ execute shutdown in AbstractMemoryCache! cacheName = " + cacheName);
if(writeOnDiskAfterShutdown && !cacheMap.isEmpty()){
ObjectStreamUtils.writeObjectToFile(CacheConfig.WRITE_TEMP_CACHEFILE + cacheName, cacheMap);
}
cacheMap.clear();
cacheMap = null;
cacheName = null;
}
public boolean isWriteOnDiskAfterShutdown() {
return writeOnDiskAfterShutdown;
}
public void setWriteOnDiskAfterShutdown(boolean boo) {
writeOnDiskAfterShutdown = boo;
}
public String toString(){
StringBuilder sb = new StringBuilder();
sb.append("[cacheName=");
sb.append(cacheName);
sb.append(", expiredTime=");
sb.append(expiredTime);
sb.append(", cacheSize=");
sb.append(cacheMap.size());
sb.append(", data=");
sb.append(cacheMap);
sb.append("]");
return sb.toString();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// cache data operations
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/**
* 根据key,从缓存取出一个用户数据
*/
public Object get(String key) {
// public T get(String key) {
// logger.debug("----------" + cacheMap.get(key).isExpired(System.currentTimeMillis(), expiredTime));
Cachable d = cacheMap.get(key);
if(d != null){
return d.getValue();
}
return null;
}
/**
* 放入缓存一条新数据
*/
public void put(String key, Object data) {
Assert.notNull(key);
Assert.notNull(data);
// synchronized (cacheMap) {
Cachable cacheData = new CacheData();
cacheData.setKey(key);
cacheData.setValue(data);
cacheMap.put(key, cacheData);
if(hasCacheListener){
cacheOperateListener.onPut(data);
}
// }
}
/**
* 放入缓存数据有时间有效期
* @param key
* @param data
* @param expiredSeconds 过期秒数
* @date 2022-11-06
*/
public void put(String key, Object data, long expiredSeconds){
throw new UnsupportedOperationException("该方法由RedisCache
或者业务自定义CacheProvider实现。");
}
/**
* 删除一条缓存数据
*/
public Object remove(String key) {
// synchronized (cacheMap){
Cachable c = cacheMap.remove(key);
if(c != null){
Object v = c.getValue();
if(hasCacheListener){
cacheOperateListener.onRemove(v);
}
return v;
}
return null;
// }
}
/**
* 替换key相同的缓存数据为data
*/
public void replace(String key, Object data) {
// synchronized (cacheMap) {
Cachable cacheData = cacheMap.get(key);
if(cacheData != null){
cacheData.setValue(data);
cacheData.setTimeStamp(System.currentTimeMillis());
cacheData.hit();
}
// }
}
/**
* 根据数据key,更新缓存数据时间戳
*/
public void updateCacheDataTimeStamp(String key) {
Cachable c = cacheMap.get(key);
if(c != null){
c.setTimeStamp(System.currentTimeMillis());
c.hit();
} else
logger.warn("updateCacheDataTimeStamp error: cache data not found! key = " + key);
}
/**
* 删除给定的列表数据,从缓存对象中
*/
public void remove(List keys) {
Assert.notNull(keys);
synchronized (cacheMap){
for(String key : keys){
cacheMap.remove(key);
}
}
}
/**
* 清除缓存数据
*/
public void clear(){
cacheMap.clear();
if(hasCacheListener){
cacheOperateListener.onClear();
}
}
public Object get(String key, Class> clazz) {
throw new UnsupportedOperationException();
}
public List getIterator(Class> clazz) {
throw new UnsupportedOperationException();
}
public long getPersistentSize() {
return 0;
}
@Override
public long size(){
return cacheMap.size();
}
/**
* 返回给定限制的缓存数据集合
* @param maxSize 限制的最大数量
* @return
*/
@Override
public Collection