package com.yung.wx.integration.cache.local;
import com.yung.common.DateUtils;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Date;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicBoolean;
public class LocalCache {
private static Logger LOGGER = LoggerFactory.getLogger(LocalCache.class);
/**
* 后台清理线程是否已经开启
*/
private final static AtomicBoolean backgroundProcessStarted = new AtomicBoolean(false);
/**
* 清理缓存线程 清理间隔
*/
private final static int backgroundProcessorDelay = 10;
/**
* 缓存map
*/
private static ConcurrentHashMap<String, LocalCacheItem> cacheMap = new ConcurrentHashMap<String, LocalCacheItem>();
/**
* 写缓存 默认失效时间30秒
*
* @param key
* @param value
*/
public static void put(String key, Object value) {
put(key, value, 30 * 1000L);
}
/**
* 写缓存
*
* @param key
* @param value
* @param expireTimeMillis 过期时间 单位 毫秒
*/
public static void put(String key, Object value, long expireTimeMillis) {
// 当第一次有session创建的时候,开启session清理线程
if (!backgroundProcessStarted.getAndSet(true)) {
Thread t = new Thread(new Runnable() {
@Override
public void run() {
while (true) {
try {
// 每秒清理一次
Thread.sleep(backgroundProcessorDelay * 1000L);
backgroundProcess();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
LOGGER.error("SessionManagerImpl.backgroundProcess error", e);
}
}
}
});
t.setDaemon(true);
t.start();
}
LocalCacheItem item = new LocalCacheItem(value, System.currentTimeMillis(), expireTimeMillis);
cacheMap.put(key, item);
}
private static void backgroundProcess() {
if (MapUtils.isEmpty(cacheMap)) {
return;
}
Set<Map.Entry<String, LocalCacheItem>> entries = cacheMap.entrySet();
for (Map.Entry<String, LocalCacheItem> entry : entries) {
LocalCacheItem value = entry.getValue();
if (System.currentTimeMillis() - value.getCreateTimeMillis() > value.getExpireTimeMillis()) {
cacheMap.remove(entry.getKey());
}
}
}
/**
* 获取缓存
*
* @param key
* @return
*/
public static Object get(String key) {
return key == null ? null : getValue(key);
}
/**
* 获取缓存
* 如果换成过期 则删除缓存
*
* @param key
* @return
*/
private static Object getValue(String key) {
LocalCacheItem item = cacheMap.get(key);
/**
* 不存在缓存直接返回
*/
if (item == null) {
return null;
}
/**
* 永不过期 直接返回
* 存在时间 没有超过过期时间 直接返回
*/
if (item.getExpireTimeMillis() <= 0
|| System.currentTimeMillis() - item.getCreateTimeMillis() < item.getExpireTimeMillis()) {
return item.getValue();
}
//已过期
cacheMap.remove(key);
return null;
}
/**
* 根据key前缀 删除缓存
*
* @param prefix
*/
public static void removeByKeyPrefix(String prefix) {
Set<Map.Entry<String, LocalCacheItem>> entries = cacheMap.entrySet();
if (CollectionUtils.isEmpty(entries)) {
return;
}
for (Map.Entry<String, LocalCacheItem> entry : entries) {
String key = entry.getKey();
if (key.startsWith(prefix)) {
cacheMap.remove(key);
}
}
}
/**
* 缓存项
*/
private static class LocalCacheItem {
/**
* 缓存对象
*/
private Object value;
/**
* 缓存创建时间
*/
private long createTimeMillis;
/**
* 缓存过期时间,0值代表永不过期
*/
private long expireTimeMillis;
public LocalCacheItem(Object value, long createTimeMillis, long expireTimeMillis) {
this.value = value;
this.createTimeMillis = createTimeMillis;
this.expireTimeMillis = expireTimeMillis;
}
public Object getValue() {
return value;
}
public void setValue(Object value) {
this.value = value;
}
public long getCreateTimeMillis() {
return createTimeMillis;
}
public void setCreateTimeMillis(long createTimeMillis) {
this.createTimeMillis = createTimeMillis;
}
public long getExpireTimeMillis() {
return expireTimeMillis;
}
public void setExpireTimeMillis(long expireTimeMillis) {
this.expireTimeMillis = expireTimeMillis;
}
}
/**
* 生成缓存的key
*
* @param pJoinPoint
* @return
*/
public static String generateKey(ProceedingJoinPoint pJoinPoint) {
String targetName = pJoinPoint.getTarget().getClass().getName();
String methodName = pJoinPoint.getSignature().getName();
Object[] arguments = pJoinPoint.getArgs();
return generateKey(targetName, methodName, arguments);
}
public static String generateKey(String targetName, String methodName,
Object... arguments) {
StringBuilder sb = new StringBuilder();
sb.append(targetName)
.append(LocalCacheKeyConstants.SYMBOL_DIT)
.append(methodName);
if ((arguments != null) && (arguments.length != 0)) {
for (int i = 0; i < arguments.length; i++) {
if (arguments[i] instanceof Date) {
sb.append(LocalCacheKeyConstants.SYMBOL_DIT).append(
DateUtils.format((Date) arguments[i], "yyyyMMddHHmmssSSS"));
} else {
sb.append(LocalCacheKeyConstants.SYMBOL_DIT).append(arguments[i]);
}
}
}
return sb.toString();
}
}