配置类
package com.qiankuniot.uwb.config;
import com.qiankuniot.uwb.cache.AspectRedisCache;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
/**
* 切面加入redis缓存
* @author Xiaoxiangdong
* @date 2021/6/10 9:54
*/
@Configuration
@EnableAspectJAutoProxy
public class AspectJConfig {
@Bean
public AspectRedisCache aspectRedisCache() {
return new AspectRedisCache();
}
}
切面类
package com.qiankuniot.uwb.cache;
import com.alibaba.fastjson.JSONObject;
import com.qiankuniot.common.result.ResultVO;
import com.qiankuniot.uwb.cache.annotation.RedisStringCache;
import com.qiankuniot.uwb.dto.UserPermissionDTO;
import com.qiankuniot.uwb.utils.RedisUtil;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
@Aspect
public class AspectRedisCache {
private static final Logger logger = LoggerFactory.getLogger(AspectRedisCache.class);
@Autowired
private StringRedisTemplate stringRedisTemplate;
@Autowired
private RedisUtil redisUtil;
//支持注解形式
@Pointcut("@annotation(com.qiankuniot.uwb.cache.annotation.RedisStringCache)")
public void pointCut() {
}
;
//@before代表在目标方法执行前切入, 并指定在哪个方法前切入
@Before("pointCut()")
public void start() {
logger.debug("开始....参数列表是:{}");
}
@After("pointCut()")
public void end() {
logger.debug("结束......");
}
@AfterReturning("pointCut()")
public void returnResult() {
logger.debug("正常返回......运行结果是:{}");
}
@AfterThrowing("pointCut()")
public void exception() {
logger.debug("运行异常......异常信息是:{}");
}
//@Arount:执行目标方法之前...
//Object obj = joinPoint.proceed();//相当于开始调div地
//@Arount:执行目标方法之后...
@Around("pointCut()")
public Object Around(ProceedingJoinPoint joinPoint) throws Throwable {
MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
Method method = methodSignature.getMethod();
Object[] args = joinPoint.getArgs();
if (method.isAnnotationPresent(RedisStringCache.class)) {
RedisStringCache redisStringCache = method.getAnnotation(RedisStringCache.class);
//判断是否开启
if (redisStringCache.isOpen()) {
String key = "cache:" + redisStringCache.key();
int time = redisStringCache.time();
TimeUnit timeUnit = redisStringCache.timeUnit();
String cacheVariableValue = redisStringCache.cacheVariable();
Class clz = redisStringCache.paramClass();
if (StringUtils.isNotBlank(cacheVariableValue)) {
cacheVariableValue = findMethodParamValueByName(args, method, cacheVariableValue, clz);
}
if (StringUtils.isNotBlank(cacheVariableValue)) {
key = key +":"+ cacheVariableValue;
}
//如果缓存不存在,重新查询数据库进行缓存
if (!stringRedisTemplate.hasKey(key)) {
//锁住5秒
if (redisUtil.setLock("lock:" + key, 5000)) {
//查询数据库
Object result = joinPoint.proceed();
JSONObject jsonObject = JSONObject.parseObject(JSONObject.toJSONString(result));
String data = jsonObject.getString("data");
if(StringUtils.isBlank(data) || data.equals("[]")){
stringRedisTemplate.opsForValue().set(key,jsonObject.toJSONString(),30,TimeUnit.SECONDS);
return jsonObject.toJSONString();
}
//缓存数据
stringRedisTemplate.opsForValue().set(key, jsonObject.toJSONString(), time, timeUnit);
return result;
}
} else {
//缓存存在,取缓存进行返回
String result = stringRedisTemplate.opsForValue().get(key);
ResultVO resultvo = JSONObject.parseObject(result).toJavaObject(ResultVO.class);
return resultvo;
}
}
}
Object obj = joinPoint.proceed();//相当于开始调div地
return obj;
}
//查找获取方法指定参数名的值
private String findMethodParamValueByName(Object[] args, Method method, String paramName, Class clz) {
if (StringUtils.isBlank(paramName)) {
return "";
}
List<Integer> indexs = new ArrayList<>();
Class<?>[] paramvalues = method.getParameterTypes();
Field field = null;
for (int i = 0; i < paramvalues.length; i++) {
if (paramvalues[i].equals(clz)) {
indexs.add(i);
Field[] fields = paramvalues[i].getDeclaredFields();
for (int j = 0; j < fields.length; j++) {
if (fields[j].getName().equals(paramName)) {
indexs.add(j);
field = fields[j];
}
}
}
}
if (indexs.size() == 1) {
return args[indexs.get(0)] + "";
}
if (indexs.size() == 2) {
Object objects = args[indexs.get(0).intValue()];
field.setAccessible(true);
try {
return field.get(objects) + "";
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
return "";
}
}
注解类定义
package com.qiankuniot.uwb.cache.annotation;
import org.junit.runner.RunWith;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.concurrent.TimeUnit;
/**
* @author Xiaoxiangdong
* @date 2021/6/10 10:02
*/
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface RedisStringCache {
//是否开启缓存,默认开启
boolean isOpen() default true;
//缓存key
String key();
//缓存的时间,单位默认毫秒
int time();
//缓存的时间单位,默认毫秒
TimeUnit timeUnit() default TimeUnit.MILLISECONDS;
//缓存的参数变量
String cacheVariable() default "";
//参数类型
Class paramClass() default String.class;
}