fix(适配发布系统项目需求):

去除 redis 添加 本地缓存;替换 mybatis 为mybatisPlus
This commit is contained in:
HueFu 2024-08-06 17:26:54 +08:00
parent 3ef6000794
commit 8ea4225f1e
No known key found for this signature in database
23 changed files with 313 additions and 411 deletions

9
.gitignore vendored
View File

@ -35,6 +35,7 @@ nbbuild/
dist/ dist/
nbdist/ nbdist/
.nb-gradle/ .nb-gradle/
pnpm-lock.yaml
###################################################################### ######################################################################
# Others # Others
@ -45,3 +46,11 @@ nbdist/
!*/build/*.java !*/build/*.java
!*/build/*.html !*/build/*.html
!*/build/*.xml !*/build/*.xml
/logs
/doc
/bin
/.github
/ry.bat
/LICENSE

17
pom.xml
View File

@ -9,7 +9,6 @@
<version>3.8.8</version> <version>3.8.8</version>
<name>ruoyi</name> <name>ruoyi</name>
<url>http://www.ruoyi.vip</url>
<description>若依管理系统</description> <description>若依管理系统</description>
<properties> <properties>
@ -20,6 +19,8 @@
<maven-jar-plugin.version>3.1.1</maven-jar-plugin.version> <maven-jar-plugin.version>3.1.1</maven-jar-plugin.version>
<spring-framework.version>5.3.33</spring-framework.version> <spring-framework.version>5.3.33</spring-framework.version>
<spring-security.version>5.7.12</spring-security.version> <spring-security.version>5.7.12</spring-security.version>
<spring-cache.version>2.5.15</spring-cache.version>
<ehcache.version>3.10.8</ehcache.version>
<druid.version>1.2.23</druid.version> <druid.version>1.2.23</druid.version>
<bitwalker.version>1.21</bitwalker.version> <bitwalker.version>1.21</bitwalker.version>
<swagger.version>3.0.0</swagger.version> <swagger.version>3.0.0</swagger.version>
@ -64,6 +65,20 @@
<scope>import</scope> <scope>import</scope>
</dependency> </dependency>
<!-- SpringCache的依赖配置 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
<version>${spring-cache.version}</version>
</dependency>
<!-- Ehcache缓存管理器 -->
<dependency>
<groupId>org.ehcache</groupId>
<artifactId>ehcache</artifactId>
<version>${ehcache.version}</version>
</dependency>
<!-- 阿里数据库连接池 --> <!-- 阿里数据库连接池 -->
<dependency> <dependency>
<groupId>com.alibaba</groupId> <groupId>com.alibaba</groupId>

View File

@ -3,6 +3,7 @@ package com.ruoyi;
import org.springframework.boot.SpringApplication; import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.cache.annotation.EnableCaching;
/** /**
* 启动程序 * 启动程序
@ -10,21 +11,22 @@ import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
* @author ruoyi * @author ruoyi
*/ */
@SpringBootApplication(exclude = { DataSourceAutoConfiguration.class }) @SpringBootApplication(exclude = { DataSourceAutoConfiguration.class })
@EnableCaching
public class RuoYiApplication public class RuoYiApplication
{ {
public static void main(String[] args) public static void main(String[] args)
{ {
// System.setProperty("spring.devtools.restart.enabled", "false"); // System.setProperty("spring.devtools.restart.enabled", "false");
SpringApplication.run(RuoYiApplication.class, args); SpringApplication.run(RuoYiApplication.class, args);
System.out.println("(♥◠‿◠)ノ゙ 若依启动成功 ლ(´ڡ`ლ)゙ \n" + // System.out.println("(♥◠‿◠)ノ゙ 若依启动成功 ლ(´ڡ`ლ)゙ \n" +
" .-------. ____ __ \n" + // " .-------. ____ __ \n" +
" | _ _ \\ \\ \\ / / \n" + // " | _ _ \\ \\ \\ / / \n" +
" | ( ' ) | \\ _. / ' \n" + // " | ( ' ) | \\ _. / ' \n" +
" |(_ o _) / _( )_ .' \n" + // " |(_ o _) / _( )_ .' \n" +
" | (_,_).' __ ___(_ o _)' \n" + // " | (_,_).' __ ___(_ o _)' \n" +
" | |\\ \\ | || |(_,_)' \n" + // " | |\\ \\ | || |(_,_)' \n" +
" | | \\ `' /| `-' / \n" + // " | | \\ `' /| `-' / \n" +
" | | \\ / \\ / \n" + // " | | \\ / \\ / \n" +
" ''-' `'-' `-..-' "); // " ''-' `'-' `-..-' ");
} }
} }

View File

@ -1,92 +1,76 @@
package com.ruoyi.web.controller.common; package com.ruoyi.web.controller.common;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
import javax.annotation.Resource;
import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.FastByteArrayOutputStream;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import com.google.code.kaptcha.Producer; import com.google.code.kaptcha.Producer;
import com.ruoyi.common.config.RuoYiConfig; import com.ruoyi.common.config.RuoYiConfig;
import com.ruoyi.common.constant.CacheConstants; import com.ruoyi.common.constant.CacheConstants;
import com.ruoyi.common.constant.Constants; import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.domain.AjaxResult; 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.sign.Base64;
import com.ruoyi.common.utils.uuid.IdUtils; import com.ruoyi.common.utils.uuid.IdUtils;
import com.ruoyi.system.service.ISysConfigService; import com.ruoyi.system.service.ISysConfigService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.FastByteArrayOutputStream;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletResponse;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
/** /**
* 验证码操作处理 * 验证码操作处理
* *
* @author ruoyi * @author ruoyi
*/ */
@RestController @RestController
public class CaptchaController public class CaptchaController {
{
@Resource(name = "captchaProducer") @Resource(name = "captchaProducer")
private Producer captchaProducer; private Producer captchaProducer;
@Resource(name = "captchaProducerMath") @Resource(name = "captchaProducerMath")
private Producer captchaProducerMath; private Producer captchaProducerMath;
@Autowired
private RedisCache redisCache;
@Autowired @Autowired
private ISysConfigService configService; private ISysConfigService configService;
/** /**
* 生成验证码 * 生成验证码
*/ */
@GetMapping("/captchaImage") @GetMapping("/captchaImage")
public AjaxResult getCode(HttpServletResponse response) throws IOException public AjaxResult getCode(HttpServletResponse response) throws IOException {
{
AjaxResult ajax = AjaxResult.success(); AjaxResult ajax = AjaxResult.success();
boolean captchaEnabled = configService.selectCaptchaEnabled(); boolean captchaEnabled = configService.selectCaptchaEnabled();
ajax.put("captchaEnabled", captchaEnabled); ajax.put("captchaEnabled", captchaEnabled);
if (!captchaEnabled) if (!captchaEnabled) {
{
return ajax; return ajax;
} }
// 保存验证码信息 // 保存验证码信息
String uuid = IdUtils.simpleUUID(); String uuid = IdUtils.simpleUUID();
String verifyKey = CacheConstants.CAPTCHA_CODE_KEY + uuid;
String capStr = null, code = null; String capStr = null, code = null;
BufferedImage image = null; BufferedImage image = null;
// 生成验证码 // 生成验证码
String captchaType = RuoYiConfig.getCaptchaType(); String captchaType = RuoYiConfig.getCaptchaType();
if ("math".equals(captchaType)) if ("math".equals(captchaType)) {
{
String capText = captchaProducerMath.createText(); String capText = captchaProducerMath.createText();
capStr = capText.substring(0, capText.lastIndexOf("@")); capStr = capText.substring(0, capText.lastIndexOf("@"));
code = capText.substring(capText.lastIndexOf("@") + 1); code = capText.substring(capText.lastIndexOf("@") + 1);
image = captchaProducerMath.createImage(capStr); image = captchaProducerMath.createImage(capStr);
} } else if ("char".equals(captchaType)) {
else if ("char".equals(captchaType))
{
capStr = code = captchaProducer.createText(); capStr = code = captchaProducer.createText();
image = captchaProducer.createImage(capStr); image = captchaProducer.createImage(capStr);
} }
CacheUtils.put(CacheConstants.CAPTCHA_CODE_KEY, uuid, code, Constants.CAPTCHA_EXPIRATION, TimeUnit.MINUTES);
redisCache.setCacheObject(verifyKey, code, Constants.CAPTCHA_EXPIRATION, TimeUnit.MINUTES);
// 转换流信息写出 // 转换流信息写出
FastByteArrayOutputStream os = new FastByteArrayOutputStream(); FastByteArrayOutputStream os = new FastByteArrayOutputStream();
try try {
{
ImageIO.write(image, "jpg", os); ImageIO.write(image, "jpg", os);
} } catch (IOException e) {
catch (IOException e)
{
return AjaxResult.error(e.getMessage()); return AjaxResult.error(e.getMessage());
} }
ajax.put("uuid", uuid); ajax.put("uuid", uuid);
ajax.put("img", Base64.encode(os.toByteArray())); ajax.put("img", Base64.encode(os.toByteArray()));
return ajax; return ajax;

View File

@ -1,16 +1,15 @@
package com.ruoyi.web.controller.monitor; package com.ruoyi.web.controller.monitor;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Properties; import java.util.Properties;
import java.util.Set; import java.util.Set;
import java.util.TreeSet; import java.util.TreeSet;
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.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
@ -19,6 +18,8 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import com.ruoyi.common.constant.CacheConstants; import com.ruoyi.common.constant.CacheConstants;
import com.ruoyi.common.core.domain.AjaxResult; 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.common.utils.StringUtils;
import com.ruoyi.system.domain.SysCache; import com.ruoyi.system.domain.SysCache;
@ -31,9 +32,8 @@ import com.ruoyi.system.domain.SysCache;
@RequestMapping("/monitor/cache") @RequestMapping("/monitor/cache")
public class CacheController public class CacheController
{ {
@Autowired private static String tmpCacheName = "";
private RedisTemplate<String, String> redisTemplate;
private final static List<SysCache> caches = new ArrayList<SysCache>(); private final static List<SysCache> caches = new ArrayList<SysCache>();
{ {
caches.add(new SysCache(CacheConstants.LOGIN_TOKEN_KEY, "用户信息")); caches.add(new SysCache(CacheConstants.LOGIN_TOKEN_KEY, "用户信息"));
@ -49,23 +49,24 @@ public class CacheController
@GetMapping() @GetMapping()
public AjaxResult getInfo() throws Exception public AjaxResult getInfo() throws Exception
{ {
Properties info = (Properties) redisTemplate.execute((RedisCallback<Object>) connection -> connection.info());
Properties commandStats = (Properties) redisTemplate.execute((RedisCallback<Object>) connection -> connection.info("commandstats"));
Object dbSize = redisTemplate.execute((RedisCallback<Object>) connection -> connection.dbSize());
Map<String, Object> result = new HashMap<>(3); Map<String, Object> result = new HashMap<>(3);
result.put("info", info); if (CacheUtils.getCacheManager() instanceof RedisCacheManager)
result.put("dbSize", dbSize); {
Properties info = (Properties) CacheUtils.getRedisTemplate().execute((RedisCallback<Object>) connection -> connection.info());
List<Map<String, String>> pieList = new ArrayList<>(); Properties commandStats = (Properties) CacheUtils.getRedisTemplate().execute((RedisCallback<Object>) connection -> connection.info("commandstats"));
commandStats.stringPropertyNames().forEach(key -> { Object dbSize = CacheUtils.getRedisTemplate().execute((RedisCallback<Object>) connection -> connection.dbSize());
Map<String, String> data = new HashMap<>(2); result.put("info", info);
String property = commandStats.getProperty(key); result.put("dbSize", dbSize);
data.put("name", StringUtils.removeStart(key, "cmdstat_")); List<Map<String, String>> pieList = new ArrayList<>();
data.put("value", StringUtils.substringBetween(property, "calls=", ",usec")); commandStats.stringPropertyNames().forEach(key -> {
pieList.add(data); Map<String, String> data = new HashMap<>(2);
}); String property = commandStats.getProperty(key);
result.put("commandStats", pieList); 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); return AjaxResult.success(result);
} }
@ -80,16 +81,23 @@ public class CacheController
@GetMapping("/getKeys/{cacheName}") @GetMapping("/getKeys/{cacheName}")
public AjaxResult getCacheKeys(@PathVariable String cacheName) public AjaxResult getCacheKeys(@PathVariable String cacheName)
{ {
Set<String> cacheKeys = redisTemplate.keys(cacheName + "*"); tmpCacheName = cacheName;
return AjaxResult.success(new TreeSet<>(cacheKeys)); Set<String> keyset = CacheUtils.getkeys(cacheName);
return AjaxResult.success(new TreeSet<>(keyset));
} }
@PreAuthorize("@ss.hasPermi('monitor:cache:list')") @PreAuthorize("@ss.hasPermi('monitor:cache:list')")
@GetMapping("/getValue/{cacheName}/{cacheKey}") @GetMapping("/getValue/{cacheName}/{cacheKey}")
public AjaxResult getCacheValue(@PathVariable String cacheName, @PathVariable String cacheKey) public AjaxResult getCacheValue(@PathVariable String cacheName, @PathVariable String cacheKey)
{ {
String cacheValue = redisTemplate.opsForValue().get(cacheKey); ValueWrapper valueWrapper = CacheUtils.get(cacheName, cacheKey);
SysCache sysCache = new SysCache(cacheName, cacheKey, cacheValue); SysCache sysCache = new SysCache();
sysCache.setCacheName(cacheName);
sysCache.setCacheKey(cacheKey);
if (StringUtils.isNotNull(valueWrapper))
{
sysCache.setCacheValue(Convert.toStr(valueWrapper.get(), ""));
}
return AjaxResult.success(sysCache); return AjaxResult.success(sysCache);
} }
@ -97,8 +105,7 @@ public class CacheController
@DeleteMapping("/clearCacheName/{cacheName}") @DeleteMapping("/clearCacheName/{cacheName}")
public AjaxResult clearCacheName(@PathVariable String cacheName) public AjaxResult clearCacheName(@PathVariable String cacheName)
{ {
Collection<String> cacheKeys = redisTemplate.keys(cacheName + "*"); CacheUtils.clear(cacheName);
redisTemplate.delete(cacheKeys);
return AjaxResult.success(); return AjaxResult.success();
} }
@ -106,7 +113,7 @@ public class CacheController
@DeleteMapping("/clearCacheKey/{cacheKey}") @DeleteMapping("/clearCacheKey/{cacheKey}")
public AjaxResult clearCacheKey(@PathVariable String cacheKey) public AjaxResult clearCacheKey(@PathVariable String cacheKey)
{ {
redisTemplate.delete(cacheKey); CacheUtils.removeIfPresent(tmpCacheName, cacheKey);
return AjaxResult.success(); return AjaxResult.success();
} }
@ -114,8 +121,10 @@ public class CacheController
@DeleteMapping("/clearCacheAll") @DeleteMapping("/clearCacheAll")
public AjaxResult clearCacheAll() public AjaxResult clearCacheAll()
{ {
Collection<String> cacheKeys = redisTemplate.keys("*"); for (String cacheName : CacheUtils.getCacheManager().getCacheNames())
redisTemplate.delete(cacheKeys); {
CacheUtils.clear(cacheName);
}
return AjaxResult.success(); return AjaxResult.success();
} }
} }

View File

@ -1,27 +1,23 @@
package com.ruoyi.web.controller.monitor; package com.ruoyi.web.controller.monitor;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
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.RestController;
import com.ruoyi.common.annotation.Log; import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.constant.CacheConstants; import com.ruoyi.common.constant.CacheConstants;
import com.ruoyi.common.core.controller.BaseController; import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult; import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.model.LoginUser; import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.core.page.TableDataInfo; import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.enums.BusinessType; import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.CacheUtils;
import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.domain.SysUserOnline; import com.ruoyi.system.domain.SysUserOnline;
import com.ruoyi.system.service.ISysUserOnlineService; import com.ruoyi.system.service.ISysUserOnlineService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
/** /**
* 在线用户监控 * 在线用户监控
@ -35,18 +31,15 @@ public class SysUserOnlineController extends BaseController
@Autowired @Autowired
private ISysUserOnlineService userOnlineService; private ISysUserOnlineService userOnlineService;
@Autowired
private RedisCache redisCache;
@PreAuthorize("@ss.hasPermi('monitor:online:list')") @PreAuthorize("@ss.hasPermi('monitor:online:list')")
@GetMapping("/list") @GetMapping("/list")
public TableDataInfo list(String ipaddr, String userName) public TableDataInfo list(String ipaddr, String userName)
{ {
Collection<String> keys = redisCache.keys(CacheConstants.LOGIN_TOKEN_KEY + "*"); Collection<String> keys = CacheUtils.getkeys(CacheConstants.LOGIN_TOKEN_KEY);
List<SysUserOnline> userOnlineList = new ArrayList<SysUserOnline>(); List<SysUserOnline> userOnlineList = new ArrayList<SysUserOnline>();
for (String key : keys) for (String key : keys)
{ {
LoginUser user = redisCache.getCacheObject(key); LoginUser user = CacheUtils.get(CacheConstants.LOGIN_TOKEN_KEY, key, LoginUser.class);
if (StringUtils.isNotEmpty(ipaddr) && StringUtils.isNotEmpty(userName)) if (StringUtils.isNotEmpty(ipaddr) && StringUtils.isNotEmpty(userName))
{ {
userOnlineList.add(userOnlineService.selectOnlineByInfo(ipaddr, userName, user)); userOnlineList.add(userOnlineService.selectOnlineByInfo(ipaddr, userName, user));
@ -77,7 +70,7 @@ public class SysUserOnlineController extends BaseController
@DeleteMapping("/{tokenId}") @DeleteMapping("/{tokenId}")
public AjaxResult forceLogout(@PathVariable String tokenId) public AjaxResult forceLogout(@PathVariable String tokenId)
{ {
redisCache.deleteObject(CacheConstants.LOGIN_TOKEN_KEY + tokenId); CacheUtils.removeIfPresent(CacheConstants.LOGIN_TOKEN_KEY, tokenId);
return success(); return success();
} }
} }

View File

@ -4,6 +4,8 @@ import java.util.ArrayList;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import com.ruoyi.common.utils.CacheUtils;
import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PathVariable;

View File

@ -6,9 +6,10 @@ spring:
druid: druid:
# 主库数据源 # 主库数据源
master: master:
url: jdbc:mysql://localhost:3306/ry-vue?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8 # url: jdbc:mysql://localhost:3306/ry-vue?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
url: jdbc:mysql://192.168.2.137:33306/ry-vue?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
username: root username: root
password: password password: 1qaz@WSX
# 从库数据源 # 从库数据源
slave: slave:
# 从数据源开关/默认关闭 # 从数据源开关/默认关闭

View File

@ -65,28 +65,38 @@ spring:
restart: restart:
# 热部署开关 # 热部署开关
enabled: true enabled: true
# redis 配置 cache:
redis: # 指定缓存类型 ehcache 本地缓存 redis 缓存
# 地址 type: ehcache
host: localhost ehcache:
# 端口默认为6379 config: classpath:ehcache.xml
port: 6379 redis:
# 数据库索引 # 指定存活时间ms
database: 0 time-to-live: 86400000
# 密码 # 指定前缀
password: use-key-prefix: true
# 连接超时时间 # 是否缓存空值,可以防止缓存穿透
timeout: 10s cache-null-values: true
lettuce: # 地址
pool: host: 192.168.2.137
# 连接池中的最小空闲连接 # 端口默认为6379
min-idle: 0 port: 26379
# 连接池中的最大空闲连接 # 数据库索引
max-idle: 8 database: 0
# 连接池的最大数据库连接数 # 密码
max-active: 8 password:
# #连接池最大阻塞等待时间(使用负值表示没有限制) # 连接超时时间
max-wait: -1ms timeout: 10s
lettuce:
pool:
# 连接池中的最小空闲连接
min-idle: 0
# 连接池中的最大空闲连接
max-idle: 8
# 连接池的最大数据库连接数
max-active: 8
# #连接池最大阻塞等待时间(使用负值表示没有限制)
max-wait: -1ms
# token配置 # token配置
token: token:
@ -97,8 +107,17 @@ token:
# 令牌有效期默认30分钟 # 令牌有效期默认30分钟
expireTime: 30 expireTime: 30
# MyBatis配置 ## MyBatis配置
mybatis: #mybatis:
# # 搜索指定包别名
# typeAliasesPackage: com.ruoyi.**.domain
# # 配置mapper的扫描找到所有的mapper.xml映射文件
# mapperLocations: classpath*:mapper/**/*Mapper.xml
# # 加载全局的配置文件
# configLocation: classpath:mybatis/mybatis-config.xml
# MyBatis Plus配置
mybatis-plus:
# 搜索指定包别名 # 搜索指定包别名
typeAliasesPackage: com.ruoyi.**.domain typeAliasesPackage: com.ruoyi.**.domain
# 配置mapper的扫描找到所有的mapper.xml映射文件 # 配置mapper的扫描找到所有的mapper.xml映射文件
@ -115,7 +134,7 @@ pagehelper:
# Swagger配置 # Swagger配置
swagger: swagger:
# 是否开启swagger # 是否开启swagger
enabled: true enabled: false
# 请求前缀 # 请求前缀
pathMapping: /dev-api pathMapping: /dev-api

View File

@ -1,7 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<configuration> <configuration>
<!-- 日志存放路径 --> <!-- 日志存放路径 -->
<property name="log.path" value="/home/ruoyi/logs" /> <!-- <property name="log.path" value="/home/ruoyi/logs" />-->
<property name="log.path" value="./logs" />
<!-- 日志输出格式 --> <!-- 日志输出格式 -->
<property name="log.pattern" value="%d{HH:mm:ss.SSS} [%thread] %-5level %logger{20} - [%method,%line] - %msg%n" /> <property name="log.pattern" value="%d{HH:mm:ss.SSS} [%thread] %-5level %logger{20} - [%method,%line] - %msg%n" />

View File

@ -119,6 +119,30 @@
<artifactId>javax.servlet-api</artifactId> <artifactId>javax.servlet-api</artifactId>
</dependency> </dependency>
<!-- SpringCache的依赖配置 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<!-- Ehcache缓存管理器 -->
<dependency>
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache</artifactId>
</dependency>
<!-- mybatis-plus 增强CRUD -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.4</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies> </dependencies>
</project> </project>

View File

@ -10,35 +10,35 @@ public class CacheConstants
/** /**
* 登录用户 redis key * 登录用户 redis key
*/ */
public static final String LOGIN_TOKEN_KEY = "login_tokens:"; public static final String LOGIN_TOKEN_KEY = "login_tokens";
/** /**
* 验证码 redis key * 验证码 redis key
*/ */
public static final String CAPTCHA_CODE_KEY = "captcha_codes:"; public static final String CAPTCHA_CODE_KEY = "captcha_codes";
/** /**
* 参数管理 cache key * 参数管理 cache key
*/ */
public static final String SYS_CONFIG_KEY = "sys_config:"; public static final String SYS_CONFIG_KEY = "sys_config";
/** /**
* 字典管理 cache key * 字典管理 cache key
*/ */
public static final String SYS_DICT_KEY = "sys_dict:"; public static final String SYS_DICT_KEY = "sys_dict";
/** /**
* 防重提交 redis key * 防重提交 redis key
*/ */
public static final String REPEAT_SUBMIT_KEY = "repeat_submit:"; public static final String REPEAT_SUBMIT_KEY = "repeat_submit";
/** /**
* 限流 redis key * 限流 redis key
*/ */
public static final String RATE_LIMIT_KEY = "rate_limit:"; public static final String RATE_LIMIT_KEY = "rate_limit";
/** /**
* 登录账户密码错误次数 redis key * 登录账户密码错误次数 redis key
*/ */
public static final String PWD_ERR_CNT_KEY = "pwd_err_cnt:"; public static final String PWD_ERR_CNT_KEY = "pwd_err_cnt";
} }

View File

@ -1,12 +1,9 @@
package com.ruoyi.common.utils; package com.ruoyi.common.utils;
import java.util.Collection;
import java.util.List;
import com.alibaba.fastjson2.JSONArray;
import com.ruoyi.common.constant.CacheConstants; import com.ruoyi.common.constant.CacheConstants;
import com.ruoyi.common.core.domain.entity.SysDictData; import com.ruoyi.common.core.domain.entity.SysDictData;
import com.ruoyi.common.core.redis.RedisCache; import org.springframework.cache.Cache;
import com.ruoyi.common.utils.spring.SpringUtils; import java.util.List;
/** /**
* 字典工具类 * 字典工具类
@ -28,7 +25,7 @@ public class DictUtils
*/ */
public static void setDictCache(String key, List<SysDictData> dictDatas) public static void setDictCache(String key, List<SysDictData> dictDatas)
{ {
SpringUtils.getBean(RedisCache.class).setCacheObject(getCacheKey(key), dictDatas); getDictCacheKey().put(key, dictDatas);
} }
/** /**
@ -37,12 +34,13 @@ public class DictUtils
* @param key 参数键 * @param key 参数键
* @return dictDatas 字典数据列表 * @return dictDatas 字典数据列表
*/ */
@SuppressWarnings("unchecked")
public static List<SysDictData> getDictCache(String key) public static List<SysDictData> getDictCache(String key)
{ {
JSONArray arrayCache = SpringUtils.getBean(RedisCache.class).getCacheObject(getCacheKey(key)); List<SysDictData> arrayCache = (List<SysDictData>) getDictCacheKey().get(key, List.class);
if (StringUtils.isNotNull(arrayCache)) if (StringUtils.isNotNull(arrayCache))
{ {
return arrayCache.toList(SysDictData.class); return arrayCache;
} }
return null; return null;
} }
@ -214,7 +212,7 @@ public class DictUtils
*/ */
public static void removeDictCache(String key) public static void removeDictCache(String key)
{ {
SpringUtils.getBean(RedisCache.class).deleteObject(getCacheKey(key)); getDictCacheKey().evict(key);
} }
/** /**
@ -222,18 +220,16 @@ public class DictUtils
*/ */
public static void clearDictCache() public static void clearDictCache()
{ {
Collection<String> keys = SpringUtils.getBean(RedisCache.class).keys(CacheConstants.SYS_DICT_KEY + "*"); getDictCacheKey().clear();
SpringUtils.getBean(RedisCache.class).deleteObject(keys);
} }
/** /**
* 设置cache key * 获取dict缓存
* *
* @param configKey 参数键 * @return 缓存Cache
* @return 缓存键key
*/ */
public static String getCacheKey(String configKey) public static Cache getDictCacheKey()
{ {
return CacheConstants.SYS_DICT_KEY + configKey; return CacheUtils.getCache(CacheConstants.SYS_DICT_KEY);
} }
} }

View File

@ -1,8 +1,10 @@
package com.ruoyi.framework.aspectj; package com.ruoyi.framework.aspectj;
import java.lang.reflect.Method; import com.ruoyi.common.annotation.RateLimiter;
import java.util.Collections; import com.ruoyi.common.enums.LimitType;
import java.util.List; import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.ip.IpUtils;
import org.aspectj.lang.JoinPoint; import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.Before;
@ -10,14 +12,13 @@ import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired; 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.RedisTemplate;
import org.springframework.data.redis.core.script.RedisScript; import org.springframework.data.redis.core.script.RedisScript;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import com.ruoyi.common.annotation.RateLimiter; import java.lang.reflect.Method;
import com.ruoyi.common.enums.LimitType; import java.util.Collections;
import com.ruoyi.common.exception.ServiceException; import java.util.List;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.ip.IpUtils;
/** /**
* 限流处理 * 限流处理
@ -26,6 +27,7 @@ import com.ruoyi.common.utils.ip.IpUtils;
*/ */
@Aspect @Aspect
@Component @Component
@ConditionalOnProperty(prefix = "spring.cache", name = { "type" }, havingValue = "redis", matchIfMissing = false)
public class RateLimiterAspect public class RateLimiterAspect
{ {
private static final Logger log = LoggerFactory.getLogger(RateLimiterAspect.class); private static final Logger log = LoggerFactory.getLogger(RateLimiterAspect.class);
@ -51,7 +53,6 @@ public class RateLimiterAspect
{ {
int time = rateLimiter.time(); int time = rateLimiter.time();
int count = rateLimiter.count(); int count = rateLimiter.count();
String combineKey = getCombineKey(rateLimiter, point); String combineKey = getCombineKey(rateLimiter, point);
List<Object> keys = Collections.singletonList(combineKey); List<Object> keys = Collections.singletonList(combineKey);
try try

View File

@ -1,132 +0,0 @@
package com.ruoyi.framework.config;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import javax.sql.DataSource;
import org.apache.ibatis.io.VFS;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.boot.autoconfigure.SpringBootVFS;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.classreading.MetadataReaderFactory;
import org.springframework.util.ClassUtils;
import com.ruoyi.common.utils.StringUtils;
/**
* Mybatis支持*匹配扫描包
*
* @author ruoyi
*/
@Configuration
public class MyBatisConfig
{
@Autowired
private Environment env;
static final String DEFAULT_RESOURCE_PATTERN = "**/*.class";
public static String setTypeAliasesPackage(String typeAliasesPackage)
{
ResourcePatternResolver resolver = (ResourcePatternResolver) new PathMatchingResourcePatternResolver();
MetadataReaderFactory metadataReaderFactory = new CachingMetadataReaderFactory(resolver);
List<String> allResult = new ArrayList<String>();
try
{
for (String aliasesPackage : typeAliasesPackage.split(","))
{
List<String> result = new ArrayList<String>();
aliasesPackage = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX
+ ClassUtils.convertClassNameToResourcePath(aliasesPackage.trim()) + "/" + DEFAULT_RESOURCE_PATTERN;
Resource[] resources = resolver.getResources(aliasesPackage);
if (resources != null && resources.length > 0)
{
MetadataReader metadataReader = null;
for (Resource resource : resources)
{
if (resource.isReadable())
{
metadataReader = metadataReaderFactory.getMetadataReader(resource);
try
{
result.add(Class.forName(metadataReader.getClassMetadata().getClassName()).getPackage().getName());
}
catch (ClassNotFoundException e)
{
e.printStackTrace();
}
}
}
}
if (result.size() > 0)
{
HashSet<String> hashResult = new HashSet<String>(result);
allResult.addAll(hashResult);
}
}
if (allResult.size() > 0)
{
typeAliasesPackage = String.join(",", (String[]) allResult.toArray(new String[0]));
}
else
{
throw new RuntimeException("mybatis typeAliasesPackage 路径扫描错误,参数typeAliasesPackage:" + typeAliasesPackage + "未找到任何包");
}
}
catch (IOException e)
{
e.printStackTrace();
}
return typeAliasesPackage;
}
public Resource[] resolveMapperLocations(String[] mapperLocations)
{
ResourcePatternResolver resourceResolver = new PathMatchingResourcePatternResolver();
List<Resource> resources = new ArrayList<Resource>();
if (mapperLocations != null)
{
for (String mapperLocation : mapperLocations)
{
try
{
Resource[] mappers = resourceResolver.getResources(mapperLocation);
resources.addAll(Arrays.asList(mappers));
}
catch (IOException e)
{
// ignore
}
}
}
return resources.toArray(new Resource[resources.size()]);
}
@Bean
public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception
{
String typeAliasesPackage = env.getProperty("mybatis.typeAliasesPackage");
String mapperLocations = env.getProperty("mybatis.mapperLocations");
String configLocation = env.getProperty("mybatis.configLocation");
typeAliasesPackage = setTypeAliasesPackage(typeAliasesPackage);
VFS.addImplClass(SpringBootVFS.class);
final SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
sessionFactory.setDataSource(dataSource);
sessionFactory.setTypeAliasesPackage(typeAliasesPackage);
sessionFactory.setMapperLocations(resolveMapperLocations(StringUtils.split(mapperLocations, ",")));
sessionFactory.setConfigLocation(new DefaultResourceLoader().getResource(configLocation));
return sessionFactory.getObject();
}
}

View File

@ -1,13 +1,19 @@
package com.ruoyi.framework.config; package com.ruoyi.framework.config;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CachingConfigurerSupport; import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; 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.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript; import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.StringRedisSerializer; import org.springframework.data.redis.serializer.StringRedisSerializer;
import java.time.Duration;
/** /**
* redis配置 * redis配置
@ -15,26 +21,47 @@ import org.springframework.data.redis.serializer.StringRedisSerializer;
* @author ruoyi * @author ruoyi
*/ */
@Configuration @Configuration
@EnableCaching @ConditionalOnProperty(prefix = "spring.cache", name = { "type" }, havingValue = "redis", matchIfMissing = false)
public class RedisConfig extends CachingConfigurerSupport public class RedisConfig extends CachingConfigurerSupport
{ {
@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 @Bean
@SuppressWarnings(value = { "unchecked", "rawtypes" }) @SuppressWarnings(value = { "unchecked", "rawtypes" })
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory connectionFactory) public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory connectionFactory)
{ {
RedisTemplate<Object, Object> template = new RedisTemplate<>(); RedisTemplate<Object, Object> template = new RedisTemplate<>();
template.setConnectionFactory(connectionFactory); template.setConnectionFactory(connectionFactory);
FastJson2JsonRedisSerializer serializer = new FastJson2JsonRedisSerializer(Object.class); FastJson2JsonRedisSerializer serializer = new FastJson2JsonRedisSerializer(Object.class);
// 使用StringRedisSerializer来序列化和反序列化redis的key值 // 使用StringRedisSerializer来序列化和反序列化redis的key值
template.setKeySerializer(new StringRedisSerializer()); template.setKeySerializer(new StringRedisSerializer());
template.setValueSerializer(serializer); template.setValueSerializer(serializer);
// Hash的key也采用StringRedisSerializer的序列化方式 // Hash的key也采用StringRedisSerializer的序列化方式
template.setHashKeySerializer(new StringRedisSerializer()); template.setHashKeySerializer(new StringRedisSerializer());
template.setHashValueSerializer(serializer); template.setHashValueSerializer(serializer);
template.afterPropertiesSet(); template.afterPropertiesSet();
return template; return template;
} }

View File

@ -1,20 +1,19 @@
package com.ruoyi.framework.interceptor.impl; package com.ruoyi.framework.interceptor.impl;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import javax.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.alibaba.fastjson2.JSON;
import com.ruoyi.common.annotation.RepeatSubmit; import com.ruoyi.common.annotation.RepeatSubmit;
import com.ruoyi.common.constant.CacheConstants; import com.ruoyi.common.constant.CacheConstants;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.filter.RepeatedlyRequestWrapper; import com.ruoyi.common.filter.RepeatedlyRequestWrapper;
import com.ruoyi.common.utils.CacheUtils;
import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.http.HttpHelper; import com.ruoyi.common.utils.http.HttpHelper;
import com.ruoyi.framework.interceptor.RepeatSubmitInterceptor; import com.ruoyi.framework.interceptor.RepeatSubmitInterceptor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
/** /**
* 判断请求url和数据是否和上一次相同 * 判断请求url和数据是否和上一次相同
@ -33,9 +32,6 @@ public class SameUrlDataInterceptor extends RepeatSubmitInterceptor
@Value("${token.header}") @Value("${token.header}")
private String header; private String header;
@Autowired
private RedisCache redisCache;
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@Override @Override
public boolean isRepeatSubmit(HttpServletRequest request, RepeatSubmit annotation) public boolean isRepeatSubmit(HttpServletRequest request, RepeatSubmit annotation)
@ -46,7 +42,6 @@ public class SameUrlDataInterceptor extends RepeatSubmitInterceptor
RepeatedlyRequestWrapper repeatedlyRequest = (RepeatedlyRequestWrapper) request; RepeatedlyRequestWrapper repeatedlyRequest = (RepeatedlyRequestWrapper) request;
nowParams = HttpHelper.getBodyString(repeatedlyRequest); nowParams = HttpHelper.getBodyString(repeatedlyRequest);
} }
// body参数为空获取Parameter的数据 // body参数为空获取Parameter的数据
if (StringUtils.isEmpty(nowParams)) if (StringUtils.isEmpty(nowParams))
{ {
@ -55,17 +50,13 @@ public class SameUrlDataInterceptor extends RepeatSubmitInterceptor
Map<String, Object> nowDataMap = new HashMap<String, Object>(); Map<String, Object> nowDataMap = new HashMap<String, Object>();
nowDataMap.put(REPEAT_PARAMS, nowParams); nowDataMap.put(REPEAT_PARAMS, nowParams);
nowDataMap.put(REPEAT_TIME, System.currentTimeMillis()); nowDataMap.put(REPEAT_TIME, System.currentTimeMillis());
// 请求地址作为存放cache的key值 // 请求地址作为存放cache的key值
String url = request.getRequestURI(); String url = request.getRequestURI();
// 唯一值没有消息头则使用请求地址 // 唯一值没有消息头则使用请求地址
String submitKey = StringUtils.trimToEmpty(request.getHeader(header)); String submitKey = StringUtils.trimToEmpty(request.getHeader(header));
// 唯一标识指定key + url + 消息头 // 唯一标识指定key + url + 消息头
String cacheRepeatKey = CacheConstants.REPEAT_SUBMIT_KEY + url + submitKey; String cacheRepeatKey = url + submitKey;
Object sessionObj = CacheUtils.get(CacheConstants.REPEAT_SUBMIT_KEY, cacheRepeatKey);
Object sessionObj = redisCache.getCacheObject(cacheRepeatKey);
if (sessionObj != null) if (sessionObj != null)
{ {
Map<String, Object> sessionMap = (Map<String, Object>) sessionObj; Map<String, Object> sessionMap = (Map<String, Object>) sessionObj;
@ -80,7 +71,7 @@ public class SameUrlDataInterceptor extends RepeatSubmitInterceptor
} }
Map<String, Object> cacheMap = new HashMap<String, Object>(); Map<String, Object> cacheMap = new HashMap<String, Object>();
cacheMap.put(url, nowDataMap); 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; return false;
} }

View File

@ -1,24 +1,13 @@
package com.ruoyi.framework.web.service; package com.ruoyi.framework.web.service;
import javax.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.CacheConstants;
import com.ruoyi.common.constant.Constants; import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.constant.UserConstants; import com.ruoyi.common.constant.UserConstants;
import com.ruoyi.common.core.domain.entity.SysUser; import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.model.LoginUser; 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.ServiceException;
import com.ruoyi.common.exception.user.BlackListException; import com.ruoyi.common.exception.user.*;
import com.ruoyi.common.exception.user.CaptchaException; import com.ruoyi.common.utils.CacheUtils;
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.DateUtils; import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.MessageUtils; import com.ruoyi.common.utils.MessageUtils;
import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.StringUtils;
@ -28,6 +17,13 @@ import com.ruoyi.framework.manager.factory.AsyncFactory;
import com.ruoyi.framework.security.context.AuthenticationContextHolder; import com.ruoyi.framework.security.context.AuthenticationContextHolder;
import com.ruoyi.system.service.ISysConfigService; import com.ruoyi.system.service.ISysConfigService;
import com.ruoyi.system.service.ISysUserService; import com.ruoyi.system.service.ISysUserService;
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 javax.annotation.Resource;
/** /**
* 登录校验方法 * 登录校验方法
@ -43,9 +39,6 @@ public class SysLoginService
@Resource @Resource
private AuthenticationManager authenticationManager; private AuthenticationManager authenticationManager;
@Autowired
private RedisCache redisCache;
@Autowired @Autowired
private ISysUserService userService; private ISysUserService userService;
@ -113,14 +106,13 @@ public class SysLoginService
boolean captchaEnabled = configService.selectCaptchaEnabled(); boolean captchaEnabled = configService.selectCaptchaEnabled();
if (captchaEnabled) if (captchaEnabled)
{ {
String verifyKey = CacheConstants.CAPTCHA_CODE_KEY + StringUtils.nvl(uuid, ""); String captcha = CacheUtils.get(CacheConstants.CAPTCHA_CODE_KEY, StringUtils.nvl(uuid, ""), String.class);
String captcha = redisCache.getCacheObject(verifyKey); CacheUtils.removeIfPresent(CacheConstants.CAPTCHA_CODE_KEY, StringUtils.nvl(uuid, ""));
if (captcha == null) if (captcha == null)
{ {
AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.expire"))); AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.expire")));
throw new CaptchaExpireException(); throw new CaptchaExpireException();
} }
redisCache.deleteObject(verifyKey);
if (!code.equalsIgnoreCase(captcha)) if (!code.equalsIgnoreCase(captcha))
{ {
AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.error"))); AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.error")));

View File

@ -1,17 +1,16 @@
package com.ruoyi.framework.web.service; 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.security.core.Authentication;
import org.springframework.stereotype.Component;
import com.ruoyi.common.constant.CacheConstants; import com.ruoyi.common.constant.CacheConstants;
import com.ruoyi.common.core.domain.entity.SysUser; 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.UserPasswordNotMatchException;
import com.ruoyi.common.exception.user.UserPasswordRetryLimitExceedException; import com.ruoyi.common.exception.user.UserPasswordRetryLimitExceedException;
import com.ruoyi.common.utils.CacheUtils;
import com.ruoyi.common.utils.SecurityUtils; import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.framework.security.context.AuthenticationContextHolder; import com.ruoyi.framework.security.context.AuthenticationContextHolder;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.Cache;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Component;
/** /**
* 登录密码方法 * 登录密码方法
@ -21,9 +20,6 @@ import com.ruoyi.framework.security.context.AuthenticationContextHolder;
@Component @Component
public class SysPasswordService public class SysPasswordService
{ {
@Autowired
private RedisCache redisCache;
@Value(value = "${user.password.maxRetryCount}") @Value(value = "${user.password.maxRetryCount}")
private int maxRetryCount; private int maxRetryCount;
@ -32,13 +28,12 @@ public class SysPasswordService
/** /**
* 登录账户密码错误次数缓存键名 * 登录账户密码错误次数缓存键名
* *
* @param username 用户名 * @return 缓存Cache
* @return 缓存键key
*/ */
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) public void validate(SysUser user)
@ -46,23 +41,19 @@ public class SysPasswordService
Authentication usernamePasswordAuthenticationToken = AuthenticationContextHolder.getContext(); Authentication usernamePasswordAuthenticationToken = AuthenticationContextHolder.getContext();
String username = usernamePasswordAuthenticationToken.getName(); String username = usernamePasswordAuthenticationToken.getName();
String password = usernamePasswordAuthenticationToken.getCredentials().toString(); String password = usernamePasswordAuthenticationToken.getCredentials().toString();
Integer retryCount = getCache().get(username, Integer.class);
Integer retryCount = redisCache.getCacheObject(getCacheKey(username));
if (retryCount == null) if (retryCount == null)
{ {
retryCount = 0; retryCount = 0;
} }
if (retryCount >= Integer.valueOf(maxRetryCount).intValue()) if (retryCount >= Integer.valueOf(maxRetryCount).intValue())
{ {
throw new UserPasswordRetryLimitExceedException(maxRetryCount, lockTime); throw new UserPasswordRetryLimitExceedException(maxRetryCount, lockTime);
} }
if (!matches(user, password)) if (!matches(user, password))
{ {
retryCount = retryCount + 1; retryCount = retryCount + 1;
redisCache.setCacheObject(getCacheKey(username), retryCount, lockTime, TimeUnit.MINUTES); getCache().put(username, retryCount);
throw new UserPasswordNotMatchException(); throw new UserPasswordNotMatchException();
} }
else else
@ -78,9 +69,6 @@ public class SysPasswordService
public void clearLoginRecordCache(String loginName) public void clearLoginRecordCache(String loginName)
{ {
if (redisCache.hasKey(getCacheKey(loginName))) getCache().evictIfPresent(loginName);
{
redisCache.deleteObject(getCacheKey(loginName));
}
} }
} }

View File

@ -1,15 +1,13 @@
package com.ruoyi.framework.web.service; 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.CacheConstants;
import com.ruoyi.common.constant.Constants; import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.constant.UserConstants; import com.ruoyi.common.constant.UserConstants;
import com.ruoyi.common.core.domain.entity.SysUser; import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.model.RegisterBody; 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.CaptchaException;
import com.ruoyi.common.exception.user.CaptchaExpireException; import com.ruoyi.common.exception.user.CaptchaExpireException;
import com.ruoyi.common.utils.CacheUtils;
import com.ruoyi.common.utils.MessageUtils; import com.ruoyi.common.utils.MessageUtils;
import com.ruoyi.common.utils.SecurityUtils; import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.StringUtils;
@ -17,6 +15,8 @@ import com.ruoyi.framework.manager.AsyncManager;
import com.ruoyi.framework.manager.factory.AsyncFactory; import com.ruoyi.framework.manager.factory.AsyncFactory;
import com.ruoyi.system.service.ISysConfigService; import com.ruoyi.system.service.ISysConfigService;
import com.ruoyi.system.service.ISysUserService; import com.ruoyi.system.service.ISysUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
/** /**
* 注册校验方法 * 注册校验方法
@ -32,9 +32,6 @@ public class SysRegisterService
@Autowired @Autowired
private ISysConfigService configService; private ISysConfigService configService;
@Autowired
private RedisCache redisCache;
/** /**
* 注册 * 注册
*/ */
@ -43,14 +40,12 @@ public class SysRegisterService
String msg = "", username = registerBody.getUsername(), password = registerBody.getPassword(); String msg = "", username = registerBody.getUsername(), password = registerBody.getPassword();
SysUser sysUser = new SysUser(); SysUser sysUser = new SysUser();
sysUser.setUserName(username); sysUser.setUserName(username);
// 验证码开关 // 验证码开关
boolean captchaEnabled = configService.selectCaptchaEnabled(); boolean captchaEnabled = configService.selectCaptchaEnabled();
if (captchaEnabled) if (captchaEnabled)
{ {
validateCaptcha(username, registerBody.getCode(), registerBody.getUuid()); validateCaptcha(username, registerBody.getCode(), registerBody.getUuid());
} }
if (StringUtils.isEmpty(username)) if (StringUtils.isEmpty(username))
{ {
msg = "用户名不能为空"; msg = "用户名不能为空";
@ -100,9 +95,8 @@ public class SysRegisterService
*/ */
public void validateCaptcha(String username, String code, String uuid) public void validateCaptcha(String username, String code, String uuid)
{ {
String verifyKey = CacheConstants.CAPTCHA_CODE_KEY + StringUtils.nvl(uuid, ""); String captcha = CacheUtils.get(CacheConstants.CAPTCHA_CODE_KEY, StringUtils.nvl(uuid, ""), String.class);
String captcha = redisCache.getCacheObject(verifyKey); CacheUtils.removeIfPresent(CacheConstants.CAPTCHA_CODE_KEY, StringUtils.nvl(uuid, ""));
redisCache.deleteObject(verifyKey);
if (captcha == null) if (captcha == null)
{ {
throw new CaptchaExpireException(); throw new CaptchaExpireException();

View File

@ -3,21 +3,24 @@ package com.ruoyi.framework.web.service;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import com.ruoyi.common.constant.CacheConstants; import com.ruoyi.common.constant.CacheConstants;
import com.ruoyi.common.constant.Constants; import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.domain.model.LoginUser; 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.ServletUtils;
import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.ip.AddressUtils; import com.ruoyi.common.utils.ip.AddressUtils;
import com.ruoyi.common.utils.ip.IpUtils; import com.ruoyi.common.utils.ip.IpUtils;
import com.ruoyi.common.utils.uuid.IdUtils; import com.ruoyi.common.utils.uuid.IdUtils;
import eu.bitwalker.useragentutils.UserAgent; import eu.bitwalker.useragentutils.UserAgent;
import io.jsonwebtoken.Claims; import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts; import io.jsonwebtoken.Jwts;
@ -51,9 +54,6 @@ public class TokenService
private static final Long MILLIS_MINUTE_TEN = 20 * 60 * 1000L; private static final Long MILLIS_MINUTE_TEN = 20 * 60 * 1000L;
@Autowired
private RedisCache redisCache;
/** /**
* 获取用户身份信息 * 获取用户身份信息
* *
@ -70,8 +70,7 @@ public class TokenService
Claims claims = parseToken(token); Claims claims = parseToken(token);
// 解析对应的权限以及用户信息 // 解析对应的权限以及用户信息
String uuid = (String) claims.get(Constants.LOGIN_USER_KEY); String uuid = (String) claims.get(Constants.LOGIN_USER_KEY);
String userKey = getTokenKey(uuid); LoginUser user = CacheUtils.get(CacheConstants.LOGIN_TOKEN_KEY, uuid, LoginUser.class);
LoginUser user = redisCache.getCacheObject(userKey);
return user; return user;
} }
catch (Exception e) catch (Exception e)
@ -100,8 +99,7 @@ public class TokenService
{ {
if (StringUtils.isNotEmpty(token)) if (StringUtils.isNotEmpty(token))
{ {
String userKey = getTokenKey(token); CacheUtils.removeIfPresent(CacheConstants.LOGIN_TOKEN_KEY, token);
redisCache.deleteObject(userKey);
} }
} }
@ -117,7 +115,6 @@ public class TokenService
loginUser.setToken(token); loginUser.setToken(token);
setUserAgent(loginUser); setUserAgent(loginUser);
refreshToken(loginUser); refreshToken(loginUser);
Map<String, Object> claims = new HashMap<>(); Map<String, Object> claims = new HashMap<>();
claims.put(Constants.LOGIN_USER_KEY, token); claims.put(Constants.LOGIN_USER_KEY, token);
return createToken(claims); return createToken(claims);
@ -149,8 +146,7 @@ public class TokenService
loginUser.setLoginTime(System.currentTimeMillis()); loginUser.setLoginTime(System.currentTimeMillis());
loginUser.setExpireTime(loginUser.getLoginTime() + expireTime * MILLIS_MINUTE); loginUser.setExpireTime(loginUser.getLoginTime() + expireTime * MILLIS_MINUTE);
// 根据uuid将loginUser缓存 // 根据uuid将loginUser缓存
String userKey = getTokenKey(loginUser.getToken()); CacheUtils.put(CacheConstants.LOGIN_TOKEN_KEY, loginUser.getToken(), loginUser, expireTime, TimeUnit.MINUTES);
redisCache.setCacheObject(userKey, loginUser, expireTime, TimeUnit.MINUTES);
} }
/** /**
@ -223,9 +219,4 @@ public class TokenService
} }
return token; return token;
} }
private String getTokenKey(String uuid)
{
return CacheConstants.LOGIN_TOKEN_KEY + uuid;
}
} }

View File

@ -1,6 +1,7 @@
package com.ruoyi.system.mapper; package com.ruoyi.system.mapper;
import java.util.List; import java.util.List;
import com.ruoyi.system.domain.SysConfig; import com.ruoyi.system.domain.SysConfig;
/** /**

View File

@ -1,21 +1,21 @@
package com.ruoyi.system.service.impl; package com.ruoyi.system.service.impl;
import java.util.Collection;
import java.util.List;
import javax.annotation.PostConstruct;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ruoyi.common.annotation.DataSource; import com.ruoyi.common.annotation.DataSource;
import com.ruoyi.common.constant.CacheConstants; import com.ruoyi.common.constant.CacheConstants;
import com.ruoyi.common.constant.UserConstants; import com.ruoyi.common.constant.UserConstants;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.core.text.Convert; import com.ruoyi.common.core.text.Convert;
import com.ruoyi.common.enums.DataSourceType; import com.ruoyi.common.enums.DataSourceType;
import com.ruoyi.common.exception.ServiceException; import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.CacheUtils;
import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.domain.SysConfig; import com.ruoyi.system.domain.SysConfig;
import com.ruoyi.system.mapper.SysConfigMapper; import com.ruoyi.system.mapper.SysConfigMapper;
import com.ruoyi.system.service.ISysConfigService; import com.ruoyi.system.service.ISysConfigService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.Cache;
import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
import java.util.List;
/** /**
* 参数配置 服务层实现 * 参数配置 服务层实现
@ -28,9 +28,6 @@ public class SysConfigServiceImpl implements ISysConfigService
@Autowired @Autowired
private SysConfigMapper configMapper; private SysConfigMapper configMapper;
@Autowired
private RedisCache redisCache;
/** /**
* 项目启动时初始化参数到缓存 * 项目启动时初始化参数到缓存
*/ */
@ -64,7 +61,7 @@ public class SysConfigServiceImpl implements ISysConfigService
@Override @Override
public String selectConfigByKey(String configKey) 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)) if (StringUtils.isNotEmpty(configValue))
{ {
return configValue; return configValue;
@ -74,7 +71,7 @@ public class SysConfigServiceImpl implements ISysConfigService
SysConfig retConfig = configMapper.selectConfig(config); SysConfig retConfig = configMapper.selectConfig(config);
if (StringUtils.isNotNull(retConfig)) if (StringUtils.isNotNull(retConfig))
{ {
redisCache.setCacheObject(getCacheKey(configKey), retConfig.getConfigValue()); CacheUtils.put(CacheConstants.SYS_CONFIG_KEY, configKey, retConfig.getConfigValue());
return retConfig.getConfigValue(); return retConfig.getConfigValue();
} }
return StringUtils.EMPTY; return StringUtils.EMPTY;
@ -120,7 +117,7 @@ public class SysConfigServiceImpl implements ISysConfigService
int row = configMapper.insertConfig(config); int row = configMapper.insertConfig(config);
if (row > 0) if (row > 0)
{ {
redisCache.setCacheObject(getCacheKey(config.getConfigKey()), config.getConfigValue()); CacheUtils.put(CacheConstants.SYS_CONFIG_KEY, config.getConfigKey(), config.getConfigValue());
} }
return row; return row;
} }
@ -137,13 +134,12 @@ public class SysConfigServiceImpl implements ISysConfigService
SysConfig temp = configMapper.selectConfigById(config.getConfigId()); SysConfig temp = configMapper.selectConfigById(config.getConfigId());
if (!StringUtils.equals(temp.getConfigKey(), config.getConfigKey())) 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); int row = configMapper.updateConfig(config);
if (row > 0) if (row > 0)
{ {
redisCache.setCacheObject(getCacheKey(config.getConfigKey()), config.getConfigValue()); CacheUtils.put(CacheConstants.SYS_CONFIG_KEY, config.getConfigKey(), config.getConfigValue());
} }
return row; return row;
} }
@ -164,7 +160,7 @@ public class SysConfigServiceImpl implements ISysConfigService
throw new ServiceException(String.format("内置参数【%1$s】不能删除 ", config.getConfigKey())); throw new ServiceException(String.format("内置参数【%1$s】不能删除 ", config.getConfigKey()));
} }
configMapper.deleteConfigById(configId); configMapper.deleteConfigById(configId);
redisCache.deleteObject(getCacheKey(config.getConfigKey())); getCache().evict(config.getConfigKey());
} }
} }
@ -177,7 +173,7 @@ public class SysConfigServiceImpl implements ISysConfigService
List<SysConfig> configsList = configMapper.selectConfigList(new SysConfig()); List<SysConfig> configsList = configMapper.selectConfigList(new SysConfig());
for (SysConfig config : configsList) for (SysConfig config : configsList)
{ {
redisCache.setCacheObject(getCacheKey(config.getConfigKey()), config.getConfigValue()); getCache().put(config.getConfigKey(), config.getConfigValue());
} }
} }
@ -187,8 +183,7 @@ public class SysConfigServiceImpl implements ISysConfigService
@Override @Override
public void clearConfigCache() public void clearConfigCache()
{ {
Collection<String> keys = redisCache.keys(CacheConstants.SYS_CONFIG_KEY + "*"); CacheUtils.getCache(CacheConstants.SYS_CONFIG_KEY).clear();
redisCache.deleteObject(keys);
} }
/** /**
@ -220,13 +215,12 @@ public class SysConfigServiceImpl implements ISysConfigService
} }
/** /**
* 设置cache key * 获取config缓存
* *
* @param configKey 参数键 * @return
* @return 缓存键key
*/ */
private String getCacheKey(String configKey) private Cache getCache()
{ {
return CacheConstants.SYS_CONFIG_KEY + configKey; return CacheUtils.getCache(CacheConstants.SYS_CONFIG_KEY);
} }
} }