mirror of https://github.com/alibaba/easyexcel
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
136 lines
4.3 KiB
136 lines
4.3 KiB
package com.alibaba.easytools.spring.cache; |
|
|
|
import java.time.Duration; |
|
import java.util.concurrent.TimeUnit; |
|
import java.util.function.Supplier; |
|
|
|
import javax.annotation.Resource; |
|
|
|
import com.alibaba.easytools.spring.cache.wrapper.CacheWrapper; |
|
|
|
import com.google.common.collect.Lists; |
|
import org.springframework.beans.factory.annotation.Autowired; |
|
import org.springframework.data.redis.core.HashOperations; |
|
import org.springframework.data.redis.core.StringRedisTemplate; |
|
import org.springframework.data.redis.core.ValueOperations; |
|
|
|
/** |
|
* 缓存操作 |
|
* |
|
* @author qiuyuyu |
|
* @date 2022/03/08 |
|
*/ |
|
public class EasyCache<V> { |
|
/** |
|
* 超时时间 |
|
*/ |
|
private static final long DEFAULT_TIMEOUT = Duration.ofMinutes(2L).toMillis(); |
|
/** |
|
* 同步锁的前缀 |
|
*/ |
|
private static final String SYNCHRONIZED_PREFIX = "_EasyCache:"; |
|
@Resource |
|
private HashOperations<String, String, CacheWrapper<V>> hashOperations; |
|
@Resource |
|
private ValueOperations<String, CacheWrapper<V>> valueOperations; |
|
@Resource |
|
private StringRedisTemplate stringRedisTemplate; |
|
|
|
/** |
|
* 去缓存里面获取一个值 并放入缓存 |
|
* |
|
* @param key 缓存的key |
|
* @param queryData 查询数据 |
|
* @return 缓存的值 |
|
*/ |
|
public V get(String key, Supplier<V> queryData) { |
|
return get(key, queryData, DEFAULT_TIMEOUT); |
|
} |
|
|
|
/** |
|
* 去缓存里面获取一个值 并放入缓存 |
|
* |
|
* @param key 缓存的key |
|
* @param queryData 查询数据 |
|
* @param timeout 超时时长 ms |
|
* @return 缓存的值 |
|
*/ |
|
public V get(String key, Supplier<V> queryData, Long timeout) { |
|
if (key == null) { |
|
return null; |
|
} |
|
// 先去缓存获取 |
|
CacheWrapper<V> cacheWrapper = valueOperations.get(key); |
|
if (cacheWrapper != null) { |
|
return cacheWrapper.getData(); |
|
} |
|
// 没有则锁住 然后第一个去获取 |
|
String lockKey = SYNCHRONIZED_PREFIX + key; |
|
synchronized (lockKey.intern()) { |
|
// 重新获取 |
|
cacheWrapper = valueOperations.get(key); |
|
if (cacheWrapper != null) { |
|
return cacheWrapper.getData(); |
|
} |
|
|
|
// 真正的去查询数据 |
|
V value = queryData.get(); |
|
|
|
// 构建缓存 |
|
CacheWrapper<V> cacheWrapperData = new CacheWrapper<>(); |
|
cacheWrapperData.setData(value); |
|
valueOperations.set(key, cacheWrapperData, timeout, TimeUnit.MILLISECONDS); |
|
return value; |
|
} |
|
} |
|
|
|
/** |
|
* 去缓存里面获取一个值 并放入缓存 |
|
* |
|
* @param key 缓存的key |
|
* @param hashKey 缓存的hashKey |
|
* @param queryData 查询数据 |
|
* @return 缓存的值 |
|
*/ |
|
public V hashGet(String key, String hashKey, Supplier<V> queryData) { |
|
if (key == null || hashKey == null) { |
|
return null; |
|
} |
|
// 先去缓存获取 |
|
CacheWrapper<V> cacheWrapper = hashOperations.get(key, hashKey); |
|
if (cacheWrapper != null && System.currentTimeMillis() < cacheWrapper.getExpireTimeMillis()) { |
|
return cacheWrapper.getData(); |
|
} |
|
|
|
// 没有则锁住 然后第一个去获取 |
|
String lockKey = SYNCHRONIZED_PREFIX + key + ":" + hashKey; |
|
synchronized (lockKey.intern()) { |
|
// 重新获取 |
|
cacheWrapper = hashOperations.get(key, hashKey); |
|
if (cacheWrapper != null && System.currentTimeMillis() < cacheWrapper.getExpireTimeMillis()) { |
|
return cacheWrapper.getData(); |
|
} |
|
|
|
// 真正的去查询数据 |
|
V value = queryData.get(); |
|
|
|
// 构建缓存 |
|
CacheWrapper<V> cacheWrapperData = new CacheWrapper<>(); |
|
cacheWrapperData.setData(value); |
|
cacheWrapperData.setExpireTimeMillis(System.currentTimeMillis() + DEFAULT_TIMEOUT); |
|
hashOperations.put(key, hashKey, cacheWrapperData); |
|
stringRedisTemplate.boundHashOps(key).expire(DEFAULT_TIMEOUT, TimeUnit.MILLISECONDS); |
|
return value; |
|
} |
|
} |
|
|
|
/** |
|
* 移除缓存 |
|
* |
|
* @param keys |
|
*/ |
|
public void delete(String... keys) { |
|
stringRedisTemplate.delete(Lists.newArrayList(keys)); |
|
} |
|
|
|
}
|
|
|