1,自定义一个注解,参数key是存到redis的key,时间就是缓存多久,默认是0,可以根据自己的业务去顶一个默认值
package com.clpc.un.pafp.statistics.config;
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 CacheFind {
public String key();
public int seconds()default 0;//超时时间
}
定义redis配置IP地址,端口等,注入到bean里面
package com.clpc.un.pafp.statistics.config;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import redis.clients.jedis.Jedis;
@Configuration
@PropertySource("classpath:/properties/redis.properties")
public class RedisConfig {
@Value("${redis.host}")
private String host;
@Value("${redis.port}")
private Integer port;
@Bean
public Jedis jedis(){
return new Jedis(host,port);
}
}
2,定义aop切入注解,redis存储过则拿redis的数据,否则就去数据库拿,并且缓存到redis
package com.clpc.un.pafp.statistics.aop;
import com.clpc.un.pafp.statistics.config.CacheFind;
import com.clpc.un.pafp.statistics.config.ObjectMapperUtil;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import redis.clients.jedis.Jedis;
import java.util.Arrays;
/**
* 此类作为缓存的AOP切面类
*/
@Aspect //标记为切面
@Component //交给spring管理
public class CacheAop {
@Value("${Redis.Flag}")
private Boolean redisFlag;
@Autowired
private Jedis jedis;
/**
* 实现思路:
* 1.动态获取key 用户自定义的前缀+用户的参数[0,xx]
* 2.判断key是否存在
* 存在: 直接从redis中获取数据 JSON, 需要将json转化为具体对象 按照返回值类型进行转化
* 不存在: 执行目标方法.获得返回值数据. 将返回值结果转化为JSON格式. 之后保存到缓存中.
* @param joinPoint
* @return
*/
@Around("@annotation(cacheFind)")
public Object around(ProceedingJoinPoint joinPoint, CacheFind cacheFind){
Object result = null;
//1,获取key的前缀
String key = cacheFind.key();
//2,获取方法参数
String argString = Arrays.toString(joinPoint.getArgs());
key = key+"::"+argString;
if (redisFlag){
try {
//3.判断缓存中是否有数据
if(jedis.exists(key)){
String json = jedis.get(key);
//5.获取返回值类型
MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
result = ObjectMapperUtil.toObject(json,methodSignature.getReturnType());
System.out.println("AOP查询redis缓存");
}else{
//表示缓存中没有数据,执行目标方法
result = joinPoint.proceed();
String json = ObjectMapperUtil.toJSON(result);
//4.判断数据中是否有超时时间
if(cacheFind.seconds()>0){
jedis.setex(key,cacheFind.seconds(),json);
}else{
jedis.set(key,json);
}
System.out.println("AOP执行数据库调用!!!!!");
}
} catch (Throwable throwable) {
throwable.printStackTrace();
throw new RuntimeException(throwable);
}
}else{
//表示缓存中没有数据,执行目标方法
try {
result = joinPoint.proceed();
System.out.println("未启用redis缓存,查询数据库");
} catch (Throwable throwable) {
throwable.printStackTrace();
throw new RuntimeException("AOP方法调用失败");
}
}
return result;
}
}
ObjectMapperUtil工具类
package com.clpc.un.pafp.statistics.config;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.context.annotation.Configuration;
@Configuration
public class ObjectMapperUtil {
private static final ObjectMapper MAPPER = new ObjectMapper();
public static String toJSON(Object target){
try {
return MAPPER.writeValueAsString(target);
} catch (JsonProcessingException e) {
e.printStackTrace();
//将检查异常转化为运行时异常.
throw new RuntimeException(e);
}
}
public static <T> T toObject(String json,Class<T> targetClass){
try {
return MAPPER.readValue(json, targetClass);
} catch (JsonProcessingException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
}
使用