package com.walker.support.redis.cache;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.walker.cache.Cachable;
import com.walker.cache.Cache;
import com.walker.cache.CacheConfig;
import com.walker.cache.CacheOperateListener;
import com.walker.cache.util.KeyUtils;
import com.walker.infrastructure.ApplicationRuntimeException;
import com.walker.infrastructure.core.ApplicationBeanDestroied;
import com.walker.infrastructure.core.ApplicationBeanInitialized;
import com.walker.infrastructure.utils.JsonUtils;
import com.walker.infrastructure.utils.StringUtils;
import com.walker.support.redis.RedisHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
public class RedisCache implements Cache, ApplicationBeanInitialized, ApplicationBeanDestroied {
/**
*
*/
private static final long serialVersionUID = -2870330465438805899L;
protected final transient Logger logger = LoggerFactory.getLogger(this.getClass());
private String cacheName;
CacheOperateListener cacheOperateListener = null;
boolean hasCacheListener = false;
private RedisHelper redisHelper;
// 2023-06-13 集合的名字,用来存储集合数据。
private String nameKeySet = null;
public boolean isSupportExpiredCache() {
return supportExpiredCache;
}
/**
* 设置是否支持缓存失效,因为redis失效是针对key,因此HashMap方式是作为整体失效的!
*
* 1) 默认不支持缓存失效,此时使用Map方式存储数据
* 2) 当设置运行失效时,必须采用字符串形式的数据结构
* 3) 该选项只对hashmap数据结构有效。
*
* @param supportExpiredCache
* @date 2024-01-05
*/
public void setSupportExpiredCache(boolean supportExpiredCache) {
this.supportExpiredCache = supportExpiredCache;
}
// 2024-01-05 是否支持缓存失效,因为redis失效是针对key,因此HashMap方式是作为整体失效的!
private boolean supportExpiredCache = false;
public RedisHelper getRedisHelper() {
return redisHelper;
}
public void setRedisHelper(RedisHelper redisHelper) {
this.redisHelper = redisHelper;
}
public RedisCache(String providerName, Map param){
this.setCacheName(providerName);
this.nameKeySet = this.getCacheName() + ":set";
}
@Override
public void shutdown() {
}
@Override
public void startup() {}
private void checkSupportExpired(){
if(!this.supportExpiredCache){
throw new IllegalStateException("该缓存'" + this.getCacheName() + "'不支持缓存失效,请调用不带时间参数方法!如果需要失效请调用方法:setSupportExpiredCache(true)");
}
}
private void checkNotSupportExpired(){
if(this.supportExpiredCache){
throw new IllegalStateException("该缓存支持时间失效(supportExpiredCache = true),请调用带时间参数的方法:put(String key, Object data, long expiredSeconds)");
}
}
@Override
public void put(String key, Object data) {
this.checkNotSupportExpired();
try{
if(data instanceof String){
this.redisHelper.hset(this.getCacheName(), key, data.toString());
} else {
this.redisHelper.hset(this.getCacheName(), key, JsonUtils.objectToJsonString(data));
}
if(hasCacheListener){
cacheOperateListener.onPut(data);
}
} catch(Exception e){
if(e instanceof JsonMappingException){
logger.error("JsonMappingException: " + key + ", data=" + data.toString(), e);
} else if(e instanceof JsonProcessingException) {
logger.error("JsonProcessingException: " + key + ", data=" + data.toString(), e);
} else {
e.printStackTrace();
}
}
}
@Override
public void put(String key, Object data, long expiredSeconds){
this.checkSupportExpired();
try{
if(data instanceof String){
// this.redisHelper.hset(this.getCacheName(), key, data.toString(), expiredSeconds);
this.redisHelper.set(this.acquireListKey(key), data.toString(), expiredSeconds);
} else {
// this.redisHelper.hset(this.getCacheName(), key, JsonUtils.objectToJsonString(data), expiredSeconds);
this.redisHelper.set(this.acquireListKey(key), JsonUtils.objectToJsonString(data), expiredSeconds);
}
if(hasCacheListener){
cacheOperateListener.onPut(data);
}
} catch (Exception e){
if(e instanceof JsonMappingException){
logger.error("JsonMappingException: " + key + ", data=" + data.toString(), e);
} else if(e instanceof JsonProcessingException) {
logger.error("JsonProcessingException: " + key + ", data=" + data.toString(), e);
} else {
e.printStackTrace();
}
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//~ 2023-06-13 操作集合,但目前没有使用,感觉删除整个集合还比较麻烦。
//~ 2023-06-14 确定使用该对象,并测试结果。
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
private String acquireListKey(String key){
return KeyUtils.acquireListKey(this.getCacheName(), key);
}
@Override
public void putList(String key, List