mirror of
https://gitee.com/huangge1199_admin/vue-pro.git
synced 2024-11-22 15:21:53 +08:00
彻底移除 RedisKeyDefine
This commit is contained in:
parent
95edd1d451
commit
5e7e3d816c
@ -1,47 +0,0 @@
|
|||||||
package cn.iocoder.yudao.framework.tenant.core.redis;
|
|
||||||
|
|
||||||
import cn.hutool.core.util.ArrayUtil;
|
|
||||||
import cn.iocoder.yudao.framework.redis.core.RedisKeyDefine;
|
|
||||||
import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
|
|
||||||
|
|
||||||
import java.time.Duration;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 多租户拓展的 RedisKeyDefine 实现类
|
|
||||||
*
|
|
||||||
* 由于 Redis 不同于 MySQL 有 column 字段,无法通过类似 WHERE tenant_id = ? 的方式过滤
|
|
||||||
* 所以需要通过在 Redis Key 上增加后缀的方式,进行租户之间的隔离。具体的步骤是:
|
|
||||||
* 1. 假设 Redis Key 是 user:%d,示例是 user:1;对应到多租户的 Redis Key 是 user:%d:%d,
|
|
||||||
* 2. 在 Redis DAO 中,需要使用 {@link #formatKey(Object...)} 方法,进行 Redis Key 的格式化
|
|
||||||
*
|
|
||||||
* 注意,大多数情况下,并不用使用 TenantRedisKeyDefine 实现。主要的使用场景,还是 Redis Key 可能存在冲突的情况。
|
|
||||||
* 例如说,租户 1 和 2 都有一个手机号作为 Key,则他们会存在冲突的问题
|
|
||||||
*
|
|
||||||
* @author 芋道源码
|
|
||||||
*/
|
|
||||||
public class TenantRedisKeyDefine extends RedisKeyDefine {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 多租户的 KEY 模板
|
|
||||||
*/
|
|
||||||
private static final String KEY_TEMPLATE_SUFFIX = ":%d";
|
|
||||||
|
|
||||||
public TenantRedisKeyDefine(String memo, String keyTemplate, KeyTypeEnum keyType, Class<?> valueType, Duration timeout) {
|
|
||||||
super(memo, buildKeyTemplate(keyTemplate), keyType, valueType, timeout);
|
|
||||||
}
|
|
||||||
|
|
||||||
public TenantRedisKeyDefine(String memo, String keyTemplate, KeyTypeEnum keyType, Class<?> valueType, TimeoutTypeEnum timeoutType) {
|
|
||||||
super(memo, buildKeyTemplate(keyTemplate), keyType, valueType, timeoutType);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static String buildKeyTemplate(String keyTemplate) {
|
|
||||||
return keyTemplate + KEY_TEMPLATE_SUFFIX;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String formatKey(Object... args) {
|
|
||||||
args = ArrayUtil.append(args, TenantContextHolder.getRequiredTenantId());
|
|
||||||
return super.formatKey(args);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,27 +0,0 @@
|
|||||||
package cn.iocoder.yudao.framework.tenant.core.redis;
|
|
||||||
|
|
||||||
import cn.iocoder.yudao.framework.redis.core.RedisKeyDefine;
|
|
||||||
import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
|
||||||
|
|
||||||
class TenantRedisKeyDefineTest {
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testFormatKey() {
|
|
||||||
Long tenantId = 30L;
|
|
||||||
TenantContextHolder.setTenantId(tenantId);
|
|
||||||
// 准备参数
|
|
||||||
TenantRedisKeyDefine define = new TenantRedisKeyDefine("", "user:%d:%d", RedisKeyDefine.KeyTypeEnum.HASH,
|
|
||||||
Object.class, RedisKeyDefine.TimeoutTypeEnum.FIXED);
|
|
||||||
Long userId = 10L;
|
|
||||||
Integer userType = 1;
|
|
||||||
|
|
||||||
// 调用
|
|
||||||
String key = define.formatKey(userId, userType);
|
|
||||||
// 断言
|
|
||||||
assertEquals("user:10:1:30", key);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,7 +1,5 @@
|
|||||||
package cn.iocoder.yudao.framework.captcha.config;
|
package cn.iocoder.yudao.framework.captcha.config;
|
||||||
|
|
||||||
import cn.hutool.core.util.ClassUtil;
|
|
||||||
import cn.iocoder.yudao.framework.captcha.core.enums.CaptchaRedisKeyConstants;
|
|
||||||
import cn.iocoder.yudao.framework.captcha.core.service.RedisCaptchaServiceImpl;
|
import cn.iocoder.yudao.framework.captcha.core.service.RedisCaptchaServiceImpl;
|
||||||
import com.xingyuv.captcha.properties.AjCaptchaProperties;
|
import com.xingyuv.captcha.properties.AjCaptchaProperties;
|
||||||
import com.xingyuv.captcha.service.CaptchaCacheService;
|
import com.xingyuv.captcha.service.CaptchaCacheService;
|
||||||
@ -15,12 +13,6 @@ import javax.annotation.Resource;
|
|||||||
@AutoConfiguration
|
@AutoConfiguration
|
||||||
public class YudaoCaptchaConfiguration {
|
public class YudaoCaptchaConfiguration {
|
||||||
|
|
||||||
static {
|
|
||||||
// 手动加载 Lock4jRedisKeyConstants 类,因为它不会被使用到
|
|
||||||
// 如果不加载,会导致 Redis 监控,看到它的 Redis Key 枚举
|
|
||||||
ClassUtil.loadClass(CaptchaRedisKeyConstants.class.getName());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private StringRedisTemplate stringRedisTemplate;
|
private StringRedisTemplate stringRedisTemplate;
|
||||||
|
|
||||||
|
@ -1,12 +1,5 @@
|
|||||||
package cn.iocoder.yudao.framework.captcha.core.enums;
|
package cn.iocoder.yudao.framework.captcha.core.enums;
|
||||||
|
|
||||||
import cn.iocoder.yudao.framework.redis.core.RedisKeyDefine;
|
|
||||||
import com.xingyuv.captcha.model.vo.PointVO;
|
|
||||||
|
|
||||||
import java.time.Duration;
|
|
||||||
|
|
||||||
import static cn.iocoder.yudao.framework.redis.core.RedisKeyDefine.KeyTypeEnum.STRING;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 验证码 Redis Key 枚举类
|
* 验证码 Redis Key 枚举类
|
||||||
*
|
*
|
||||||
@ -14,12 +7,22 @@ import static cn.iocoder.yudao.framework.redis.core.RedisKeyDefine.KeyTypeEnum.S
|
|||||||
*/
|
*/
|
||||||
public interface CaptchaRedisKeyConstants {
|
public interface CaptchaRedisKeyConstants {
|
||||||
|
|
||||||
RedisKeyDefine AJ_CAPTCHA_REQ_LIMIT = new RedisKeyDefine("验证码的请求限流",
|
/**
|
||||||
"AJ.CAPTCHA.REQ.LIMIT-%s-%s",
|
* 验证码的请求限流
|
||||||
STRING, Integer.class, Duration.ofSeconds(60)); // 例如说:验证失败 5 次,get 接口锁定
|
*
|
||||||
|
* KEY 格式:AJ.CAPTCHA.REQ.LIMIT-%s-%s
|
||||||
|
* VALUE 数据类型:String // 例如说:验证失败 5 次,get 接口锁定
|
||||||
|
* 过期时间:60 秒
|
||||||
|
*/
|
||||||
|
String AJ_CAPTCHA_REQ_LIMIT = "AJ.CAPTCHA.REQ.LIMIT-%s-%s";
|
||||||
|
|
||||||
RedisKeyDefine AJ_CAPTCHA_RUNNING = new RedisKeyDefine("验证码的坐标",
|
/**
|
||||||
"RUNNING:CAPTCHA:%s", // AbstractCaptchaService.REDIS_CAPTCHA_KEY
|
* 验证码的坐标
|
||||||
STRING, PointVO.class, Duration.ofSeconds(120)); // {"secretKey":"PP1w2Frr2KEejD2m","x":162,"y":5}
|
*
|
||||||
|
* KEY 格式:RUNNING:CAPTCHA:%s // AbstractCaptchaService.REDIS_CAPTCHA_KEY
|
||||||
|
* VALUE 数据类型:String // PointVO.class {"secretKey":"PP1w2Frr2KEejD2m","x":162,"y":5}
|
||||||
|
* 过期时间:120 秒
|
||||||
|
*/
|
||||||
|
String AJ_CAPTCHA_RUNNING = "RUNNING:CAPTCHA:%s";
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -106,6 +106,7 @@ public interface BaseMapperX<T> extends BaseMapper<T> {
|
|||||||
default void updateBatch(Collection<T> entities) {
|
default void updateBatch(Collection<T> entities) {
|
||||||
Db.updateBatchById(entities);
|
Db.updateBatchById(entities);
|
||||||
}
|
}
|
||||||
|
|
||||||
default void updateBatch(Collection<T> entities, int size) {
|
default void updateBatch(Collection<T> entities, int size) {
|
||||||
Db.updateBatchById(entities, size);
|
Db.updateBatchById(entities, size);
|
||||||
}
|
}
|
||||||
|
@ -1,13 +1,10 @@
|
|||||||
package cn.iocoder.yudao.framework.idempotent.core.redis;
|
package cn.iocoder.yudao.framework.idempotent.core.redis;
|
||||||
|
|
||||||
import cn.iocoder.yudao.framework.redis.core.RedisKeyDefine;
|
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import org.springframework.data.redis.core.StringRedisTemplate;
|
import org.springframework.data.redis.core.StringRedisTemplate;
|
||||||
|
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
import static cn.iocoder.yudao.framework.redis.core.RedisKeyDefine.KeyTypeEnum.STRING;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 幂等 Redis DAO
|
* 幂等 Redis DAO
|
||||||
*
|
*
|
||||||
@ -16,9 +13,14 @@ import static cn.iocoder.yudao.framework.redis.core.RedisKeyDefine.KeyTypeEnum.S
|
|||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
public class IdempotentRedisDAO {
|
public class IdempotentRedisDAO {
|
||||||
|
|
||||||
private static final RedisKeyDefine IDEMPOTENT = new RedisKeyDefine("幂等操作",
|
/**
|
||||||
"idempotent:%s", // 参数为 uuid
|
* 幂等操作
|
||||||
STRING, String.class, RedisKeyDefine.TimeoutTypeEnum.DYNAMIC);
|
*
|
||||||
|
* KEY 格式:idempotent:%s // 参数为 uuid
|
||||||
|
* VALUE 格式:String
|
||||||
|
* 过期时间:不固定
|
||||||
|
*/
|
||||||
|
private static final String IDEMPOTENT = "idempotent:%s";
|
||||||
|
|
||||||
private final StringRedisTemplate redisTemplate;
|
private final StringRedisTemplate redisTemplate;
|
||||||
|
|
||||||
@ -28,7 +30,7 @@ public class IdempotentRedisDAO {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static String formatKey(String key) {
|
private static String formatKey(String key) {
|
||||||
return String.format(IDEMPOTENT.getKeyTemplate(), key);
|
return String.format(IDEMPOTENT, key);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,21 +1,13 @@
|
|||||||
package cn.iocoder.yudao.framework.lock4j.config;
|
package cn.iocoder.yudao.framework.lock4j.config;
|
||||||
|
|
||||||
import cn.hutool.core.util.ClassUtil;
|
|
||||||
import com.baomidou.lock.spring.boot.autoconfigure.LockAutoConfiguration;
|
|
||||||
import cn.iocoder.yudao.framework.lock4j.core.DefaultLockFailureStrategy;
|
import cn.iocoder.yudao.framework.lock4j.core.DefaultLockFailureStrategy;
|
||||||
import cn.iocoder.yudao.framework.lock4j.core.Lock4jRedisKeyConstants;
|
import com.baomidou.lock.spring.boot.autoconfigure.LockAutoConfiguration;
|
||||||
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
|
|
||||||
@AutoConfiguration(before = LockAutoConfiguration.class)
|
@AutoConfiguration(before = LockAutoConfiguration.class)
|
||||||
public class YudaoLock4jConfiguration {
|
public class YudaoLock4jConfiguration {
|
||||||
|
|
||||||
static {
|
|
||||||
// 手动加载 Lock4jRedisKeyConstants 类,因为它不会被使用到
|
|
||||||
// 如果不加载,会导致 Redis 监控,看到它的 Redis Key 枚举
|
|
||||||
ClassUtil.loadClass(Lock4jRedisKeyConstants.class.getName());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public DefaultLockFailureStrategy lockFailureStrategy() {
|
public DefaultLockFailureStrategy lockFailureStrategy() {
|
||||||
return new DefaultLockFailureStrategy();
|
return new DefaultLockFailureStrategy();
|
||||||
|
@ -1,10 +1,5 @@
|
|||||||
package cn.iocoder.yudao.framework.lock4j.core;
|
package cn.iocoder.yudao.framework.lock4j.core;
|
||||||
|
|
||||||
import cn.iocoder.yudao.framework.redis.core.RedisKeyDefine;
|
|
||||||
import org.redisson.api.RLock;
|
|
||||||
|
|
||||||
import static cn.iocoder.yudao.framework.redis.core.RedisKeyDefine.KeyTypeEnum.HASH;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Lock4j Redis Key 枚举类
|
* Lock4j Redis Key 枚举类
|
||||||
*
|
*
|
||||||
@ -12,8 +7,13 @@ import static cn.iocoder.yudao.framework.redis.core.RedisKeyDefine.KeyTypeEnum.H
|
|||||||
*/
|
*/
|
||||||
public interface Lock4jRedisKeyConstants {
|
public interface Lock4jRedisKeyConstants {
|
||||||
|
|
||||||
RedisKeyDefine LOCK4J = new RedisKeyDefine("分布式锁",
|
/**
|
||||||
"lock4j:%s", // 参数来自 DefaultLockKeyBuilder 类
|
* 分布式锁
|
||||||
HASH, RLock.class, RedisKeyDefine.TimeoutTypeEnum.DYNAMIC); // Redisson 的 Lock 锁,使用 Hash 数据结构
|
*
|
||||||
|
* KEY 格式:lock4j:%s // 参数来自 DefaultLockKeyBuilder 类
|
||||||
|
* VALUE 数据格式:HASH // RLock.class:Redisson 的 Lock 锁,使用 Hash 数据结构
|
||||||
|
* 过期时间:不固定
|
||||||
|
*/
|
||||||
|
String LOCK4J = "lock4j:%s";
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,113 +0,0 @@
|
|||||||
package cn.iocoder.yudao.framework.redis.core;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonValue;
|
|
||||||
import lombok.AllArgsConstructor;
|
|
||||||
import lombok.Data;
|
|
||||||
import lombok.Getter;
|
|
||||||
|
|
||||||
import java.time.Duration;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Redis Key 定义类
|
|
||||||
*
|
|
||||||
* @author 芋道源码
|
|
||||||
*/
|
|
||||||
@Data
|
|
||||||
public class RedisKeyDefine {
|
|
||||||
|
|
||||||
@Getter
|
|
||||||
@AllArgsConstructor
|
|
||||||
public enum KeyTypeEnum {
|
|
||||||
|
|
||||||
STRING("String"),
|
|
||||||
LIST("List"),
|
|
||||||
HASH("Hash"),
|
|
||||||
SET("Set"),
|
|
||||||
ZSET("Sorted Set"),
|
|
||||||
STREAM("Stream"),
|
|
||||||
PUBSUB("Pub/Sub");
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 类型
|
|
||||||
*/
|
|
||||||
@JsonValue
|
|
||||||
private final String type;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Getter
|
|
||||||
@AllArgsConstructor
|
|
||||||
public enum TimeoutTypeEnum {
|
|
||||||
|
|
||||||
FOREVER(1), // 永不超时
|
|
||||||
DYNAMIC(2), // 动态超时
|
|
||||||
FIXED(3); // 固定超时
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 类型
|
|
||||||
*/
|
|
||||||
@JsonValue
|
|
||||||
private final Integer type;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Key 模板
|
|
||||||
*/
|
|
||||||
private final String keyTemplate;
|
|
||||||
/**
|
|
||||||
* Key 类型的枚举
|
|
||||||
*/
|
|
||||||
private final KeyTypeEnum keyType;
|
|
||||||
/**
|
|
||||||
* Value 类型
|
|
||||||
*
|
|
||||||
* 如果是使用分布式锁,设置为 {@link java.util.concurrent.locks.Lock} 类型
|
|
||||||
*/
|
|
||||||
private final Class<?> valueType;
|
|
||||||
/**
|
|
||||||
* 超时类型
|
|
||||||
*/
|
|
||||||
private final TimeoutTypeEnum timeoutType;
|
|
||||||
/**
|
|
||||||
* 过期时间
|
|
||||||
*/
|
|
||||||
private final Duration timeout;
|
|
||||||
/**
|
|
||||||
* 备注
|
|
||||||
*/
|
|
||||||
private final String memo;
|
|
||||||
|
|
||||||
private RedisKeyDefine(String memo, String keyTemplate, KeyTypeEnum keyType, Class<?> valueType,
|
|
||||||
TimeoutTypeEnum timeoutType, Duration timeout) {
|
|
||||||
this.memo = memo;
|
|
||||||
this.keyTemplate = keyTemplate;
|
|
||||||
this.keyType = keyType;
|
|
||||||
this.valueType = valueType;
|
|
||||||
this.timeout = timeout;
|
|
||||||
this.timeoutType = timeoutType;
|
|
||||||
// 添加注册表
|
|
||||||
RedisKeyRegistry.add(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
public RedisKeyDefine(String memo, String keyTemplate, KeyTypeEnum keyType, Class<?> valueType, Duration timeout) {
|
|
||||||
this(memo, keyTemplate, keyType, valueType, TimeoutTypeEnum.FIXED, timeout);
|
|
||||||
}
|
|
||||||
|
|
||||||
public RedisKeyDefine(String memo, String keyTemplate, KeyTypeEnum keyType, Class<?> valueType, TimeoutTypeEnum timeoutType) {
|
|
||||||
this(memo, keyTemplate, keyType, valueType, timeoutType, Duration.ZERO);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 格式化 Key
|
|
||||||
*
|
|
||||||
* 注意,内部采用 {@link String#format(String, Object...)} 实现
|
|
||||||
*
|
|
||||||
* @param args 格式化的参数
|
|
||||||
* @return Key
|
|
||||||
*/
|
|
||||||
public String formatKey(Object... args) {
|
|
||||||
return String.format(keyTemplate, args);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,28 +0,0 @@
|
|||||||
package cn.iocoder.yudao.framework.redis.core;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@link RedisKeyDefine} 注册表
|
|
||||||
*/
|
|
||||||
public class RedisKeyRegistry {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Redis RedisKeyDefine 数组
|
|
||||||
*/
|
|
||||||
private static final List<RedisKeyDefine> DEFINES = new ArrayList<>();
|
|
||||||
|
|
||||||
public static void add(RedisKeyDefine define) {
|
|
||||||
DEFINES.add(define);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static List<RedisKeyDefine> list() {
|
|
||||||
return DEFINES;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int size() {
|
|
||||||
return DEFINES.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -2,8 +2,3 @@
|
|||||||
GET {{baseUrl}}/infra/redis/get-monitor-info
|
GET {{baseUrl}}/infra/redis/get-monitor-info
|
||||||
Authorization: Bearer {{token}}
|
Authorization: Bearer {{token}}
|
||||||
tenant-id: {{adminTenentId}}
|
tenant-id: {{adminTenentId}}
|
||||||
|
|
||||||
### 请求 /infra/redis/get-key-list 接口 => 成功
|
|
||||||
GET {{baseUrl}}/infra/redis/get-key-list
|
|
||||||
Authorization: Bearer {{token}}
|
|
||||||
tenant-id: {{adminTenentId}}
|
|
||||||
|
@ -1,27 +1,20 @@
|
|||||||
package cn.iocoder.yudao.module.infra.controller.admin.redis;
|
package cn.iocoder.yudao.module.infra.controller.admin.redis;
|
||||||
|
|
||||||
import cn.hutool.core.collection.CollUtil;
|
|
||||||
import cn.hutool.core.util.StrUtil;
|
|
||||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||||
import cn.iocoder.yudao.framework.redis.core.RedisKeyDefine;
|
|
||||||
import cn.iocoder.yudao.framework.redis.core.RedisKeyRegistry;
|
|
||||||
import cn.iocoder.yudao.module.infra.controller.admin.redis.vo.RedisKeyDefineRespVO;
|
|
||||||
import cn.iocoder.yudao.module.infra.controller.admin.redis.vo.RedisKeyValueRespVO;
|
|
||||||
import cn.iocoder.yudao.module.infra.controller.admin.redis.vo.RedisMonitorRespVO;
|
import cn.iocoder.yudao.module.infra.controller.admin.redis.vo.RedisMonitorRespVO;
|
||||||
import cn.iocoder.yudao.module.infra.convert.redis.RedisConvert;
|
import cn.iocoder.yudao.module.infra.convert.redis.RedisConvert;
|
||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
|
||||||
import io.swagger.v3.oas.annotations.Parameter;
|
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
import org.springframework.data.redis.connection.RedisServerCommands;
|
import org.springframework.data.redis.connection.RedisServerCommands;
|
||||||
import org.springframework.data.redis.core.Cursor;
|
|
||||||
import org.springframework.data.redis.core.RedisCallback;
|
import org.springframework.data.redis.core.RedisCallback;
|
||||||
import org.springframework.data.redis.core.ScanOptions;
|
|
||||||
import org.springframework.data.redis.core.StringRedisTemplate;
|
import org.springframework.data.redis.core.StringRedisTemplate;
|
||||||
import org.springframework.security.access.prepost.PreAuthorize;
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import java.util.*;
|
import java.util.Properties;
|
||||||
|
|
||||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||||
|
|
||||||
@ -47,66 +40,4 @@ public class RedisController {
|
|||||||
return success(RedisConvert.INSTANCE.build(info, dbSize, commandStats));
|
return success(RedisConvert.INSTANCE.build(info, dbSize, commandStats));
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/get-key-define-list")
|
|
||||||
@Operation(summary = "获得 Redis Key 模板列表")
|
|
||||||
@PreAuthorize("@ss.hasPermission('infra:redis:get-key-list')")
|
|
||||||
public CommonResult<List<RedisKeyDefineRespVO>> getKeyDefineList() {
|
|
||||||
List<RedisKeyDefine> keyDefines = RedisKeyRegistry.list();
|
|
||||||
return success(RedisConvert.INSTANCE.convertList(keyDefines));
|
|
||||||
}
|
|
||||||
|
|
||||||
@GetMapping("/get-key-list")
|
|
||||||
@Operation(summary = "获得 Redis keys 键名列表")
|
|
||||||
@Parameter(name = "keyTemplate", description = "Redis Key 定义", example = "true")
|
|
||||||
@PreAuthorize("@ss.hasPermission('infra:redis:get-key-list')")
|
|
||||||
public CommonResult<Set<String>> getKeyDefineList(@RequestParam("keyTemplate") String keyTemplate) {
|
|
||||||
return success(getKeyDefineList0(keyTemplate));
|
|
||||||
}
|
|
||||||
|
|
||||||
private Set<String> getKeyDefineList0(String keyTemplate) {
|
|
||||||
// key 格式化
|
|
||||||
String key = StrUtil.replace(keyTemplate, "%[s|c|b|d|x|o|f|a|e|g]", parameter -> "*");
|
|
||||||
// scan 扫描 key
|
|
||||||
Set<String> keys = new LinkedHashSet<>();
|
|
||||||
stringRedisTemplate.execute((RedisCallback<Set<String>>) connection -> {
|
|
||||||
try (Cursor<byte[]> cursor = connection.scan(ScanOptions.scanOptions().match(key).count(100).build())) {
|
|
||||||
cursor.forEachRemaining(value -> keys.add(StrUtil.utf8Str(value)));
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
return keys;
|
|
||||||
});
|
|
||||||
return keys;
|
|
||||||
}
|
|
||||||
|
|
||||||
@GetMapping("/get-key-value")
|
|
||||||
@Operation(summary = "获得 Redis key 内容")
|
|
||||||
@Parameter(name = "key", description = "Redis Key", example = "oauth2_access_token:233")
|
|
||||||
@PreAuthorize("@ss.hasPermission('infra:redis:get-key-list')")
|
|
||||||
public CommonResult<RedisKeyValueRespVO> getKeyValue(@RequestParam("key") String key) {
|
|
||||||
String value = stringRedisTemplate.opsForValue().get(key);
|
|
||||||
return success(new RedisKeyValueRespVO(key, value));
|
|
||||||
}
|
|
||||||
|
|
||||||
@DeleteMapping("/delete-key")
|
|
||||||
@Operation(summary = "删除 Redis Key")
|
|
||||||
@Parameter(name = "key", description = "Redis Key", example = "oauth2_access_token:233")
|
|
||||||
@PreAuthorize("@ss.hasPermission('infra:redis:get-key-list')")
|
|
||||||
public CommonResult<Boolean> deleteKey(@RequestParam("key") String key) {
|
|
||||||
stringRedisTemplate.delete(key);
|
|
||||||
return success(Boolean.TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
@DeleteMapping("/delete-keys")
|
|
||||||
@Operation(summary = "删除 Redis Key 根据模板")
|
|
||||||
@Parameter(name = "keyTemplate", description = "Redis Key 定义", example = "true")
|
|
||||||
@PreAuthorize("@ss.hasPermission('infra:redis:get-key-list')")
|
|
||||||
public CommonResult<Boolean> deleteKeys(@RequestParam("keyTemplate") String keyTemplate) {
|
|
||||||
Set<String> keys = getKeyDefineList0(keyTemplate);
|
|
||||||
if (CollUtil.isNotEmpty(keys)) {
|
|
||||||
stringRedisTemplate.delete(keys);
|
|
||||||
}
|
|
||||||
return success(Boolean.TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,35 +0,0 @@
|
|||||||
package cn.iocoder.yudao.module.infra.controller.admin.redis.vo;
|
|
||||||
|
|
||||||
import cn.iocoder.yudao.framework.redis.core.RedisKeyDefine;
|
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
|
||||||
import lombok.AllArgsConstructor;
|
|
||||||
import lombok.Builder;
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
import java.time.Duration;
|
|
||||||
|
|
||||||
@Schema(description = "管理后台 - Redis Key 信息 Response VO")
|
|
||||||
@Data
|
|
||||||
@Builder
|
|
||||||
@AllArgsConstructor
|
|
||||||
public class RedisKeyDefineRespVO {
|
|
||||||
|
|
||||||
@Schema(description = "Key 模板", requiredMode = Schema.RequiredMode.REQUIRED, example = "login_user:%s")
|
|
||||||
private String keyTemplate;
|
|
||||||
|
|
||||||
@Schema(description = "Key 类型的枚举", requiredMode = Schema.RequiredMode.REQUIRED, example = "String")
|
|
||||||
private RedisKeyDefine.KeyTypeEnum keyType;
|
|
||||||
|
|
||||||
@Schema(description = "Value 类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "java.lang.String")
|
|
||||||
private Class<?> valueType;
|
|
||||||
|
|
||||||
@Schema(description = "超时类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
|
||||||
private RedisKeyDefine.TimeoutTypeEnum timeoutType;
|
|
||||||
|
|
||||||
@Schema(description = "过期时间,单位:毫秒", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
|
||||||
private Duration timeout;
|
|
||||||
|
|
||||||
@Schema(description = "备注", requiredMode = Schema.RequiredMode.REQUIRED, example = "啦啦啦啦~")
|
|
||||||
private String memo;
|
|
||||||
|
|
||||||
}
|
|
@ -1,18 +0,0 @@
|
|||||||
package cn.iocoder.yudao.module.infra.controller.admin.redis.vo;
|
|
||||||
|
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
|
||||||
import lombok.AllArgsConstructor;
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
@Schema(description = "管理后台 - 单个 Redis Key Value Response VO")
|
|
||||||
@Data
|
|
||||||
@AllArgsConstructor
|
|
||||||
public class RedisKeyValueRespVO {
|
|
||||||
|
|
||||||
@Schema(description = "c5f6990767804a928f4bb96ca249febf", requiredMode = Schema.RequiredMode.REQUIRED, example = "String")
|
|
||||||
private String key;
|
|
||||||
|
|
||||||
@Schema(requiredMode = Schema.RequiredMode.REQUIRED, example = "String")
|
|
||||||
private String value;
|
|
||||||
|
|
||||||
}
|
|
@ -1,14 +1,11 @@
|
|||||||
package cn.iocoder.yudao.module.infra.convert.redis;
|
package cn.iocoder.yudao.module.infra.convert.redis;
|
||||||
|
|
||||||
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.util.StrUtil;
|
||||||
import cn.iocoder.yudao.framework.redis.core.RedisKeyDefine;
|
|
||||||
import cn.iocoder.yudao.module.infra.controller.admin.redis.vo.RedisKeyDefineRespVO;
|
|
||||||
import cn.iocoder.yudao.module.infra.controller.admin.redis.vo.RedisMonitorRespVO;
|
import cn.iocoder.yudao.module.infra.controller.admin.redis.vo.RedisMonitorRespVO;
|
||||||
import org.mapstruct.Mapper;
|
import org.mapstruct.Mapper;
|
||||||
import org.mapstruct.factory.Mappers;
|
import org.mapstruct.factory.Mappers;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
|
||||||
@Mapper
|
@Mapper
|
||||||
@ -29,6 +26,4 @@ public interface RedisConvert {
|
|||||||
return respVO;
|
return respVO;
|
||||||
}
|
}
|
||||||
|
|
||||||
List<RedisKeyDefineRespVO> convertList(List<RedisKeyDefine> list);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,5 @@
|
|||||||
package cn.iocoder.yudao.module.pay.dal.redis;
|
package cn.iocoder.yudao.module.pay.dal.redis;
|
||||||
|
|
||||||
import cn.iocoder.yudao.framework.redis.core.RedisKeyDefine;
|
|
||||||
import org.redisson.api.RLock;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 支付 Redis Key 枚举类
|
* 支付 Redis Key 枚举类
|
||||||
*
|
*
|
||||||
@ -10,9 +7,14 @@ import org.redisson.api.RLock;
|
|||||||
*/
|
*/
|
||||||
public interface RedisKeyConstants {
|
public interface RedisKeyConstants {
|
||||||
|
|
||||||
RedisKeyDefine PAY_NOTIFY_LOCK = new RedisKeyDefine("通知任务的分布式锁",
|
/**
|
||||||
"pay_notify:lock:%d", // 参数来自 DefaultLockKeyBuilder 类
|
* 通知任务的分布式锁
|
||||||
RedisKeyDefine.KeyTypeEnum.HASH, RLock.class, RedisKeyDefine.TimeoutTypeEnum.DYNAMIC); // Redisson 的 Lock 锁,使用 Hash 数据结构
|
*
|
||||||
|
* KEY 格式:pay_notify:lock:%d // 参数来自 DefaultLockKeyBuilder 类
|
||||||
|
* VALUE 数据格式:HASH // RLock.class:Redisson 的 Lock 锁,使用 Hash 数据结构
|
||||||
|
* 过期时间:不固定
|
||||||
|
*/
|
||||||
|
String PAY_NOTIFY_LOCK = "pay_notify:lock:%d";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 支付序号的缓存
|
* 支付序号的缓存
|
||||||
|
@ -33,7 +33,7 @@ public class PayNotifyLockRedisDAO {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static String formatKey(Long id) {
|
private static String formatKey(Long id) {
|
||||||
return String.format(PAY_NOTIFY_LOCK.getKeyTemplate(), id);
|
return String.format(PAY_NOTIFY_LOCK, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
POST {{baseUrl}}/system/auth/login
|
POST {{baseUrl}}/system/auth/login
|
||||||
Content-Type: application/json
|
Content-Type: application/json
|
||||||
tenant-id: {{adminTenentId}}
|
tenant-id: {{adminTenentId}}
|
||||||
|
tag: Yunai.local
|
||||||
|
|
||||||
{
|
{
|
||||||
"username": "admin",
|
"username": "admin",
|
||||||
|
Loading…
Reference in New Issue
Block a user