diff --git a/ruoyi-admin/src/main/resources/ehcache.xml b/ruoyi-admin/src/main/resources/ehcache.xml new file mode 100755 index 00000000..5add5e62 --- /dev/null +++ b/ruoyi-admin/src/main/resources/ehcache.xml @@ -0,0 +1,142 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/CacheUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/CacheUtils.java new file mode 100755 index 00000000..6fd985ce --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/CacheUtils.java @@ -0,0 +1,200 @@ +package com.ruoyi.common.utils; + +import com.ruoyi.common.utils.spring.SpringUtils; +import org.springframework.cache.Cache; +import org.springframework.cache.CacheManager; +import org.springframework.cache.ehcache.EhCacheCache; +import org.springframework.cache.transaction.TransactionAwareCacheDecorator; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.lang.Nullable; +import org.springframework.util.ObjectUtils; +import java.util.HashSet; +import java.util.Set; +import java.util.concurrent.TimeUnit; + +public class CacheUtils +{ + /** + * 使用redis时对redis进行单独特殊操作需要使用 + * + * @param + * @param + * @return + */ + public static RedisTemplate getRedisTemplate() + { + return SpringUtils.getBean("redisTemplate"); + } + + /** + * 获取CacheManager + * + * @return + */ + public static CacheManager getCacheManager() + { + return SpringUtils.getBean(CacheManager.class); + } + + /** + * 根据cacheName从CacheManager中获取cache + * + * @param cacheName + * @return + */ + public static Cache getCache(String cacheName) + { + return getCacheManager().getCache(cacheName); + } + + /** + * 获取缓存的所有key值(由于springcache不支持获取所有key,只能根据cache类型来单独获取) + * + * @param cacheName + * @return + */ + @SuppressWarnings(value = { "unchecked" }) + public static Set getkeys(String cacheName) + { + Cache cache = getCacheManager().getCache(cacheName); + Set keyset = new HashSet<>(); + if (cache instanceof EhCacheCache) + { + EhCacheCache ehcache = (EhCacheCache) cache; + keyset = new HashSet<>(ehcache.getNativeCache().getKeys()); + } + else if (cache instanceof TransactionAwareCacheDecorator) + { + Set keysets = getRedisTemplate().keys(cache.getName() + "*"); + for (Object s : keysets) + { + keyset.add(StringUtils.replace(s.toString(), cache.getName() + ":", "")); + } + } + return keyset; + } + + /** + * 根据cacheName,key缓存数据 + * + * @param cacheName + * @param key + * @param value + * @param + */ + public static void put(String cacheName, String key, T value) + { + put(cacheName, key, value, 0, null); + } + + /** + * 如果没有则进行缓存,根据cacheName,key缓存数据 + * + * @param cacheName + * @param key + * @param value + * @param + */ + public static void putIfAbsent(String cacheName, String key, T value) + { + if (ObjectUtils.isEmpty(get(cacheName, key))) + { + put(cacheName, key, value, 0, null); + } + } + + /** + * 根据cacheName,key和缓存过期时间进行缓存数据,使用各种不同缓存可以单独进行操作 + * + * @param cacheName + * @param key + * @param value + * @param timeout + * @param unit + * @param + */ + public static void put(String cacheName, String key, T value, long timeout, TimeUnit unit) + { + Cache cache = getCacheManager().getCache(cacheName); + if (cache instanceof EhCacheCache) + { + EhCacheCache ehcache = (EhCacheCache) cache; + ehcache.put(key, value); + } + else if (cache instanceof TransactionAwareCacheDecorator) + { + if (timeout != 0 && unit != null) + { + getRedisTemplate().opsForValue().set(cacheName + ":" + key, value, timeout, unit); + } + else + { + getRedisTemplate().opsForValue().set(cacheName + ":" + key, value); + } + } + else + { + cache.put(key, value); + } + } + + /** + * 获取数据 + * + * @param cacheName + * @param key + * @return + */ + public static Cache.ValueWrapper get(String cacheName, String key) + { + return getCacheManager().getCache(cacheName).get(key); + } + + /** + * 根据类型获取数据 + * + * @param cacheName + * @param key + * @param type + * @param + * @return + */ + public static T get(String cacheName, String key, @Nullable Class type) + { + return getCacheManager().getCache(cacheName).get(key, type); + } + + /** + * 移除缓存数据 + * + * @param cacheName + * @param key + */ + public static void remove(String cacheName, String key) + { + getCacheManager().getCache(cacheName).evict(key); + } + + /** + * 如果存在则移除缓存数据 + * + * @param cacheName + * @param key + * @return + */ + public static boolean removeIfPresent(String cacheName, String key) + { + remove(cacheName, key); + return false; + } + + /** + * 清除缓存名称为cacheName的所有缓存数据 + * + * @param cacheName + */ + public static void clear(String cacheName) + { + getCacheManager().getCache(cacheName).clear(); + } +} diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/MybatisPlusConfig.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/MybatisPlusConfig.java new file mode 100644 index 00000000..f7121800 --- /dev/null +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/MybatisPlusConfig.java @@ -0,0 +1,62 @@ +package com.ruoyi.framework.config; + +import com.baomidou.mybatisplus.annotation.DbType; +import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; +import com.baomidou.mybatisplus.extension.plugins.inner.BlockAttackInnerInterceptor; +import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor; +import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.transaction.annotation.EnableTransactionManagement; + +/** + * Mybatis Plus 配置 + * + * @author ruoyi + */ +@EnableTransactionManagement(proxyTargetClass = true) +@Configuration +public class MybatisPlusConfig +{ + @Bean + public MybatisPlusInterceptor mybatisPlusInterceptor() + { + MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); + // 分页插件 + interceptor.addInnerInterceptor(paginationInnerInterceptor()); + // 乐观锁插件 + interceptor.addInnerInterceptor(optimisticLockerInnerInterceptor()); + // 阻断插件 + interceptor.addInnerInterceptor(blockAttackInnerInterceptor()); + return interceptor; + } + + /** + * 分页插件,自动识别数据库类型 https://baomidou.com/guide/interceptor-pagination.html + */ + public PaginationInnerInterceptor paginationInnerInterceptor() + { + PaginationInnerInterceptor paginationInnerInterceptor = new PaginationInnerInterceptor(); + // 设置数据库类型为mysql + paginationInnerInterceptor.setDbType(DbType.MYSQL); + // 设置最大单页限制数量,默认 500 条,-1 不受限制 + paginationInnerInterceptor.setMaxLimit(-1L); + return paginationInnerInterceptor; + } + + /** + * 乐观锁插件 https://baomidou.com/guide/interceptor-optimistic-locker.html + */ + public OptimisticLockerInnerInterceptor optimisticLockerInnerInterceptor() + { + return new OptimisticLockerInnerInterceptor(); + } + + /** + * 如果是对全表的删除或更新操作,就会终止该操作 https://baomidou.com/guide/interceptor-block-attack.html + */ + public BlockAttackInnerInterceptor blockAttackInnerInterceptor() + { + return new BlockAttackInnerInterceptor(); + } +} \ No newline at end of file