package integration.advice;
import cn.hutool.core.util.ArrayUtil;
import com.ctrip.framework.apollo.spring.annotation.ApolloJsonValue;
import com.google.common.collect.ImmutableMap;
import integration.util.DesensitizeUtils;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.CodeSignature;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import java.util.LinkedHashMap;
import java.util.Map;
import static integration.util.DesensitizeUtils.encode;
@Slf4j
@Aspect
@Component
@Order(2)
public class RedisCuts {
@Pointcut("execution(* integration.util.redis.*.*(..))")
public void redisCutPoint() {
}
@Pointcut("execution(* integration.util.redis.RedisUtils.*(..))")
public void excludeCutPoint() {
}
@Around("redisCutPoint() && !excludeCutPoint()")
public Object redisAspect(ProceedingJoinPoint pjp) {
String method = pjp.getTarget().getClass().getSimpleName() + "." + pjp.getSignature().getName();
boolean needLog = checkNeedPrintLog();
Object resp = null;
try {
if (redisSwitch) {
resp = pjp.proceed();
}
} catch (Throwable throwable) {
log.warn("请求缓存异常", throwable);
resp = handlePrimitiveTypeResult(pjp);
}
if (needLog) {
log.info("{} param:{} result:{}", method, getParams(pjp), resp);
}else {
log.info("{} param:{} result:{}", method,
method.contains("set") ? "noPrint" : getParams(pjp),
method.contains("get") ? "noPrint" : resp);
}
return resp;
}
private Object handlePrimitiveTypeResult(ProceedingJoinPoint pjp) {
Signature signature = pjp.getSignature();
if (signature instanceof MethodSignature){
MethodSignature methodSignature = (MethodSignature) signature;
Class<?> returnType = methodSignature.getMethod().getReturnType();
if (PRIMITIVE_VALUE.containsKey(returnType)){
return PRIMITIVE_VALUE.get(returnType);
}
}
return null;
}
private static final Map<Class<?>, Object> PRIMITIVE_VALUE = new ImmutableMap.Builder<Class<?>, Object>()
.put(Boolean.TYPE, false)
.put(Integer.TYPE, 0)
.put(Long.TYPE, 0)
.put(Double.TYPE, 0)
.build();
private boolean checkNeedPrintLog() {
if (printLogSwitch){
return true;
}
StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
for (StackTraceElement element : stackTrace) {
if ("integration.util.redis.RedisUtils".equals(element.getClassName())){
return !element.getMethodName().contains("WithoutLog");
}
}
return true;
}
private Map<String, Object> getParams(ProceedingJoinPoint pjp) {
Map<String, Object> params = new LinkedHashMap<>();
Object[] args = pjp.getArgs();
String[] names = ((CodeSignature) pjp.getSignature()).getParameterNames();
if (ArrayUtil.isNotEmpty(names) && names.length == args.length) {
for (int i = 0; i < names.length; i++) {
params.put(names[i], args[i]);
}
}
return params;
}
}
package integration.util.redis;
import cn.hutool.core.util.NumberUtil;
import com.fasterxml.jackson.core.type.TypeReference;
import integration.configuration.ObjectRedisCodec;
import integration.util.JsonUtil;
import io.lettuce.core.RedisClient;
import io.lettuce.core.ScriptOutputType;
import io.lettuce.core.api.StatefulRedisConnection;
import org.redisson.api.RTopic;
import org.redisson.api.RedissonClient;
import org.redisson.api.listener.MessageListener;
import org.redisson.client.codec.StringCodec;
import org.springframework.context.annotation.Configuration;
import org.springframework.lang.Nullable;
import java.util.List;
import java.util.Map;
@Configuration
public class RedisUtils {
private static RedisSet setRedis;
private static RedisStr strRedis;
private static RedisKey keyRedis;
private static RedisList listRedis;
private static RedisHash hashRedis;
private static RedisScript scriptRedis;
private static RedissonClient redissonClient;
public static void setSync(String key, Object value, long timeout) {
strRedis.set(key, JsonUtil.writeValueToString(value), timeout);
}
public static void set(String key, Object value, long timeout) {
strRedis.set(key, JsonUtil.writeValueToString(value), timeout);
}
public static String setAndGetOld(String key, Object value, long timeout) {
String old = strRedis.getset(key, JsonUtil.writeValueToString(value));
expire(key, timeout);
return old;
}
public static void setAsync(String key, Object value, long timeout) {
strRedis.setAsync(key, JsonUtil.writeValueToString(value), timeout);
}
public static String getString(String key) {
return strRedis.get(key);
}
public static <T> T getObject(String key, TypeReference<T> type) {
return JsonUtil.readValue(strRedis.get(key), type);
}
public static boolean setNx(String key, String value, long exSeconds) {
boolean result;
if (result = strRedis.setNx(key, value)) {
expire(key, exSeconds);
}
return result;
}
public static long getCount(String key) {
return toLong(strRedis.get(key));
}
public static void increment(String key, long expireSeconds) {
if (strRedis.incr(key) == 1)
expire(key, expireSeconds);
}
public static void decrement(String key) {
strRedis.decr(key);
}
public static void addSet(String key, long timeout, Object... values) {
if (values.length == 0) return;
setRedis.set(key, values);
expire(key, timeout);
}
public static void remSet(String key, Object... values) {
setRedis.del(key, values);
}
public static @Nullable
Boolean existSet(String key, Object value) {
return keyRedis.exist(key) ? setRedis.exist(key, value) : null;
}
public static boolean existSetNotNull(String key, Object value) {
return setRedis.exist(key, value);
}
public static void addHash(String hashKey, Map<String, Object> map, long timeout) {
hashRedis.set(hashKey, map);
expire(hashKey, timeout);
}
public static void addHash(String hashKey, String field, Object value, long timeout) {
hashRedis.set(hashKey, field, value);
expire(hashKey, timeout);
}
public static void addHashWithoutLog(String hashKey, String field, Object value, long timeout) {
hashRedis.set(hashKey, field, value);
expire(hashKey, timeout);
}
public static <T> Map<String, T> getHash(String hashKey) {
return hashRedis.allEntrys(hashKey);
}
public static <T> Map<String, T> getHashWithoutLog(String hashKey) {
return hashRedis.allEntrysWithoutLog(hashKey);
}
public static <T> T getHash(String hashKey, String field) {
return hashRedis.get(hashKey, field);
}
public static <T> List<T> getHash(String hashKey, String... field) {
return hashRedis.get(hashKey, field);
}
public static <T> T getHashWithoutLog(String hashKey, String field) {
return hashRedis.get(hashKey, field);
}
public static void remHash(String hashKey, String... field) {
hashRedis.delKey(hashKey, field);
}
public static <T> void addList(String k, List<T> v, long exSeconds) {
listRedis.pushRight(k, v);
expire(k, exSeconds);
}
public static <T> List<T> getList(String k) {
return listRedis.getAll(k);
}
public static void expire(String key, long exSecond) {
if (exSecond > 0)
keyRedis.expire(key, exSecond);
}
public static boolean isExist(String key) {
return keyRedis.exist(key);
}
public static long delKeys(String... keys) {
return keyRedis.del(keys);
}
public static long getTtl(String key) {
return keyRedis.ttl(key);
}
public static void delPattern(String pattern) {
keyRedis.del(keyRedis.keys(pattern + "*").toArray(new String[]{}));
}
public static Long executeUnLockLuaScripts(ScriptOutputType type, String[] keys, String[] args) {
return scriptRedis.evalSha(type, keys, args);
}
public static RedissonClient getRedissonClient() {
return redissonClient;
}
public static long publish(String topic, Object param) {
return redissonClient.getTopic(topic, StringCodec.INSTANCE).publish(param);
}
public static void addListener(String topicId, MessageListener<String> listener) {
RTopic topic = RedisUtils.getRedissonClient().getTopic(topicId, StringCodec.INSTANCE);
topic.addListener(String.class, listener);
}
private static Long toLong(String value) {
return NumberUtil.isLong(value) ? Long.parseLong(value) : 0;
}
public RedisUtils(RedisList listRedis, RedisSet setRedis, RedisStr strRedis, RedisHash hashRedis, RedisKey keyRedis, RedisScript scriptRedis) {
RedisUtils.setRedis = setRedis;
RedisUtils.strRedis = strRedis;
RedisUtils.keyRedis = keyRedis;
RedisUtils.hashRedis = hashRedis;
RedisUtils.listRedis = listRedis;
RedisUtils.scriptRedis = scriptRedis;
}
public void initClient(RedisClient client, RedissonClient redissonClient) {
StatefulRedisConnection<String, String> connection = client.connect();
StatefulRedisConnection<String, Object> objConnection = client.connect(new ObjectRedisCodec());
RedisStr.commands = connection.sync();
RedisKey.commands = connection.sync();
RedisSet.commands = objConnection.sync();
RedisList.commands = objConnection.sync();
RedisHash.commands = objConnection.sync();
RedisStr.asyncCommands = connection.async();
RedisUtils.redissonClient = redissonClient;
RedisScript.init(connection.sync());
}
}
package com.ph.sp.integration.util.redis;
import io.lettuce.core.api.sync.RedisSetCommands;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import java.util.Set;
@Component
@SuppressWarnings({"all"})
class RedisSet {
static RedisSetCommands<String, Object> commands;
<T> Set<T> getAll(String key) {
return (Set<T>) commands.smembers(key);
}
Boolean exist(String key, Object item) {
return commands.sismember(key, item);
}
Long set(String key, Object... values) {
return commands.sadd(key, values);
}
Long del(String key, Object... values) {
return commands.srem(key, values);
}
Long count(String key) {
return commands.scard(key);
}
<T> Set<T> difference(String... keys) {
return (Set<T>) commands.sdiff(keys);
}
<T> Set<T> intersection(String... keys) {
return (Set<T>) commands.sinter(keys);
}
<T> Set<T> union(String... keys) {
return (Set<T>) commands.sunion(keys);
}
}
package com.ph.sp.integration.util.redis;
import io.lettuce.core.api.sync.RedisHashCommands;
import org.springframework.stereotype.Component;
import java.util.List;
import java.util.Map;
@Component
@SuppressWarnings({"all"})
class RedisHash {
static RedisHashCommands<String, Object> commands;
String set(String hashKey, Map<String, Object> map) {
return commands.hmset(hashKey, map);
}
Boolean set(String hashKey, String field, Object value) {
return commands.hset(hashKey, field, value);
}
<T> T get(String hashKey, String field) {
return (T) commands.hget(hashKey, field);
}
<T> T getWithoutLog(String hashKey, String field) {
return (T) commands.hget(hashKey, field);
}
<T> List<T> get(String hashKey, String... fields) {
return (List<T>) commands.hmget(hashKey, fields);
}
Long getLen(String hashKey) {
return commands.hlen(hashKey);
}
Boolean exist(String hashKey, String field) {
return commands.hexists(hashKey, field);
}
List<String> allKeys(String hashKey) {
return commands.hkeys(hashKey);
}
<T> List<T> allValues(String hashKey) {
return (List<T>) commands.hvals(hashKey);
}
<T> Map<String, T> allEntrys(String hashKey) {
return (Map<String, T>) commands.hgetall(hashKey);
}
<T> Map<String, T> allEntrysWithoutLog(String hashKey) {
return (Map<String, T>) commands.hgetall(hashKey);
}
Long delKey(String hashKey, String... fields) {
return commands.hdel(hashKey, fields);
}
}
package com.ph.sp.integration.util.redis;
import io.lettuce.core.api.sync.RedisKeyCommands;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import java.util.List;
@Component
class RedisKey {
static RedisKeyCommands<String, String> commands;
boolean exist(String key) {
return commands.exists(key) == 1;
}
Long del(String... key) {
return commands.del(key);
}
List<String> keys(String pattern) {
return commands.keys(pattern);
}
Boolean expire(String key, long seconds) {
return commands.expire(key, seconds);
}
Long ttl(String key){
return commands.ttl(key);
}
}
package com.ph.sp.integration.util.redis;
import io.lettuce.core.api.sync.RedisListCommands;
import org.springframework.stereotype.Component;
import java.util.List;
@Component
@SuppressWarnings({"all"})
class RedisList {
static RedisListCommands<String, Object> commands;
<T> List<T> getAll(String key) {
return (List<T>) commands.lrange(key, start_left, start_right);
}
<T> List<T> getAll(String key, long start, long end) {
return (List<T>) commands.lrange(key, start, end);
}
Long pushLeft(String key, Object... values) {
return commands.lpush(key, values);
}
Long pushRight(String key, Object... v) {
return commands.rpush(key, v);
}
<T> T popLeft(String key) {
return (T) commands.lpop(key);
}
<T> T popRight(String key) {
return (T) commands.rpop(key);
}
String set(String key, long index, Object value) {
return commands.lset(key, index, value);
}
<T> T get(String key, long offset) {
return (T) commands.lindex(key, offset);
}
Long del(String key, Object value) {
return commands.lrem(key, remove_all, value);
}
Long del(String key, long count, Object value) {
return commands.lrem(key, count, value);
}
String trim(String key, long start, long end) {
return commands.ltrim(key, start, end);
}
private static final long remove_all = 0L;
private static final long start_left = 0L;
private static final long start_right = -1L;
}
package com.ph.sp.integration.util.redis;
import io.lettuce.core.ScriptOutputType;
import io.lettuce.core.api.sync.RedisCommands;
import io.lettuce.core.api.sync.RedisScriptingCommands;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import java.util.concurrent.atomic.AtomicReference;
@Component
class RedisScript {
static RedisScriptingCommands<String, String> commands;
Long evalSha(ScriptOutputType type, String[] keys, String[] args) {
return commands.evalsha(LUA_SHA_UNLOCK.get(), type, keys, args);
}
static void init(RedisCommands<String, String> command){
commands = command;
LUA_SHA_UNLOCK.compareAndSet(null, commands.scriptLoad(UNLOCK_LUA_STATEMENT));
}
private static final AtomicReference<String> LUA_SHA_UNLOCK = new AtomicReference<>();
private static final String UNLOCK_LUA_STATEMENT = "local result = redis.call('get', KEYS[1]);" +
"if result == ARGV[1] then redis.call('del', KEYS[1]) " +
"return 1 else return nil end";
}
package com.ph.sp.integration.util.redis;
import io.lettuce.core.SetArgs;
import io.lettuce.core.api.async.RedisStringAsyncCommands;
import io.lettuce.core.api.sync.RedisStringCommands;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
@Component
@SuppressWarnings({"all"})
class RedisStr {
static RedisStringCommands<String, String> commands;
static RedisStringAsyncCommands<String, String> asyncCommands;
String set(String key, String value, long timeout) {
SetArgs args = SetArgs.Builder.nx().ex(timeout);
return commands.set(key, value, args);
}
String getset(String key, String value) {
return commands.getset(key, value);
}
void setAsync(String key, String value, long timeout) {
SetArgs args = SetArgs.Builder.nx().ex(timeout);
asyncCommands.set(key, value, args);
}
String get(String key){
return commands.get(key);
}
Boolean setNx(String key, String value){
return commands.setnx(key, value);
}
Long incr(String key){
return commands.incr(key);
}
Long decr(String key){
return commands.decr(key);
}
}