forked from dyf/fys-Multi-tenant
提交
This commit is contained in:
@ -36,4 +36,7 @@ public interface GlobalConstants {
|
||||
* 三方认证 redis key
|
||||
*/
|
||||
String SOCIAL_AUTH_CODE_KEY = GLOBAL_REDIS_KEY + "social_auth_codes:";
|
||||
|
||||
|
||||
String FUNCTION_ACCESS_KEY = GLOBAL_REDIS_KEY + "device:function_access:";
|
||||
}
|
||||
|
@ -0,0 +1,11 @@
|
||||
package com.fuyuanshen.common.ratelimiter.annotation;// DeviceRedisKeyAnnotation.java
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Target(ElementType.METHOD)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface FunctionAccessAnnotation {
|
||||
String value() default "";
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
package com.fuyuanshen.common.ratelimiter.annotation;// DeviceRedisKeyAnnotation.java
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Target(ElementType.METHOD)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface FunctionAccessBatcAnnotation {
|
||||
String value() default "";
|
||||
}
|
@ -0,0 +1,103 @@
|
||||
package com.fuyuanshen.common.ratelimiter.aspectj;// DeviceRedisKeyAspect.java
|
||||
import com.fuyuanshen.common.core.exception.ServiceException;
|
||||
import com.fuyuanshen.common.core.utils.StringUtils;
|
||||
import com.fuyuanshen.common.ratelimiter.annotation.FunctionAccessAnnotation;
|
||||
import com.fuyuanshen.common.redis.utils.RedisUtils;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.aspectj.lang.ProceedingJoinPoint;
|
||||
import org.aspectj.lang.annotation.Around;
|
||||
import org.aspectj.lang.annotation.Aspect;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.time.Duration;
|
||||
|
||||
import static com.fuyuanshen.common.core.constant.GlobalConstants.FUNCTION_ACCESS_KEY;
|
||||
|
||||
@Slf4j
|
||||
@Aspect
|
||||
@Component
|
||||
public class FunctionAccessAspect {
|
||||
|
||||
// 定义切点,拦截带有DeviceRedisKeyAnnotation注解的方法
|
||||
@Around("@annotation(functionAccessAnnotation)")
|
||||
public Object addDeviceRedisKey(ProceedingJoinPoint joinPoint, FunctionAccessAnnotation functionAccessAnnotation) throws Throwable {
|
||||
Object result;
|
||||
String deviceImei = null;
|
||||
|
||||
// 获取方法参数,查找设备ID
|
||||
Object[] args = joinPoint.getArgs();
|
||||
deviceImei = extractDeviceImei(args);
|
||||
|
||||
if (StringUtils.isNotBlank(deviceImei)) {
|
||||
// 生成全局Redis key
|
||||
String redisKey = generateDeviceRedisKey(deviceImei);
|
||||
String cacheKey = RedisUtils.getCacheObject(redisKey);
|
||||
if(StringUtils.isNotBlank(cacheKey) && "ACTIVE".equals(cacheKey)){
|
||||
throw new ServiceException("设备已存在访问限制,请稍后再试", 500);
|
||||
}
|
||||
// 存储到Redis中,设置过期时间
|
||||
RedisUtils.setCacheObject(redisKey, "ACTIVE", Duration.ofMinutes(30));
|
||||
log.info("设备Redis key已添加: {}", redisKey);
|
||||
}
|
||||
|
||||
// 执行原方法
|
||||
result = joinPoint.proceed();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 从方法参数中提取设备ID
|
||||
*/
|
||||
private String extractDeviceImei(Object[] args) {
|
||||
if (args == null || args.length == 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
for (Object arg : args) {
|
||||
if (arg == null) continue;
|
||||
|
||||
// 如果参数本身就是设备ID (Long类型)
|
||||
if (arg instanceof Long) {
|
||||
return arg.toString();
|
||||
}
|
||||
|
||||
// 如果参数是对象,尝试获取deviceId字段
|
||||
try {
|
||||
// 使用反射获取deviceId字段
|
||||
java.lang.reflect.Field[] fields = arg.getClass().getDeclaredFields();
|
||||
for (java.lang.reflect.Field field : fields) {
|
||||
if ("deviceImei".equalsIgnoreCase(field.getName()) ||
|
||||
"device_imei".equalsIgnoreCase(field.getName())) {
|
||||
field.setAccessible(true);
|
||||
Object value = field.get(arg);
|
||||
if (value != null) {
|
||||
return value.toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 尝试获取getId方法
|
||||
try {
|
||||
java.lang.reflect.Method getIdMethod = arg.getClass().getMethod("getDeviceImei");
|
||||
Object value = getIdMethod.invoke(arg);
|
||||
if (value != null) {
|
||||
return value.toString();
|
||||
}
|
||||
} catch (Exception ignored) {}
|
||||
|
||||
} catch (Exception e) {
|
||||
log.debug("从参数中提取设备ID时出错: {}", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成设备的全局Redis key
|
||||
*/
|
||||
private String generateDeviceRedisKey(String deviceImei) {
|
||||
return FUNCTION_ACCESS_KEY + deviceImei;
|
||||
}
|
||||
}
|
@ -0,0 +1,184 @@
|
||||
package com.fuyuanshen.common.ratelimiter.aspectj;// DeviceRedisKeyAspect.java
|
||||
import cn.hutool.json.JSON;
|
||||
import cn.hutool.json.JSONObject;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.fuyuanshen.common.core.exception.ServiceException;
|
||||
import com.fuyuanshen.common.core.utils.StringUtils;
|
||||
import com.fuyuanshen.common.ratelimiter.annotation.FunctionAccessAnnotation;
|
||||
import com.fuyuanshen.common.ratelimiter.annotation.FunctionAccessBatcAnnotation;
|
||||
import com.fuyuanshen.common.redis.utils.RedisUtils;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.aspectj.lang.ProceedingJoinPoint;
|
||||
import org.aspectj.lang.annotation.Around;
|
||||
import org.aspectj.lang.annotation.Aspect;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import static com.fuyuanshen.common.core.constant.GlobalConstants.FUNCTION_ACCESS_KEY;
|
||||
|
||||
@Slf4j
|
||||
@Aspect
|
||||
@Component
|
||||
public class FunctionAccessBatchAspect {
|
||||
|
||||
// 定义切点,拦截带有DeviceRedisKeyAnnotation注解的方法
|
||||
@Around("@annotation(functionAccessBatchAspect)")
|
||||
public Object addDeviceRedisKey(ProceedingJoinPoint joinPoint, FunctionAccessBatcAnnotation functionAccessBatchAspect) throws Throwable {
|
||||
Object result;
|
||||
String batchId = null;
|
||||
List<String> deviceImeiList = null;
|
||||
|
||||
// 获取方法参数,查找设备ID
|
||||
Object[] args = joinPoint.getArgs();
|
||||
batchId = extractDeviceBatchId(args);
|
||||
deviceImeiList = extractDeviceImeiList(args);
|
||||
if (StringUtils.isNotBlank(batchId)) {
|
||||
// 生成全局Redis key
|
||||
String redisKey = generateDeviceRedisKey(batchId);
|
||||
String cacheKey = RedisUtils.getCacheObject(redisKey);
|
||||
if(StringUtils.isNotBlank(cacheKey) && "ACTIVE".equals(cacheKey)){
|
||||
throw new ServiceException("设备已存在访问限制,请稍后再试", 500);
|
||||
}
|
||||
// 存储到Redis中,设置过期时间
|
||||
RedisUtils.setCacheObject(redisKey, JSONUtil.toJsonStr(deviceImeiList), Duration.ofMinutes(30));
|
||||
log.info("设备Redis key已添加: {}", redisKey);
|
||||
}
|
||||
|
||||
// 执行原方法
|
||||
result = joinPoint.proceed();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 从方法参数中提取设备IMEI列表
|
||||
*/
|
||||
private List<String> extractDeviceImeiList(Object[] args) {
|
||||
if (args == null || args.length == 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
for (Object arg : args) {
|
||||
if (arg == null) continue;
|
||||
|
||||
// 如果参数本身就是List<String>类型
|
||||
if (arg instanceof List) {
|
||||
List<?> list = (List<?>) arg;
|
||||
if (!list.isEmpty() && list.get(0) instanceof String) {
|
||||
// 检查是否为deviceImeiList
|
||||
return (List<String>) list;
|
||||
}
|
||||
}
|
||||
|
||||
// 如果参数是对象,尝试获取deviceImeiList字段
|
||||
try {
|
||||
// 使用反射获取deviceImeiList字段
|
||||
java.lang.reflect.Field[] fields = arg.getClass().getDeclaredFields();
|
||||
for (java.lang.reflect.Field field : fields) {
|
||||
if ("deviceImeiList".equalsIgnoreCase(field.getName()) ||
|
||||
"device_imei_list".equalsIgnoreCase(field.getName()) ||
|
||||
"deviceImeis".equalsIgnoreCase(field.getName()) ||
|
||||
"device_imeis".equalsIgnoreCase(field.getName())) {
|
||||
field.setAccessible(true);
|
||||
Object value = field.get(arg);
|
||||
if (value instanceof List) {
|
||||
List<?> list = (List<?>) value;
|
||||
if (!list.isEmpty() && list.get(0) instanceof String) {
|
||||
return (List<String>) list;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 尝试获取getDeviceImeiList方法
|
||||
try {
|
||||
java.lang.reflect.Method getDeviceImeiListMethod = arg.getClass().getMethod("getDeviceImeiList");
|
||||
Object value = getDeviceImeiListMethod.invoke(arg);
|
||||
if (value instanceof List) {
|
||||
List<?> list = (List<?>) value;
|
||||
if (!list.isEmpty() && list.get(0) instanceof String) {
|
||||
return (List<String>) list;
|
||||
}
|
||||
}
|
||||
} catch (Exception ignored) {}
|
||||
|
||||
// 尝试获取getDeviceImeis方法
|
||||
try {
|
||||
java.lang.reflect.Method getDeviceImeisMethod = arg.getClass().getMethod("getDeviceImeis");
|
||||
Object value = getDeviceImeisMethod.invoke(arg);
|
||||
if (value instanceof List) {
|
||||
List<?> list = (List<?>) value;
|
||||
if (!list.isEmpty() && list.get(0) instanceof String) {
|
||||
return (List<String>) list;
|
||||
}
|
||||
}
|
||||
} catch (Exception ignored) {}
|
||||
|
||||
} catch (Exception e) {
|
||||
log.debug("从参数中提取设备IMEI列表时出错: {}", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 从方法参数中提取设备ID
|
||||
*/
|
||||
private String extractDeviceBatchId(Object[] args) {
|
||||
if (args == null || args.length == 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
for (Object arg : args) {
|
||||
if (arg == null) continue;
|
||||
|
||||
// 如果参数本身就是设备ID (Long类型)
|
||||
if (arg instanceof Long) {
|
||||
return arg.toString();
|
||||
}
|
||||
|
||||
// 如果参数是对象,尝试获取deviceId字段
|
||||
try {
|
||||
// 使用反射获取deviceId字段
|
||||
java.lang.reflect.Field[] fields = arg.getClass().getDeclaredFields();
|
||||
for (java.lang.reflect.Field field : fields) {
|
||||
if ("batchId".equalsIgnoreCase(field.getName()) ||
|
||||
"batch_id".equalsIgnoreCase(field.getName())) {
|
||||
field.setAccessible(true);
|
||||
Object value = field.get(arg);
|
||||
if (value != null) {
|
||||
return value.toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 尝试获取getId方法
|
||||
try {
|
||||
java.lang.reflect.Method getIdMethod = arg.getClass().getMethod("batchId");
|
||||
Object value = getIdMethod.invoke(arg);
|
||||
if (value != null) {
|
||||
return value.toString();
|
||||
}
|
||||
} catch (Exception ignored) {}
|
||||
|
||||
} catch (Exception e) {
|
||||
log.debug("从参数中提取批次号时出错: {}", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成设备的全局Redis key
|
||||
*/
|
||||
private String generateDeviceRedisKey(String batchId) {
|
||||
return FUNCTION_ACCESS_KEY + batchId;
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user