From 57318cc55d50f4b8a0e8742b15c06f2256443939 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Wed, 3 Jan 2024 10:25:23 +0800 Subject: [PATCH] =?UTF-8?q?[=E9=87=8D=E5=A4=A7=E6=9B=B4=E6=96=B0]=20?= =?UTF-8?q?=E6=96=B0=E5=A2=9E=20PlusCacheWrapper=E8=A3=85=E9=A5=B0?= =?UTF-8?q?=E5=99=A8=20=E4=B8=BASpringCache=E5=A2=9E=E5=8A=A0=E6=9C=AC?= =?UTF-8?q?=E5=9C=B0=E7=BC=93=E5=AD=98=E5=87=8F=E5=B0=91redis=E6=9F=A5?= =?UTF-8?q?=E8=AF=A2=E6=8F=90=E9=AB=98=E6=80=A7=E8=83=BD(=E5=B0=9D?= =?UTF-8?q?=E8=AF=95=E6=80=A7=E6=9B=B4=E6=96=B0=E9=97=AE=E9=A2=98=E6=9C=AA?= =?UTF-8?q?=E7=9F=A5=20=E8=AF=B7=E5=8B=BF=E8=BD=BB=E6=98=93=E6=9B=B4?= =?UTF-8?q?=E6=96=B0=E5=B0=9D=E8=AF=95)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ruoyi-common/ruoyi-common-redis/pom.xml | 5 + .../redis/manager/PlusCacheWrapper.java | 96 +++++++++++++++++++ .../redis/manager/PlusSpringCacheManager.java | 4 +- .../satoken/core/dao/PlusSaTokenDao.java | 4 +- .../security/config/SecurityConfig.java | 12 +-- .../service/impl/SysDictTypeServiceImpl.java | 22 +---- 6 files changed, 110 insertions(+), 33 deletions(-) create mode 100644 ruoyi-common/ruoyi-common-redis/src/main/java/org/dromara/common/redis/manager/PlusCacheWrapper.java diff --git a/ruoyi-common/ruoyi-common-redis/pom.xml b/ruoyi-common/ruoyi-common-redis/pom.xml index 5e5c277f3..140866575 100644 --- a/ruoyi-common/ruoyi-common-redis/pom.xml +++ b/ruoyi-common/ruoyi-common-redis/pom.xml @@ -32,6 +32,11 @@ com.baomidou lock4j-redisson-spring-boot-starter + + + com.github.ben-manes.caffeine + caffeine + diff --git a/ruoyi-common/ruoyi-common-redis/src/main/java/org/dromara/common/redis/manager/PlusCacheWrapper.java b/ruoyi-common/ruoyi-common-redis/src/main/java/org/dromara/common/redis/manager/PlusCacheWrapper.java new file mode 100644 index 000000000..65a3e89f6 --- /dev/null +++ b/ruoyi-common/ruoyi-common-redis/src/main/java/org/dromara/common/redis/manager/PlusCacheWrapper.java @@ -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 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 get(Object key, Class 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 get(Object key, Callable valueLoader) { + Object o = CAFFEINE.get(key, k -> cache.get(key, valueLoader)); + Console.log("redisson caffeine -> key: " + key + ",value:" + o); + return (T) o; + } + +} diff --git a/ruoyi-common/ruoyi-common-redis/src/main/java/org/dromara/common/redis/manager/PlusSpringCacheManager.java b/ruoyi-common/ruoyi-common-redis/src/main/java/org/dromara/common/redis/manager/PlusSpringCacheManager.java index 08ebc7826..0f8121b52 100644 --- a/ruoyi-common/ruoyi-common-redis/src/main/java/org/dromara/common/redis/manager/PlusSpringCacheManager.java +++ b/ruoyi-common/ruoyi-common-redis/src/main/java/org/dromara/common/redis/manager/PlusSpringCacheManager.java @@ -156,7 +156,7 @@ public class PlusSpringCacheManager implements CacheManager { private Cache createMap(String name, CacheConfig config) { RMap 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 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); } diff --git a/ruoyi-common/ruoyi-common-satoken/src/main/java/org/dromara/common/satoken/core/dao/PlusSaTokenDao.java b/ruoyi-common/ruoyi-common-satoken/src/main/java/org/dromara/common/satoken/core/dao/PlusSaTokenDao.java index b262d07f0..2cfc927c5 100644 --- a/ruoyi-common/ruoyi-common-satoken/src/main/java/org/dromara/common/satoken/core/dao/PlusSaTokenDao.java +++ b/ruoyi-common/ruoyi-common-satoken/src/main/java/org/dromara/common/satoken/core/dao/PlusSaTokenDao.java @@ -15,6 +15,8 @@ import java.util.concurrent.TimeUnit; /** * Sa-Token持久层接口(使用框架自带RedisUtils实现 协议统一) + *

+ * 采用 caffeine + redis 多级缓存 优化并发查询效率 * * @author Lion Li */ @@ -22,7 +24,7 @@ public class PlusSaTokenDao implements SaTokenDao { private static final Cache CAFFEINE = Caffeine.newBuilder() // 设置最后一次写入或访问后经过固定时间过期 - .expireAfterWrite(10, TimeUnit.SECONDS) + .expireAfterWrite(5, TimeUnit.SECONDS) // 初始的缓存空间大小 .initialCapacity(100) // 缓存的最大条数 diff --git a/ruoyi-common/ruoyi-common-security/src/main/java/org/dromara/common/security/config/SecurityConfig.java b/ruoyi-common/ruoyi-common-security/src/main/java/org/dromara/common/security/config/SecurityConfig.java index 211cefa05..b9283e038 100644 --- a/ruoyi-common/ruoyi-common-security/src/main/java/org/dromara/common/security/config/SecurityConfig.java +++ b/ruoyi-common/ruoyi-common-security/src/main/java/org/dromara/common/security/config/SecurityConfig.java @@ -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()); } diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysDictTypeServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysDictTypeServiceImpl.java index b20bf65c3..bc6663f0c 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysDictTypeServiceImpl.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysDictTypeServiceImpl.java @@ -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 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 datas = SpringUtils.getAopProxy(this).selectDictDataByType(dictType); Map 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 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 datas = SpringUtils.getAopProxy(this).selectDictDataByType(dictType); Map map = StreamUtils.toMap(datas, SysDictDataVo::getDictLabel, SysDictDataVo::getDictValue); if (StringUtils.containsAny(dictLabel, separator)) { return Arrays.stream(dictLabel.split(separator))