Commit 592d0294 by yuwei

项目初始化

parent 23336f6e
package cn.datax.common.redis.annotation;
import java.lang.annotation.*;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RedisCacheAop {
// 缓存名
String cacheName() default "";
// 过期时间(秒) time要大于0 如果time小于等于0 将设置无限期
long expire() default -1;
// 缓存反序列化获取的对象
Class clazz() default Object.class;
// 序列化后的对象是否是数组 比如 List<Object>
boolean isArray() default false;
}
package cn.datax.common.redis.aspectj;
import cn.datax.common.redis.annotation.RedisCacheAop;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
@Aspect
@Slf4j
public class RedisCacheAspect {
@Autowired
private RedisTemplate redisTemplate;
@Autowired
private ObjectMapper objectMapper;
/**
* 分隔符 生成key 格式为 类全类名|方法名|参数所属类全类名
**/
private static final String DELIMITER = ":";
/**
* Service层切点 使用到了我们定义的 RedisCacheAspect 作为切点表达式。
* 而且我们可以看出此表达式基于 annotation。
* 并且用于内建属性为查询的方法之上
*/
@Pointcut("@annotation(cn.datax.common.redis.annotation.RedisCacheAop)")
public void redisCacheAspect() {
}
/**
* Around 手动控制调用核心业务逻辑,以及调用前和调用后的处理,
* <p>
* 注意:当核心业务抛异常后,立即退出,转向AfterAdvice 执行完AfterAdvice,再转到ThrowingAdvice
*/
@Around(value = "redisCacheAspect()")
public Object aroundAdvice(ProceedingJoinPoint joinPoint) throws Throwable {
// 得到类名、方法名和参数
String clazzName = joinPoint.getTarget().getClass().getName();
String methodName = joinPoint.getSignature().getName();
Object[] args = joinPoint.getArgs();
// 根据类名、方法名和参数生成Key
log.info("key参数: " + clazzName + "." + methodName);
String key = getKey(clazzName, methodName, args);
if (log.isInfoEnabled()) {
log.info("生成key: " + key);
}
// 得到被代理的方法
Method method = ((MethodSignature) joinPoint.getSignature()).getMethod();
String cacheName = method.getAnnotation(RedisCacheAop.class).cacheName();
long expire = method.getAnnotation(RedisCacheAop.class).expire();
Class objectType = method.getAnnotation(RedisCacheAop.class).clazz();
boolean isArray = method.getAnnotation(RedisCacheAop.class).isArray();
// 检查Redis中是否有缓存
String value = (String) redisTemplate.opsForValue().get(key + DELIMITER + cacheName);
// result是方法的最终返回结果
Object result = null;
try {
if (null == value) {
log.info("缓存未命中");
// 调用数据库查询方法
result = joinPoint.proceed(args);
// 结果放入缓存
if (expire > 0) {
redisTemplate.opsForValue().set(key + DELIMITER + cacheName, objectMapper.writeValueAsString(result), expire, TimeUnit.SECONDS);
} else {
redisTemplate.opsForValue().set(key + DELIMITER + cacheName, objectMapper.writeValueAsString(result));
}
} else {
/**
* 可以直接针对mapper进行缓存,如果mapper查询返回的List<Objec> 需要isArray 为true 否则转换异常
*/
if (isArray){
// return JSON.parseArray(value, objectType);
}else {
// return JSON.parseObject(value,objectType);
}
}
} catch (Throwable e) {
log.error("程序异常", e.getMessage());
throw e;
}
return result;
}
/**
* 根据类名、方法名和参数生成Key
* @param clazzName
* @param methodName
* @param args
* @return key格式:全类名:方法名:参数类型
*/
private String getKey(String clazzName, String methodName, Object[] args) {
StringBuilder key = new StringBuilder(clazzName);
key.append(DELIMITER);
key.append(methodName);
key.append(DELIMITER);
key.append(Arrays.stream(args).map(x -> x.toString()).collect(Collectors.joining(DELIMITER)));
return key.toString();
}
}
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
cn.datax.common.redis.config.RedisConfig,\ cn.datax.common.redis.config.RedisConfig,\
cn.datax.common.redis.config.RedissonConfig,\ cn.datax.common.redis.config.RedissonConfig
cn.datax.common.redis.aspectj.RedisCacheAspect
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment