[重大更新] 新增 PlusCacheWrapper装饰器 为SpringCache增加本地缓存减少redis查询提高性能(尝试性更新问题未知 请勿轻易更新尝试)
已添加1个文件
已修改5个文件
143 ■■■■ 文件已修改
ruoyi-common/ruoyi-common-redis/pom.xml 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/ruoyi-common-redis/src/main/java/org/dromara/common/redis/manager/PlusCacheWrapper.java 96 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/ruoyi-common-redis/src/main/java/org/dromara/common/redis/manager/PlusSpringCacheManager.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/ruoyi-common-satoken/src/main/java/org/dromara/common/satoken/core/dao/PlusSaTokenDao.java 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/ruoyi-common-security/src/main/java/org/dromara/common/security/config/SecurityConfig.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysDictTypeServiceImpl.java 22 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/ruoyi-common-redis/pom.xml
@@ -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>
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<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;
    }
}
ruoyi-common/ruoyi-common-redis/src/main/java/org/dromara/common/redis/manager/PlusSpringCacheManager.java
@@ -156,7 +156,7 @@
    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 @@
    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);
        }
ruoyi-common/ruoyi-common-satoken/src/main/java/org/dromara/common/satoken/core/dao/PlusSaTokenDao.java
@@ -15,6 +15,8 @@
/**
 * Sa-Token持久层接口(使用框架自带RedisUtils实现 åè®®ç»Ÿä¸€)
 * <p>
 * é‡‡ç”¨ caffeine + redis å¤šçº§ç¼“å­˜ ä¼˜åŒ–并发查询效率
 *
 * @author Lion Li
 */
@@ -22,7 +24,7 @@
    private static final Cache<String, Object> CAFFEINE = Caffeine.newBuilder()
        // è®¾ç½®æœ€åŽä¸€æ¬¡å†™å…¥æˆ–访问后经过固定时间过期
        .expireAfterWrite(10, TimeUnit.SECONDS)
        .expireAfterWrite(5, TimeUnit.SECONDS)
        // åˆå§‹çš„缓存空间大小
        .initialCapacity(100)
        // ç¼“存的最大条数
ruoyi-common/ruoyi-common-security/src/main/java/org/dromara/common/security/config/SecurityConfig.java
@@ -59,9 +59,6 @@
                                StpUtil.getTokenValue());
                        }
                        // ä¿å­˜ç”¨æˆ·ä¿¡æ¯
//                        ThreadLocalHolder.set(LoginHelper.LOGIN_USER_KEY, LoginHelper.getLoginUser());
                        // æœ‰æ•ˆçŽ‡å½±å“ ç”¨äºŽä¸´æ—¶æµ‹è¯•
                        // if (log.isDebugEnabled()) {
                        //     log.info("剩余有效时间: {}", StpUtil.getTokenTimeout());
@@ -69,14 +66,7 @@
                        // }
                    });
            })
//            {
//                @Override
//                public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
//                    ThreadLocalHolder.clear();
//                }
//            }
            ).addPathPatterns("/**")
            })).addPathPatterns("/**")
            // æŽ’除不需要拦截的路径
            .excludePathPatterns(securityProperties.getExcludes());
    }
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysDictTypeServiceImpl.java
@@ -6,9 +6,8 @@
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.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 @@
     * @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 @@
     * @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))