[重大更新] 新增 PlusCacheWrapper装饰器 为SpringCache增加本地缓存减少redis查询提高性能(尝试性更新问题未知 请勿轻易更新尝试)
This commit is contained in:
parent
df5edb67f0
commit
57318cc55d
@ -32,6 +32,11 @@
|
||||
<groupId>com.baomidou</groupId>
|
||||
<artifactId>lock4j-redisson-spring-boot-starter</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.github.ben-manes.caffeine</groupId>
|
||||
<artifactId>caffeine</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
|
@ -0,0 +1,96 @@
|
||||
package org.dromara.common.redis.manager;
|
||||
|
||||
import cn.hutool.core.lang.Console;
|
||||
import com.github.benmanes.caffeine.cache.Caffeine;
|
||||
import org.springframework.cache.Cache;
|
||||
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* Cache 装饰器(用于扩展一级缓存)
|
||||
*
|
||||
* @author LionLi
|
||||
*/
|
||||
public class PlusCacheWrapper implements Cache {
|
||||
|
||||
private static final com.github.benmanes.caffeine.cache.Cache<Object, Object> CAFFEINE = Caffeine.newBuilder()
|
||||
// 设置最后一次写入或访问后经过固定时间过期
|
||||
.expireAfterWrite(30, TimeUnit.SECONDS)
|
||||
// 初始的缓存空间大小
|
||||
.initialCapacity(100)
|
||||
// 缓存的最大条数
|
||||
.maximumSize(1000)
|
||||
.build();
|
||||
|
||||
private final Cache cache;
|
||||
|
||||
public PlusCacheWrapper(Cache cache) {
|
||||
this.cache = cache;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return cache.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getNativeCache() {
|
||||
return cache.getNativeCache();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ValueWrapper get(Object key) {
|
||||
Object o = CAFFEINE.get(key, k -> cache.get(key));
|
||||
Console.log("redisson caffeine -> key: " + key + ",value:" + o);
|
||||
return (ValueWrapper) o;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T get(Object key, Class<T> type) {
|
||||
Object o = CAFFEINE.get(key, k -> cache.get(key, type));
|
||||
Console.log("redisson caffeine -> key: " + key + ",value:" + o);
|
||||
return (T) o;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void put(Object key, Object value) {
|
||||
cache.put(key, value);
|
||||
CAFFEINE.put(key, value);
|
||||
}
|
||||
|
||||
public ValueWrapper putIfAbsent(Object key, Object value) {
|
||||
return cache.putIfAbsent(key, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void evict(Object key) {
|
||||
evictIfPresent(key);
|
||||
}
|
||||
|
||||
public boolean evictIfPresent(Object key) {
|
||||
boolean b = cache.evictIfPresent(key);
|
||||
if (b) {
|
||||
CAFFEINE.invalidate(key);
|
||||
}
|
||||
return b;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
cache.clear();
|
||||
}
|
||||
|
||||
public boolean invalidate() {
|
||||
return cache.invalidate();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public <T> T get(Object key, Callable<T> valueLoader) {
|
||||
Object o = CAFFEINE.get(key, k -> cache.get(key, valueLoader));
|
||||
Console.log("redisson caffeine -> key: " + key + ",value:" + o);
|
||||
return (T) o;
|
||||
}
|
||||
|
||||
}
|
@ -156,7 +156,7 @@ public class PlusSpringCacheManager implements CacheManager {
|
||||
private Cache createMap(String name, CacheConfig config) {
|
||||
RMap<Object, Object> map = RedisUtils.getClient().getMap(name);
|
||||
|
||||
Cache cache = new RedissonCache(map, allowNullValues);
|
||||
Cache cache = new PlusCacheWrapper(new RedissonCache(map, allowNullValues));
|
||||
if (transactionAware) {
|
||||
cache = new TransactionAwareCacheDecorator(cache);
|
||||
}
|
||||
@ -170,7 +170,7 @@ public class PlusSpringCacheManager implements CacheManager {
|
||||
private Cache createMapCache(String name, CacheConfig config) {
|
||||
RMapCache<Object, Object> map = RedisUtils.getClient().getMapCache(name);
|
||||
|
||||
Cache cache = new RedissonCache(map, config, allowNullValues);
|
||||
Cache cache = new PlusCacheWrapper(new RedissonCache(map, config, allowNullValues));
|
||||
if (transactionAware) {
|
||||
cache = new TransactionAwareCacheDecorator(cache);
|
||||
}
|
||||
|
@ -15,6 +15,8 @@ import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* Sa-Token持久层接口(使用框架自带RedisUtils实现 协议统一)
|
||||
* <p>
|
||||
* 采用 caffeine + redis 多级缓存 优化并发查询效率
|
||||
*
|
||||
* @author Lion Li
|
||||
*/
|
||||
@ -22,7 +24,7 @@ public class PlusSaTokenDao implements SaTokenDao {
|
||||
|
||||
private static final Cache<String, Object> CAFFEINE = Caffeine.newBuilder()
|
||||
// 设置最后一次写入或访问后经过固定时间过期
|
||||
.expireAfterWrite(10, TimeUnit.SECONDS)
|
||||
.expireAfterWrite(5, TimeUnit.SECONDS)
|
||||
// 初始的缓存空间大小
|
||||
.initialCapacity(100)
|
||||
// 缓存的最大条数
|
||||
|
@ -59,9 +59,6 @@ public class SecurityConfig implements WebMvcConfigurer {
|
||||
StpUtil.getTokenValue());
|
||||
}
|
||||
|
||||
// 保存用户信息
|
||||
// ThreadLocalHolder.set(LoginHelper.LOGIN_USER_KEY, LoginHelper.getLoginUser());
|
||||
|
||||
// 有效率影响 用于临时测试
|
||||
// if (log.isDebugEnabled()) {
|
||||
// log.info("剩余有效时间: {}", StpUtil.getTokenTimeout());
|
||||
@ -69,14 +66,7 @@ public class SecurityConfig implements WebMvcConfigurer {
|
||||
// }
|
||||
|
||||
});
|
||||
})
|
||||
// {
|
||||
// @Override
|
||||
// public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
|
||||
// ThreadLocalHolder.clear();
|
||||
// }
|
||||
// }
|
||||
).addPathPatterns("/**")
|
||||
})).addPathPatterns("/**")
|
||||
// 排除不需要拦截的路径
|
||||
.excludePathPatterns(securityProperties.getExcludes());
|
||||
}
|
||||
|
@ -6,9 +6,8 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import org.dromara.common.core.constant.CacheConstants;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.dromara.common.core.constant.CacheNames;
|
||||
import org.dromara.common.core.context.ThreadLocalHolder;
|
||||
import org.dromara.common.core.exception.ServiceException;
|
||||
import org.dromara.common.core.service.DictService;
|
||||
import org.dromara.common.core.utils.MapstructUtils;
|
||||
@ -26,7 +25,6 @@ import org.dromara.system.domain.vo.SysDictTypeVo;
|
||||
import org.dromara.system.mapper.SysDictDataMapper;
|
||||
import org.dromara.system.mapper.SysDictTypeMapper;
|
||||
import org.dromara.system.service.ISysDictTypeService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.cache.annotation.CachePut;
|
||||
import org.springframework.cache.annotation.Cacheable;
|
||||
import org.springframework.stereotype.Service;
|
||||
@ -217,16 +215,9 @@ public class SysDictTypeServiceImpl implements ISysDictTypeService, DictService
|
||||
* @param separator 分隔符
|
||||
* @return 字典标签
|
||||
*/
|
||||
@SuppressWarnings("unchecked cast")
|
||||
@Override
|
||||
public String getDictLabel(String dictType, String dictValue, String separator) {
|
||||
// 优先从本地缓存获取
|
||||
List<SysDictDataVo> datas = ThreadLocalHolder.get(CacheConstants.SYS_DICT_KEY + dictType);
|
||||
if (ObjectUtil.isNull(datas)) {
|
||||
datas = SpringUtils.getAopProxy(this).selectDictDataByType(dictType);
|
||||
ThreadLocalHolder.set(CacheConstants.SYS_DICT_KEY + dictType, datas);
|
||||
}
|
||||
|
||||
List<SysDictDataVo> datas = SpringUtils.getAopProxy(this).selectDictDataByType(dictType);
|
||||
Map<String, String> map = StreamUtils.toMap(datas, SysDictDataVo::getDictValue, SysDictDataVo::getDictLabel);
|
||||
if (StringUtils.containsAny(dictValue, separator)) {
|
||||
return Arrays.stream(dictValue.split(separator))
|
||||
@ -245,16 +236,9 @@ public class SysDictTypeServiceImpl implements ISysDictTypeService, DictService
|
||||
* @param separator 分隔符
|
||||
* @return 字典值
|
||||
*/
|
||||
@SuppressWarnings("unchecked cast")
|
||||
@Override
|
||||
public String getDictValue(String dictType, String dictLabel, String separator) {
|
||||
// 优先从本地缓存获取
|
||||
List<SysDictDataVo> datas = ThreadLocalHolder.get(CacheConstants.SYS_DICT_KEY + dictType);
|
||||
if (ObjectUtil.isNull(datas)) {
|
||||
datas = SpringUtils.getAopProxy(this).selectDictDataByType(dictType);
|
||||
ThreadLocalHolder.set(CacheConstants.SYS_DICT_KEY + dictType, datas);
|
||||
}
|
||||
|
||||
List<SysDictDataVo> datas = SpringUtils.getAopProxy(this).selectDictDataByType(dictType);
|
||||
Map<String, String> map = StreamUtils.toMap(datas, SysDictDataVo::getDictLabel, SysDictDataVo::getDictValue);
|
||||
if (StringUtils.containsAny(dictLabel, separator)) {
|
||||
return Arrays.stream(dictLabel.split(separator))
|
||||
|
Loading…
x
Reference in New Issue
Block a user