From 1c768d66070ecea6ea7b377dbd4aa3dee786c633 Mon Sep 17 00:00:00 2001 From: D <3066417822@qq.com> Date: Wed, 24 Apr 2024 05:49:43 +0800 Subject: [PATCH] =?UTF-8?q?=E6=88=90=E5=8A=9F=E9=9B=86=E6=88=90ehcache,?= =?UTF-8?q?=E5=B9=B6=E6=8B=BF=E5=88=B0=E4=BA=86=E5=AE=83=E7=9A=84=E7=BC=93?= =?UTF-8?q?=E5=AD=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/common/CaptchaController.java | 21 +- .../controller/monitor/CacheController.java | 79 ++++--- .../monitor/SysUserOnlineController.java | 55 ++--- .../src/main/resources/application.yml | 10 + ruoyi-common/pom.xml | 22 ++ .../ruoyi/common/constant/CacheConstants.java | 14 +- .../com/ruoyi/common/utils/CacheUtils.java | 201 ++++++++++++++++++ .../com/ruoyi/common/utils/DictUtils.java | 30 ++- .../framework/aspectj/RateLimiterAspect.java | 40 ++-- .../framework/config/Ehcache3Config.java | 48 +++++ .../ruoyi/framework/config/RedisConfig.java | 38 +++- .../impl/SameUrlDataInterceptor.java | 22 +- .../web/service/SysLoginService.java | 16 +- .../web/service/SysPasswordService.java | 39 ++-- .../web/service/SysRegisterService.java | 13 +- .../framework/web/service/TokenService.java | 26 +-- .../service/impl/SysConfigServiceImpl.java | 42 ++-- 17 files changed, 494 insertions(+), 222 deletions(-) create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/utils/CacheUtils.java create mode 100644 ruoyi-framework/src/main/java/com/ruoyi/framework/config/Ehcache3Config.java diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/common/CaptchaController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/common/CaptchaController.java index 0d3c782..3ed5aa2 100644 --- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/common/CaptchaController.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/common/CaptchaController.java @@ -12,27 +12,23 @@ import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; import com.google.code.kaptcha.Producer; -import com.ruoyi.common.annotation.Anonymous; import com.ruoyi.common.config.RuoYiConfig; import com.ruoyi.common.constant.CacheConstants; import com.ruoyi.common.constant.Constants; import com.ruoyi.common.core.domain.AjaxResult; -import com.ruoyi.common.core.redis.RedisCache; +import com.ruoyi.common.utils.CacheUtils; import com.ruoyi.common.utils.sign.Base64; import com.ruoyi.common.utils.uuid.IdUtils; import com.ruoyi.system.service.ISysConfigService; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.annotation.Resource; import jakarta.servlet.http.HttpServletResponse; /** * 验证码操作处理 - * + * * @author ruoyi */ -@Tag(name = "验证码") @RestController public class CaptchaController { @Resource(name = "captchaProducer") @@ -41,17 +37,12 @@ public class CaptchaController { @Resource(name = "captchaProducerMath") private Producer captchaProducerMath; - @Autowired - private RedisCache redisCache; - @Autowired private ISysConfigService configService; /** * 生成验证码 */ - @Operation(summary = "获取验证码") - @Anonymous @GetMapping("/captchaImage") public AjaxResult getCode(HttpServletResponse response) throws IOException { AjaxResult ajax = AjaxResult.success(); @@ -60,14 +51,10 @@ public class CaptchaController { if (!captchaEnabled) { return ajax; } - // 保存验证码信息 String uuid = IdUtils.simpleUUID(); - String verifyKey = CacheConstants.CAPTCHA_CODE_KEY + uuid; - String capStr = null, code = null; BufferedImage image = null; - // 生成验证码 String captchaType = RuoYiConfig.getCaptchaType(); if ("math".equals(captchaType)) { @@ -79,8 +66,7 @@ public class CaptchaController { capStr = code = captchaProducer.createText(); image = captchaProducer.createImage(capStr); } - - redisCache.setCacheObject(verifyKey, code, Constants.CAPTCHA_EXPIRATION, TimeUnit.MINUTES); + CacheUtils.put(CacheConstants.CAPTCHA_CODE_KEY, uuid, code, Constants.CAPTCHA_EXPIRATION, TimeUnit.MINUTES); // 转换流信息写出 FastByteArrayOutputStream os = new FastByteArrayOutputStream(); try { @@ -88,7 +74,6 @@ public class CaptchaController { } catch (IOException e) { return AjaxResult.error(e.getMessage()); } - ajax.put("uuid", uuid); ajax.put("img", Base64.encode(os.toByteArray())); return ajax; diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/CacheController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/CacheController.java index 2770464..0e6dab9 100644 --- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/CacheController.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/CacheController.java @@ -1,16 +1,15 @@ package com.ruoyi.web.controller.monitor; import java.util.ArrayList; -import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Properties; import java.util.Set; -import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cache.Cache.ValueWrapper; +import org.springframework.data.redis.cache.RedisCacheManager; import org.springframework.data.redis.core.RedisCallback; -import org.springframework.data.redis.core.RedisTemplate; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; @@ -20,6 +19,8 @@ import org.springframework.web.bind.annotation.RestController; import com.ruoyi.common.constant.CacheConstants; import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.core.text.Convert; +import com.ruoyi.common.utils.CacheUtils; import com.ruoyi.common.utils.StringUtils; import com.ruoyi.system.domain.SysCache; @@ -38,9 +39,8 @@ import io.swagger.v3.oas.annotations.tags.Tag; @RequestMapping("/monitor/cache") public class CacheController { - @Autowired - private RedisTemplate redisTemplate; - + private static String tmpCacheName = ""; + private final static List caches = new ArrayList(); { caches.add(new SysCache(CacheConstants.LOGIN_TOKEN_KEY, "用户信息")); @@ -57,23 +57,25 @@ public class CacheController @GetMapping() public AjaxResult getInfo() throws Exception { - Properties info = (Properties) redisTemplate.execute((RedisCallback) connection -> connection.serverCommands().info()); - Properties commandStats = (Properties) redisTemplate.execute((RedisCallback) connection -> connection.serverCommands().info("commandstats")); - Object dbSize = redisTemplate.execute((RedisCallback) connection -> connection.serverCommands().dbSize()); - Map result = new HashMap<>(3); - result.put("info", info); - result.put("dbSize", dbSize); + if (CacheUtils.getCacheManager() instanceof RedisCacheManager) + { + Properties info = (Properties) CacheUtils.getRedisTemplate().execute((RedisCallback) connection -> connection.info()); + Properties commandStats = (Properties) CacheUtils.getRedisTemplate().execute((RedisCallback) connection -> connection.info("commandstats")); + Object dbSize = CacheUtils.getRedisTemplate().execute((RedisCallback) connection -> connection.dbSize()); + result.put("info", info); + result.put("dbSize", dbSize); - List> pieList = new ArrayList<>(); - commandStats.stringPropertyNames().forEach(key -> { - Map data = new HashMap<>(2); - String property = commandStats.getProperty(key); - data.put("name", StringUtils.removeStart(key, "cmdstat_")); - data.put("value", StringUtils.substringBetween(property, "calls=", ",usec")); - pieList.add(data); - }); - result.put("commandStats", pieList); + List> pieList = new ArrayList<>(); + commandStats.stringPropertyNames().forEach(key -> { + Map data = new HashMap<>(2); + String property = commandStats.getProperty(key); + data.put("name", StringUtils.removeStart(key, "cmdstat_")); + data.put("value", StringUtils.substringBetween(property, "calls=", ",usec")); + pieList.add(data); + }); + result.put("commandStats", pieList); + } return AjaxResult.success(result); } @@ -91,10 +93,11 @@ public class CacheController }) @PreAuthorize("@ss.hasPermi('monitor:cache:list')") @GetMapping("/getKeys/{cacheName}") - public AjaxResult getCacheKeys(@PathVariable( name = "cacheName" ) String cacheName) + public AjaxResult getCacheKeys(@PathVariable String cacheName) { - Set cacheKeys = redisTemplate.keys(cacheName + "*"); - return AjaxResult.success(cacheKeys); + tmpCacheName = cacheName; + Set keyset = CacheUtils.getkeys(cacheName); + return AjaxResult.success(keyset); } @Operation(summary = "获取缓存值列表") @@ -104,10 +107,16 @@ public class CacheController }) @PreAuthorize("@ss.hasPermi('monitor:cache:list')") @GetMapping("/getValue/{cacheName}/{cacheKey}") - public AjaxResult getCacheValue(@PathVariable( name = "cacheKey" ) String cacheName, @PathVariable String cacheKey) + public AjaxResult getCacheValue(@PathVariable String cacheName, @PathVariable String cacheKey) { - String cacheValue = redisTemplate.opsForValue().get(cacheKey); - SysCache sysCache = new SysCache(cacheName, cacheKey, cacheValue); + ValueWrapper valueWrapper = CacheUtils.get(cacheName, cacheKey); + SysCache sysCache = new SysCache(); + sysCache.setCacheName(cacheName); + sysCache.setCacheKey(cacheKey); + if (StringUtils.isNotNull(valueWrapper)) + { + sysCache.setCacheValue(Convert.toStr(valueWrapper.get(), "")); + } return AjaxResult.success(sysCache); } @@ -117,10 +126,9 @@ public class CacheController }) @PreAuthorize("@ss.hasPermi('monitor:cache:list')") @DeleteMapping("/clearCacheName/{cacheName}") - public AjaxResult clearCacheName(@PathVariable( name = "cacheName" ) String cacheName) + public AjaxResult clearCacheName(@PathVariable String cacheName) { - Collection cacheKeys = redisTemplate.keys(cacheName + "*"); - redisTemplate.delete(cacheKeys); + CacheUtils.clear(cacheName); return AjaxResult.success(); } @@ -130,19 +138,20 @@ public class CacheController }) @PreAuthorize("@ss.hasPermi('monitor:cache:list')") @DeleteMapping("/clearCacheKey/{cacheKey}") - public AjaxResult clearCacheKey(@PathVariable( name = "cacheKey" ) String cacheKey) + public AjaxResult clearCacheKey(@PathVariable String cacheKey) { - redisTemplate.delete(cacheKey); + CacheUtils.removeIfPresent(tmpCacheName, cacheKey); return AjaxResult.success(); } - @Operation(summary = "清除所有缓存") @PreAuthorize("@ss.hasPermi('monitor:cache:list')") @DeleteMapping("/clearCacheAll") public AjaxResult clearCacheAll() { - Collection cacheKeys = redisTemplate.keys("*"); - redisTemplate.delete(cacheKeys); + for (String cacheName : CacheUtils.getCacheManager().getCacheNames()) + { + CacheUtils.clear(cacheName); + } return AjaxResult.success(); } } diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/SysUserOnlineController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/SysUserOnlineController.java index c548bfb..50e9bc9 100644 --- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/SysUserOnlineController.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/SysUserOnlineController.java @@ -11,7 +11,6 @@ import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import com.ruoyi.common.annotation.Log; @@ -20,52 +19,47 @@ import com.ruoyi.common.core.controller.BaseController; import com.ruoyi.common.core.domain.AjaxResult; import com.ruoyi.common.core.domain.model.LoginUser; import com.ruoyi.common.core.page.TableDataInfo; -import com.ruoyi.common.core.redis.RedisCache; import com.ruoyi.common.enums.BusinessType; +import com.ruoyi.common.utils.CacheUtils; import com.ruoyi.common.utils.StringUtils; import com.ruoyi.system.domain.SysUserOnline; import com.ruoyi.system.service.ISysUserOnlineService; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.Parameters; -import io.swagger.v3.oas.annotations.tags.Tag; - /** * 在线用户监控 * * @author ruoyi */ -@Tag(name = "在线用户监控") @RestController @RequestMapping("/monitor/online") -public class SysUserOnlineController extends BaseController { +public class SysUserOnlineController extends BaseController +{ @Autowired private ISysUserOnlineService userOnlineService; - @Autowired - private RedisCache redisCache; - - @Operation(summary = "获取在线用户列表") - @Parameters({ - @Parameter(name = "ipaddr", description = "ip地址", required = false), - @Parameter(name = "userName", description = "用户名", required = false), - }) @PreAuthorize("@ss.hasPermi('monitor:online:list')") @GetMapping("/list") - public TableDataInfo list(@RequestParam(name = "ipaddr", required = false) String ipaddr, - @RequestParam(name = "userName", required = false) String userName) { - Collection keys = redisCache.keys(CacheConstants.LOGIN_TOKEN_KEY + "*"); + public TableDataInfo list(String ipaddr, String userName) + { + Collection keys = CacheUtils.getkeys(CacheConstants.LOGIN_TOKEN_KEY); List userOnlineList = new ArrayList(); - for (String key : keys) { - LoginUser user = redisCache.getCacheObject(key); - if (StringUtils.isNotEmpty(ipaddr) && StringUtils.isNotEmpty(userName)) { + for (String key : keys) + { + LoginUser user = CacheUtils.get(CacheConstants.LOGIN_TOKEN_KEY, key, LoginUser.class); + if (StringUtils.isNotEmpty(ipaddr) && StringUtils.isNotEmpty(userName)) + { userOnlineList.add(userOnlineService.selectOnlineByInfo(ipaddr, userName, user)); - } else if (StringUtils.isNotEmpty(ipaddr)) { + } + else if (StringUtils.isNotEmpty(ipaddr)) + { userOnlineList.add(userOnlineService.selectOnlineByIpaddr(ipaddr, user)); - } else if (StringUtils.isNotEmpty(userName) && StringUtils.isNotNull(user.getUser())) { + } + else if (StringUtils.isNotEmpty(userName) && StringUtils.isNotNull(user.getUser())) + { userOnlineList.add(userOnlineService.selectOnlineByUserName(userName, user)); - } else { + } + else + { userOnlineList.add(userOnlineService.loginUserToUserOnline(user)); } } @@ -77,15 +71,12 @@ public class SysUserOnlineController extends BaseController { /** * 强退用户 */ - @Operation(summary = "强退用户") - @Parameters({ - @Parameter(name = "tokenId", description = "用户凭证", required = true), - }) @PreAuthorize("@ss.hasPermi('monitor:online:forceLogout')") @Log(title = "在线用户", businessType = BusinessType.FORCE) @DeleteMapping("/{tokenId}") - public AjaxResult forceLogout(@PathVariable(name = "tokenId") String tokenId) { - redisCache.deleteObject(CacheConstants.LOGIN_TOKEN_KEY + tokenId); + public AjaxResult forceLogout(@PathVariable String tokenId) + { + CacheUtils.removeIfPresent(CacheConstants.LOGIN_TOKEN_KEY, tokenId); return success(); } } diff --git a/ruoyi-admin/src/main/resources/application.yml b/ruoyi-admin/src/main/resources/application.yml index 4f5d752..cee266f 100644 --- a/ruoyi-admin/src/main/resources/application.yml +++ b/ruoyi-admin/src/main/resources/application.yml @@ -47,6 +47,16 @@ user: # Spring配置 spring: + cache: + # 指定缓存类型 jcache 本地缓存 redis 缓存 + type: jcache + redis: + # 指定存活时间(ms) + time-to-live: 86400000 + # 指定前缀 + use-key-prefix: true + # 是否缓存空值,可以防止缓存穿透 + cache-null-values: true mvc: pathmatch: matching-strategy: ANT_PATH_MATCHER diff --git a/ruoyi-common/pom.xml b/ruoyi-common/pom.xml index a7e895c..0e16728 100644 --- a/ruoyi-common/pom.xml +++ b/ruoyi-common/pom.xml @@ -105,6 +105,11 @@ javax.xml.bind jaxb-api + + com.sun.xml.bind + jaxb-core + 2.3.0.1 + @@ -157,6 +162,23 @@ org.projectlombok lombok + + + + org.springframework.boot + spring-boot-starter-cache + + + + + org.ehcache + ehcache + 3.10.8 + + + javax.cache + cache-api + diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/constant/CacheConstants.java b/ruoyi-common/src/main/java/com/ruoyi/common/constant/CacheConstants.java index 0080343..1be9faf 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/constant/CacheConstants.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/constant/CacheConstants.java @@ -10,35 +10,35 @@ public class CacheConstants /** * 登录用户 redis key */ - public static final String LOGIN_TOKEN_KEY = "login_tokens:"; + public static final String LOGIN_TOKEN_KEY = "login_tokens"; /** * 验证码 redis key */ - public static final String CAPTCHA_CODE_KEY = "captcha_codes:"; + public static final String CAPTCHA_CODE_KEY = "captcha_codes"; /** * 参数管理 cache key */ - public static final String SYS_CONFIG_KEY = "sys_config:"; + public static final String SYS_CONFIG_KEY = "sys_config"; /** * 字典管理 cache key */ - public static final String SYS_DICT_KEY = "sys_dict:"; + public static final String SYS_DICT_KEY = "sys_dict"; /** * 防重提交 redis key */ - public static final String REPEAT_SUBMIT_KEY = "repeat_submit:"; + public static final String REPEAT_SUBMIT_KEY = "repeat_submit"; /** * 限流 redis key */ - public static final String RATE_LIMIT_KEY = "rate_limit:"; + public static final String RATE_LIMIT_KEY = "rate_limit"; /** * 登录账户密码错误次数 redis key */ - public static final String PWD_ERR_CNT_KEY = "pwd_err_cnt:"; + public static final String PWD_ERR_CNT_KEY = "pwd_err_cnt"; } 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 100644 index 0000000..f995465 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/CacheUtils.java @@ -0,0 +1,201 @@ +package com.ruoyi.common.utils; + +import java.lang.reflect.Field; +import java.util.HashSet; +import java.util.Set; +import java.util.concurrent.TimeUnit; + +import org.ehcache.core.EhcacheBase; +import org.ehcache.impl.internal.concurrent.ConcurrentHashMap; +import org.ehcache.impl.internal.store.heap.OnHeapStore; +import org.springframework.cache.Cache; +import org.springframework.cache.CacheManager; +import org.springframework.cache.jcache.JCacheCache; +import org.springframework.cache.transaction.TransactionAwareCacheDecorator; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.lang.Nullable; +import org.springframework.util.ObjectUtils; + +import com.ruoyi.common.utils.spring.SpringUtils; + +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", "rawtypes" }) + public static Set getkeys(String cacheName) { + Cache cache = getCacheManager().getCache(cacheName); + Set keyset = new HashSet<>(); + if (cache instanceof JCacheCache) { + try { + JCacheCache jehcache = (JCacheCache) cache; + // org.ehcache.jsr107.Eh107Cache 不公开 + Object nativeCache = jehcache.getNativeCache(); + Class nativeCacheClass = nativeCache.getClass(); + Field ehCacheField = nativeCacheClass.getDeclaredField("ehCache"); + ehCacheField.setAccessible(true); + EhcacheBase ehcache = (EhcacheBase) ehCacheField.get(nativeCache); + Field storeField = EhcacheBase.class.getDeclaredField("store"); + storeField.setAccessible(true); + OnHeapStore store = (OnHeapStore) storeField.get(ehcache); + Field mapField = OnHeapStore.class.getDeclaredField("map"); + mapField.setAccessible(true); + // org.ehcache.impl.internal.store.heap.Backend 不公开 + Object map = mapField.get(store); + Class mapClass = map.getClass(); + Field realMapField = mapClass.getDeclaredField("realMap"); + realMapField.setAccessible(true); + ConcurrentHashMap realMap = (ConcurrentHashMap) realMapField.get(map); + keyset = realMap.keySet(); + } catch (Exception e) { + } + + } 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 JCacheCache) { + JCacheCache ehcache = (JCacheCache) 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-common/src/main/java/com/ruoyi/common/utils/DictUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/DictUtils.java index cc5eab2..5613a8f 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/utils/DictUtils.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/DictUtils.java @@ -1,12 +1,11 @@ package com.ruoyi.common.utils; -import java.util.Collection; import java.util.List; -import com.alibaba.fastjson2.JSONArray; + +import org.springframework.cache.Cache; + import com.ruoyi.common.constant.CacheConstants; import com.ruoyi.common.core.domain.entity.SysDictData; -import com.ruoyi.common.core.redis.RedisCache; -import com.ruoyi.common.utils.spring.SpringUtils; /** * 字典工具类 @@ -28,7 +27,7 @@ public class DictUtils */ public static void setDictCache(String key, List dictDatas) { - SpringUtils.getBean(RedisCache.class).setCacheObject(getCacheKey(key), dictDatas); + getDictCacheKey().put(key, dictDatas); } /** @@ -37,12 +36,13 @@ public class DictUtils * @param key 参数键 * @return dictDatas 字典数据列表 */ + @SuppressWarnings("unchecked") public static List getDictCache(String key) { - JSONArray arrayCache = SpringUtils.getBean(RedisCache.class).getCacheObject(getCacheKey(key)); + List arrayCache = (List) getDictCacheKey().get(key, List.class); if (StringUtils.isNotNull(arrayCache)) { - return arrayCache.toList(SysDictData.class); + return arrayCache; } return null; } @@ -83,7 +83,6 @@ public class DictUtils { StringBuilder propertyString = new StringBuilder(); List datas = getDictCache(dictType); - if (StringUtils.isNotNull(datas)) { if (StringUtils.containsAny(separator, dictValue)) @@ -126,7 +125,6 @@ public class DictUtils { StringBuilder propertyString = new StringBuilder(); List datas = getDictCache(dictType); - if (StringUtils.containsAny(separator, dictLabel) && StringUtils.isNotEmpty(datas)) { for (SysDictData dict : datas) @@ -161,7 +159,7 @@ public class DictUtils */ public static void removeDictCache(String key) { - SpringUtils.getBean(RedisCache.class).deleteObject(getCacheKey(key)); + getDictCacheKey().evict(key); } /** @@ -169,18 +167,16 @@ public class DictUtils */ public static void clearDictCache() { - Collection keys = SpringUtils.getBean(RedisCache.class).keys(CacheConstants.SYS_DICT_KEY + "*"); - SpringUtils.getBean(RedisCache.class).deleteObject(keys); + getDictCacheKey().clear(); } /** - * 设置cache key + * 获取dict缓存 * - * @param configKey 参数键 - * @return 缓存键key + * @return 缓存Cache */ - public static String getCacheKey(String configKey) + public static Cache getDictCacheKey() { - return CacheConstants.SYS_DICT_KEY + configKey; + return CacheUtils.getCache(CacheConstants.SYS_DICT_KEY); } } diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/RateLimiterAspect.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/RateLimiterAspect.java index 9d27f59..f5e24d1 100644 --- a/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/RateLimiterAspect.java +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/RateLimiterAspect.java @@ -11,6 +11,7 @@ import org.aspectj.lang.reflect.MethodSignature; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.script.RedisScript; import org.springframework.stereotype.Component; @@ -18,7 +19,6 @@ import org.springframework.stereotype.Component; import com.ruoyi.common.annotation.RateLimiter; import com.ruoyi.common.enums.LimitType; import com.ruoyi.common.exception.ServiceException; -import com.ruoyi.common.utils.SecurityUtils; import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.ip.IpUtils; @@ -29,7 +29,9 @@ import com.ruoyi.common.utils.ip.IpUtils; */ @Aspect @Component -public class RateLimiterAspect { +@ConditionalOnProperty(prefix = "spring.cache", name = { "type" }, havingValue = "redis", matchIfMissing = false) +public class RateLimiterAspect +{ private static final Logger log = LoggerFactory.getLogger(RateLimiterAspect.class); private RedisTemplate redisTemplate; @@ -37,43 +39,49 @@ public class RateLimiterAspect { private RedisScript limitScript; @Autowired - public void setRedisTemplate1(RedisTemplate redisTemplate) { + public void setRedisTemplate1(RedisTemplate redisTemplate) + { this.redisTemplate = redisTemplate; } @Autowired - public void setLimitScript(RedisScript limitScript) { + public void setLimitScript(RedisScript limitScript) + { this.limitScript = limitScript; } @Before("@annotation(rateLimiter)") - public void doBefore(JoinPoint point, RateLimiter rateLimiter) throws Throwable { + public void doBefore(JoinPoint point, RateLimiter rateLimiter) throws Throwable + { int time = rateLimiter.time(); int count = rateLimiter.count(); - String combineKey = getCombineKey(rateLimiter, point); List keys = Collections.singletonList(combineKey); - try { + try + { Long number = redisTemplate.execute(limitScript, keys, count, time); - if (StringUtils.isNull(number) || number.intValue() > count) { + if (StringUtils.isNull(number) || number.intValue() > count) + { throw new ServiceException("访问过于频繁,请稍候再试"); } log.info("限制请求'{}',当前请求'{}',缓存key'{}'", count, number.intValue(), combineKey); - } catch (ServiceException e) { + } + catch (ServiceException e) + { throw e; - } catch (Exception e) { + } + catch (Exception e) + { throw new RuntimeException("服务器限流异常,请稍候再试"); } } - public String getCombineKey(RateLimiter rateLimiter, JoinPoint point) { + public String getCombineKey(RateLimiter rateLimiter, JoinPoint point) + { StringBuffer stringBuffer = new StringBuffer(rateLimiter.key()); - if (rateLimiter.limitType() == LimitType.IP) { + if (rateLimiter.limitType() == LimitType.IP) + { stringBuffer.append(IpUtils.getIpAddr()).append("-"); - } else if (rateLimiter.limitType() == LimitType.USER) { - stringBuffer.append(SecurityUtils.getUserId()).append("-"); - } else if (rateLimiter.limitType() == LimitType.DEPT) { - stringBuffer.append(SecurityUtils.getDeptId()).append("-"); } MethodSignature signature = (MethodSignature) point.getSignature(); Method method = signature.getMethod(); diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/Ehcache3Config.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/Ehcache3Config.java new file mode 100644 index 0000000..e9fd659 --- /dev/null +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/Ehcache3Config.java @@ -0,0 +1,48 @@ +package com.ruoyi.framework.config; + +import java.util.concurrent.TimeUnit; + +import javax.cache.CacheManager; +import javax.cache.Caching; +import javax.cache.configuration.MutableConfiguration; +import javax.cache.expiry.CreatedExpiryPolicy; +import javax.cache.expiry.Duration; + +import org.ehcache.jsr107.EhcacheCachingProvider; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.cache.annotation.EnableCaching; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +@EnableCaching +@ConditionalOnProperty(prefix = "spring.cache", name = { "type" }, havingValue = "jcache", matchIfMissing = false) +public class Ehcache3Config { + + @Bean + public CacheManager ehcacheManager() { + EhcacheCachingProvider cachingProvider = (EhcacheCachingProvider) Caching.getCachingProvider(); + + CacheManager cacheManager = (CacheManager) cachingProvider.getCacheManager(); + MutableConfiguration mutableConfiguration = new MutableConfiguration<>(); + mutableConfiguration.setTypes(String.class, Object.class); + mutableConfiguration.setStoreByValue(false); // 默认值为 true,可根据需求调整 + mutableConfiguration.setManagementEnabled(true); // 启用管理功能(可选) + mutableConfiguration.setStatisticsEnabled(true); // 启用统计功能(可选) + // 设置缓存过期策略(以 timeToIdle 为例,根据实际需求调整) + mutableConfiguration.setExpiryPolicyFactory(CreatedExpiryPolicy.factoryOf(new Duration(TimeUnit.HOURS,1))); + + cacheManager.createCache("temp_cache", mutableConfiguration); + cacheManager.createCache("eternal_cache", mutableConfiguration); + cacheManager.createCache("sys_dict", mutableConfiguration); + cacheManager.createCache("sys_config", mutableConfiguration); + cacheManager.createCache("repeat_submit", mutableConfiguration); + cacheManager.createCache("captcha_codes", mutableConfiguration); + cacheManager.createCache("login_tokens", mutableConfiguration); + cacheManager.createCache("rate_limit", mutableConfiguration); + cacheManager.createCache("pwd_err_cnt", mutableConfiguration); + + return cacheManager; + + } +} diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/RedisConfig.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/RedisConfig.java index f6e4918..a214ca9 100644 --- a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/RedisConfig.java +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/RedisConfig.java @@ -1,12 +1,19 @@ package com.ruoyi.framework.config; +import java.time.Duration; + +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.cache.CacheManager; import org.springframework.cache.annotation.CachingConfigurer; -import org.springframework.cache.annotation.EnableCaching; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Primary; +import org.springframework.data.redis.cache.RedisCacheConfiguration; +import org.springframework.data.redis.cache.RedisCacheManager; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.script.DefaultRedisScript; +import org.springframework.data.redis.serializer.RedisSerializationContext; import org.springframework.data.redis.serializer.StringRedisSerializer; /** @@ -15,16 +22,41 @@ import org.springframework.data.redis.serializer.StringRedisSerializer; * @author ruoyi */ @Configuration -@EnableCaching +@ConditionalOnProperty(prefix = "spring.cache", name = { "type" }, havingValue = "redis", matchIfMissing = false) public class RedisConfig implements CachingConfigurer { + @Bean + @Primary + public CacheManager cacheManager(RedisConnectionFactory connectionFactory) + { + RedisCacheConfiguration config = instanceConfig(3600 * 24 * 15L); + return RedisCacheManager.builder(connectionFactory).cacheDefaults(config).transactionAware().build(); + } + + @Bean + public CacheManager cacheManager30m(RedisConnectionFactory connectionFactory) + { + RedisCacheConfiguration config = instanceConfig(1800L); + return RedisCacheManager.builder(connectionFactory).cacheDefaults(config).transactionAware().build(); + } + + @SuppressWarnings(value = { "unchecked", "rawtypes" }) + private RedisCacheConfiguration instanceConfig(Long ttl) + { + FastJson2JsonRedisSerializer serializer = new FastJson2JsonRedisSerializer(Object.class); + return RedisCacheConfiguration.defaultCacheConfig().entryTtl(Duration.ofSeconds(ttl)).disableCachingNullValues() + .computePrefixWith(name -> name + ":") + .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer())) + .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(serializer)); + } + @Bean @SuppressWarnings(value = { "unchecked", "rawtypes" }) public RedisTemplate redisTemplate(RedisConnectionFactory connectionFactory) { RedisTemplate template = new RedisTemplate<>(); template.setConnectionFactory(connectionFactory); - + FastJson2JsonRedisSerializer serializer = new FastJson2JsonRedisSerializer(Object.class); // 使用StringRedisSerializer来序列化和反序列化redis的key值 diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/interceptor/impl/SameUrlDataInterceptor.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/interceptor/impl/SameUrlDataInterceptor.java index c93df50..004ca42 100644 --- a/ruoyi-framework/src/main/java/com/ruoyi/framework/interceptor/impl/SameUrlDataInterceptor.java +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/interceptor/impl/SameUrlDataInterceptor.java @@ -3,19 +3,21 @@ package com.ruoyi.framework.interceptor.impl; import java.util.HashMap; import java.util.Map; import java.util.concurrent.TimeUnit; -import jakarta.servlet.http.HttpServletRequest; -import org.springframework.beans.factory.annotation.Autowired; + import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; + import com.alibaba.fastjson2.JSON; import com.ruoyi.common.annotation.RepeatSubmit; import com.ruoyi.common.constant.CacheConstants; -import com.ruoyi.common.core.redis.RedisCache; import com.ruoyi.common.filter.RepeatedlyRequestWrapper; +import com.ruoyi.common.utils.CacheUtils; import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.http.HttpHelper; import com.ruoyi.framework.interceptor.RepeatSubmitInterceptor; +import jakarta.servlet.http.HttpServletRequest; + /** * 判断请求url和数据是否和上一次相同, * 如果和上次相同,则是重复提交表单。 有效时间为10秒内。 @@ -33,9 +35,6 @@ public class SameUrlDataInterceptor extends RepeatSubmitInterceptor @Value("${token.header}") private String header; - @Autowired - private RedisCache redisCache; - @SuppressWarnings("unchecked") @Override public boolean isRepeatSubmit(HttpServletRequest request, RepeatSubmit annotation) @@ -46,7 +45,6 @@ public class SameUrlDataInterceptor extends RepeatSubmitInterceptor RepeatedlyRequestWrapper repeatedlyRequest = (RepeatedlyRequestWrapper) request; nowParams = HttpHelper.getBodyString(repeatedlyRequest); } - // body参数为空,获取Parameter的数据 if (StringUtils.isEmpty(nowParams)) { @@ -55,17 +53,13 @@ public class SameUrlDataInterceptor extends RepeatSubmitInterceptor Map nowDataMap = new HashMap(); nowDataMap.put(REPEAT_PARAMS, nowParams); nowDataMap.put(REPEAT_TIME, System.currentTimeMillis()); - // 请求地址(作为存放cache的key值) String url = request.getRequestURI(); - // 唯一值(没有消息头则使用请求地址) String submitKey = StringUtils.trimToEmpty(request.getHeader(header)); - // 唯一标识(指定key + url + 消息头) - String cacheRepeatKey = CacheConstants.REPEAT_SUBMIT_KEY + url + submitKey; - - Object sessionObj = redisCache.getCacheObject(cacheRepeatKey); + String cacheRepeatKey = url + submitKey; + Object sessionObj = CacheUtils.get(CacheConstants.REPEAT_SUBMIT_KEY, cacheRepeatKey); if (sessionObj != null) { Map sessionMap = (Map) sessionObj; @@ -80,7 +74,7 @@ public class SameUrlDataInterceptor extends RepeatSubmitInterceptor } Map cacheMap = new HashMap(); cacheMap.put(url, nowDataMap); - redisCache.setCacheObject(cacheRepeatKey, cacheMap, annotation.interval(), TimeUnit.MILLISECONDS); + CacheUtils.put(CacheConstants.REPEAT_SUBMIT_KEY, cacheRepeatKey, cacheMap, annotation.interval(), TimeUnit.MILLISECONDS); return false; } diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysLoginService.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysLoginService.java index a6f7124..350bed8 100644 --- a/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysLoginService.java +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysLoginService.java @@ -1,24 +1,24 @@ package com.ruoyi.framework.web.service; -import jakarta.annotation.Resource; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.BadCredentialsException; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.Authentication; import org.springframework.stereotype.Component; + import com.ruoyi.common.constant.CacheConstants; import com.ruoyi.common.constant.Constants; import com.ruoyi.common.constant.UserConstants; import com.ruoyi.common.core.domain.entity.SysUser; import com.ruoyi.common.core.domain.model.LoginUser; -import com.ruoyi.common.core.redis.RedisCache; import com.ruoyi.common.exception.ServiceException; import com.ruoyi.common.exception.user.BlackListException; import com.ruoyi.common.exception.user.CaptchaException; import com.ruoyi.common.exception.user.CaptchaExpireException; import com.ruoyi.common.exception.user.UserNotExistsException; import com.ruoyi.common.exception.user.UserPasswordNotMatchException; +import com.ruoyi.common.utils.CacheUtils; import com.ruoyi.common.utils.DateUtils; import com.ruoyi.common.utils.MessageUtils; import com.ruoyi.common.utils.StringUtils; @@ -29,6 +29,8 @@ import com.ruoyi.framework.security.context.AuthenticationContextHolder; import com.ruoyi.system.service.ISysConfigService; import com.ruoyi.system.service.ISysUserService; +import jakarta.annotation.Resource; + /** * 登录校验方法 * @@ -43,9 +45,6 @@ public class SysLoginService @Resource private AuthenticationManager authenticationManager; - @Autowired - private RedisCache redisCache; - @Autowired private ISysUserService userService; @@ -113,9 +112,8 @@ public class SysLoginService boolean captchaEnabled = configService.selectCaptchaEnabled(); if (captchaEnabled) { - String verifyKey = CacheConstants.CAPTCHA_CODE_KEY + StringUtils.nvl(uuid, ""); - String captcha = redisCache.getCacheObject(verifyKey); - redisCache.deleteObject(verifyKey); + String captcha = CacheUtils.get(CacheConstants.CAPTCHA_CODE_KEY, StringUtils.nvl(uuid, ""), String.class); + CacheUtils.removeIfPresent(CacheConstants.CAPTCHA_CODE_KEY, StringUtils.nvl(uuid, "")); if (captcha == null) { AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.expire"))); @@ -146,7 +144,7 @@ public class SysLoginService if (password.length() < UserConstants.PASSWORD_MIN_LENGTH || password.length() > UserConstants.PASSWORD_MAX_LENGTH) { - AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.not.match"))); + AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL,MessageUtils.message("user.password.not.match"))); throw new UserPasswordNotMatchException(); } // 用户名不在指定范围内 错误 diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysPasswordService.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysPasswordService.java index 3937c48..9a0a833 100644 --- a/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysPasswordService.java +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysPasswordService.java @@ -1,18 +1,20 @@ package com.ruoyi.framework.web.service; -import java.util.concurrent.TimeUnit; - -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; +import org.springframework.cache.Cache; import org.springframework.security.core.Authentication; import org.springframework.stereotype.Component; import com.ruoyi.common.constant.CacheConstants; +import com.ruoyi.common.constant.Constants; import com.ruoyi.common.core.domain.entity.SysUser; -import com.ruoyi.common.core.redis.RedisCache; import com.ruoyi.common.exception.user.UserPasswordNotMatchException; import com.ruoyi.common.exception.user.UserPasswordRetryLimitExceedException; +import com.ruoyi.common.utils.CacheUtils; +import com.ruoyi.common.utils.MessageUtils; import com.ruoyi.common.utils.SecurityUtils; +import com.ruoyi.framework.manager.AsyncManager; +import com.ruoyi.framework.manager.factory.AsyncFactory; import com.ruoyi.framework.security.context.AuthenticationContextHolder; /** @@ -23,9 +25,6 @@ import com.ruoyi.framework.security.context.AuthenticationContextHolder; @Component public class SysPasswordService { - @Autowired - private RedisCache redisCache; - @Value(value = "${user.password.maxRetryCount}") private int maxRetryCount; @@ -34,13 +33,12 @@ public class SysPasswordService /** * 登录账户密码错误次数缓存键名 - * - * @param username 用户名 - * @return 缓存键key + * + * @return 缓存Cache */ - private String getCacheKey(String username) + private Cache getCache() { - return CacheConstants.PWD_ERR_CNT_KEY + username; + return CacheUtils.getCache(CacheConstants.PWD_ERR_CNT_KEY); } public void validate(SysUser user) @@ -48,23 +46,23 @@ public class SysPasswordService Authentication usernamePasswordAuthenticationToken = AuthenticationContextHolder.getContext(); String username = usernamePasswordAuthenticationToken.getName(); String password = usernamePasswordAuthenticationToken.getCredentials().toString(); - - Integer retryCount = redisCache.getCacheObject(getCacheKey(username)); - + Integer retryCount = getCache().get(username, Integer.class); if (retryCount == null) { retryCount = 0; } - if (retryCount >= Integer.valueOf(maxRetryCount).intValue()) { + AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, + MessageUtils.message("user.password.retry.limit.exceed", maxRetryCount, lockTime))); throw new UserPasswordRetryLimitExceedException(maxRetryCount, lockTime); } - if (!matches(user, password)) { retryCount = retryCount + 1; - redisCache.setCacheObject(getCacheKey(username), retryCount, lockTime, TimeUnit.MINUTES); + AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, + MessageUtils.message("user.password.retry.limit.count", retryCount))); + getCache().put(username, retryCount); throw new UserPasswordNotMatchException(); } else @@ -80,9 +78,6 @@ public class SysPasswordService public void clearLoginRecordCache(String loginName) { - if (redisCache.hasKey(getCacheKey(loginName))) - { - redisCache.deleteObject(getCacheKey(loginName)); - } + getCache().evictIfPresent(loginName); } } diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysRegisterService.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysRegisterService.java index f2afe31..6b80994 100644 --- a/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysRegisterService.java +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysRegisterService.java @@ -2,14 +2,15 @@ package com.ruoyi.framework.web.service; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; + import com.ruoyi.common.constant.CacheConstants; import com.ruoyi.common.constant.Constants; import com.ruoyi.common.constant.UserConstants; import com.ruoyi.common.core.domain.entity.SysUser; import com.ruoyi.common.core.domain.model.RegisterBody; -import com.ruoyi.common.core.redis.RedisCache; import com.ruoyi.common.exception.user.CaptchaException; import com.ruoyi.common.exception.user.CaptchaExpireException; +import com.ruoyi.common.utils.CacheUtils; import com.ruoyi.common.utils.MessageUtils; import com.ruoyi.common.utils.SecurityUtils; import com.ruoyi.common.utils.StringUtils; @@ -32,9 +33,6 @@ public class SysRegisterService @Autowired private ISysConfigService configService; - @Autowired - private RedisCache redisCache; - /** * 注册 */ @@ -43,14 +41,12 @@ public class SysRegisterService String msg = "", username = registerBody.getUsername(), password = registerBody.getPassword(); SysUser sysUser = new SysUser(); sysUser.setUserName(username); - // 验证码开关 boolean captchaEnabled = configService.selectCaptchaEnabled(); if (captchaEnabled) { validateCaptcha(username, registerBody.getCode(), registerBody.getUuid()); } - if (StringUtils.isEmpty(username)) { msg = "用户名不能为空"; @@ -100,9 +96,8 @@ public class SysRegisterService */ public void validateCaptcha(String username, String code, String uuid) { - String verifyKey = CacheConstants.CAPTCHA_CODE_KEY + StringUtils.nvl(uuid, ""); - String captcha = redisCache.getCacheObject(verifyKey); - redisCache.deleteObject(verifyKey); + String captcha = CacheUtils.get(CacheConstants.CAPTCHA_CODE_KEY, StringUtils.nvl(uuid, ""), String.class); + CacheUtils.removeIfPresent(CacheConstants.CAPTCHA_CODE_KEY, StringUtils.nvl(uuid, "")); if (captcha == null) { throw new CaptchaExpireException(); diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/TokenService.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/TokenService.java index 881f8e6..980580f 100644 --- a/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/TokenService.java +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/TokenService.java @@ -3,23 +3,25 @@ package com.ruoyi.framework.web.service; import java.util.HashMap; import java.util.Map; import java.util.concurrent.TimeUnit; -import jakarta.servlet.http.HttpServletRequest; -import org.springframework.beans.factory.annotation.Autowired; + import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; + import com.ruoyi.common.constant.CacheConstants; import com.ruoyi.common.constant.Constants; import com.ruoyi.common.core.domain.model.LoginUser; -import com.ruoyi.common.core.redis.RedisCache; +import com.ruoyi.common.utils.CacheUtils; import com.ruoyi.common.utils.ServletUtils; import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.ip.AddressUtils; import com.ruoyi.common.utils.ip.IpUtils; import com.ruoyi.common.utils.uuid.IdUtils; + import eu.bitwalker.useragentutils.UserAgent; import io.jsonwebtoken.Claims; import io.jsonwebtoken.Jwts; import io.jsonwebtoken.SignatureAlgorithm; +import jakarta.servlet.http.HttpServletRequest; /** * token验证处理 @@ -47,9 +49,6 @@ public class TokenService private static final Long MILLIS_MINUTE_TEN = 20 * 60 * 1000L; - @Autowired - private RedisCache redisCache; - /** * 获取用户身份信息 * @@ -66,8 +65,7 @@ public class TokenService Claims claims = parseToken(token); // 解析对应的权限以及用户信息 String uuid = (String) claims.get(Constants.LOGIN_USER_KEY); - String userKey = getTokenKey(uuid); - LoginUser user = redisCache.getCacheObject(userKey); + LoginUser user = CacheUtils.get(CacheConstants.LOGIN_TOKEN_KEY, uuid, LoginUser.class); return user; } catch (Exception e) @@ -95,8 +93,7 @@ public class TokenService { if (StringUtils.isNotEmpty(token)) { - String userKey = getTokenKey(token); - redisCache.deleteObject(userKey); + CacheUtils.removeIfPresent(CacheConstants.LOGIN_TOKEN_KEY, token); } } @@ -112,7 +109,6 @@ public class TokenService loginUser.setToken(token); setUserAgent(loginUser); refreshToken(loginUser); - Map claims = new HashMap<>(); claims.put(Constants.LOGIN_USER_KEY, token); return createToken(claims); @@ -144,8 +140,7 @@ public class TokenService loginUser.setLoginTime(System.currentTimeMillis()); loginUser.setExpireTime(loginUser.getLoginTime() + expireTime * MILLIS_MINUTE); // 根据uuid将loginUser缓存 - String userKey = getTokenKey(loginUser.getToken()); - redisCache.setCacheObject(userKey, loginUser, expireTime, TimeUnit.MINUTES); + CacheUtils.put(CacheConstants.LOGIN_TOKEN_KEY, loginUser.getToken(), loginUser, expireTime, TimeUnit.MINUTES); } /** @@ -218,9 +213,4 @@ public class TokenService } return token; } - - private String getTokenKey(String uuid) - { - return CacheConstants.LOGIN_TOKEN_KEY + uuid; - } } diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysConfigServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysConfigServiceImpl.java index 9e2d0f8..f254871 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysConfigServiceImpl.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysConfigServiceImpl.java @@ -1,22 +1,25 @@ package com.ruoyi.system.service.impl; -import java.util.Collection; import java.util.List; -import jakarta.annotation.PostConstruct; + import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cache.Cache; import org.springframework.stereotype.Service; + import com.ruoyi.common.annotation.DataSource; import com.ruoyi.common.constant.CacheConstants; import com.ruoyi.common.constant.UserConstants; -import com.ruoyi.common.core.redis.RedisCache; import com.ruoyi.common.core.text.Convert; import com.ruoyi.common.enums.DataSourceType; import com.ruoyi.common.exception.ServiceException; +import com.ruoyi.common.utils.CacheUtils; import com.ruoyi.common.utils.StringUtils; import com.ruoyi.system.domain.SysConfig; import com.ruoyi.system.mapper.SysConfigMapper; import com.ruoyi.system.service.ISysConfigService; +import jakarta.annotation.PostConstruct; + /** * 参数配置 服务层实现 * @@ -28,9 +31,6 @@ public class SysConfigServiceImpl implements ISysConfigService @Autowired private SysConfigMapper configMapper; - @Autowired - private RedisCache redisCache; - /** * 项目启动时,初始化参数到缓存 */ @@ -64,7 +64,7 @@ public class SysConfigServiceImpl implements ISysConfigService @Override public String selectConfigByKey(String configKey) { - String configValue = Convert.toStr(redisCache.getCacheObject(getCacheKey(configKey))); + String configValue = Convert.toStr(getCache().get(configKey, String.class)); if (StringUtils.isNotEmpty(configValue)) { return configValue; @@ -74,7 +74,7 @@ public class SysConfigServiceImpl implements ISysConfigService SysConfig retConfig = configMapper.selectConfig(config); if (StringUtils.isNotNull(retConfig)) { - redisCache.setCacheObject(getCacheKey(configKey), retConfig.getConfigValue()); + CacheUtils.put(CacheConstants.SYS_CONFIG_KEY, configKey, retConfig.getConfigValue()); return retConfig.getConfigValue(); } return StringUtils.EMPTY; @@ -120,7 +120,7 @@ public class SysConfigServiceImpl implements ISysConfigService int row = configMapper.insertConfig(config); if (row > 0) { - redisCache.setCacheObject(getCacheKey(config.getConfigKey()), config.getConfigValue()); + CacheUtils.put(CacheConstants.SYS_CONFIG_KEY, config.getConfigKey(), config.getConfigValue()); } return row; } @@ -137,13 +137,13 @@ public class SysConfigServiceImpl implements ISysConfigService SysConfig temp = configMapper.selectConfigById(config.getConfigId()); if (!StringUtils.equals(temp.getConfigKey(), config.getConfigKey())) { - redisCache.deleteObject(getCacheKey(temp.getConfigKey())); + CacheUtils.removeIfPresent(CacheConstants.SYS_CONFIG_KEY, temp.getConfigKey()); } int row = configMapper.updateConfig(config); if (row > 0) { - redisCache.setCacheObject(getCacheKey(config.getConfigKey()), config.getConfigValue()); + CacheUtils.put(CacheConstants.SYS_CONFIG_KEY, config.getConfigKey(), config.getConfigValue()); } return row; } @@ -161,10 +161,10 @@ public class SysConfigServiceImpl implements ISysConfigService SysConfig config = selectConfigById(configId); if (StringUtils.equals(UserConstants.YES, config.getConfigType())) { - throw new ServiceException("内置参数【%1$s】不能删除 ".formatted(config.getConfigKey())); + throw new ServiceException(String.format("内置参数【%1$s】不能删除 ", config.getConfigKey())); } configMapper.deleteConfigById(configId); - redisCache.deleteObject(getCacheKey(config.getConfigKey())); + getCache().evict(config.getConfigKey()); } } @@ -177,7 +177,7 @@ public class SysConfigServiceImpl implements ISysConfigService List configsList = configMapper.selectConfigList(new SysConfig()); for (SysConfig config : configsList) { - redisCache.setCacheObject(getCacheKey(config.getConfigKey()), config.getConfigValue()); + getCache().put(config.getConfigKey(), config.getConfigValue()); } } @@ -187,8 +187,7 @@ public class SysConfigServiceImpl implements ISysConfigService @Override public void clearConfigCache() { - Collection keys = redisCache.keys(CacheConstants.SYS_CONFIG_KEY + "*"); - redisCache.deleteObject(keys); + CacheUtils.getCache(CacheConstants.SYS_CONFIG_KEY).clear(); } /** @@ -220,13 +219,12 @@ public class SysConfigServiceImpl implements ISysConfigService } /** - * 设置cache key - * - * @param configKey 参数键 - * @return 缓存键key + * 获取config缓存 + * + * @return */ - private String getCacheKey(String configKey) + private Cache getCache() { - return CacheConstants.SYS_CONFIG_KEY + configKey; + return CacheUtils.getCache(CacheConstants.SYS_CONFIG_KEY); } }