在Spring-boot集成Redis基础上,集成spring-cache
Spring-boot集成Redis
1、RedisConfig 类添加注解 @EnableCaching
2、keyGenerator
/**
* 自定义缓存的key
* @return
*/
@Bean
@Override
public KeyGenerator keyGenerator() {
return new KeyGenerator(){
@Override
public Object generate(Object target, Method method, Object... params){
StringBuilder sb = new StringBuilder();
sb.append(target.getClass().getName()).append(".");
sb.append(method.getName()).append(".");
for (Object obj : params) {
sb.append(obj.toString());
}
System.out.println("keyGenerator="+sb.toString());
return sb.toString();
}
};
}
3、cacheManager
/**
* 创建RedisCacheManager
* @param connectionFactory
* @return
*/
@Bean
public CacheManager cacheManager(RedisConnectionFactory connectionFactory){
//初始化一个RedisCacheWriter
RedisCacheWriter redisCacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter(connectionFactory);
//设置CacheManager的值序列化方式
//RedisCacheConfiguration defaultCacheConfig=RedisCacheConfiguration.defaultCacheConfig().serializeValuesWith(pair);
RedisCacheConfiguration defaultCacheConfig = RedisCacheConfiguration.defaultCacheConfig();
//设置默认超过期时间是30秒
defaultCacheConfig.entryTtl(Duration.ofSeconds(30));
//初始化RedisCacheManager
RedisCacheManager redisCacheManager = new RedisCacheManager(redisCacheWriter, defaultCacheConfig);
return redisCacheManager;
}
4、方法中添加注解
/**
* 保存缓存
* @param id
* @return
*/
@Cacheable(value = "log", key = "'log'.concat(#id.toString())")
public Log findLogById(Long id) {
String sql = "select id,content,createtime from log_info where id = ?";
RowMapper<Log> rowMapper = new BeanPropertyRowMapper<>(Log.class);
Log log = jdbcTemplate.queryForObject(sql,rowMapper,id);
System.out.println("log="+log);
return log;
}
/**
* 重新保存缓存
* @param log
* @return
*/
@CachePut(value = "log", key = "'log'.concat(#log.id.toString())")
public Log update(Log log) {
Integer id = log.getId();
String content = "测试缓存"+id;
log.setContent(content);
jdbcTemplate.update("UPDATE log_info SET content = ? WHERE id = ?", new Object[] {content, id});
System.out.println("log="+log);
return log;
}
/**
* 删除缓存
* @param id
*/
@CacheEvict(value = "log", key = "'log'.concat(#id.toString())")
public void remove(Long id) {
String sql = "delete from log_info where id=?";
int update = jdbcTemplate.update(sql, id);
System.out.println(update);
}
5、注解描述
@Cacheable 触发缓存入口
一般用于查询操作,根据key查询缓存.
1. 如果key不存在,查询db,并将结果更新到缓存中。
2. 如果key存在,直接查询缓存中的数据。
@CacheEvict 触发移出缓存
根据key删除缓存中的数据。allEntries=true表示删除缓存中的所有数据。
@CachePut 触发更新缓存
一般用于更新和插入操作,每次都会请求db
1. 如果key存在,更新内容
2. 如果key不存在,插入内容。
@Caching 将多种缓存操作分组
这个注解将其他注解方式融合在一起了,我们可以根据需求来自定义注解,并将前面三个注解应用在一起
@CacheConfig 类级别的缓存注解,允许共享缓存名称
该注解是可以将缓存分类,它是类级别的注解方式。
6、自定义AOP缓存
自定义注解
/**
* 元注解 用来标识查询数据库的方法
*/
@Documented
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface RedisCache {
}
自定义Aspect
/**
* AOP实现Redis缓存处理
*/
@Component
@Aspect
public class RedisAspect {
@Autowired
private RedisService redisService;
/**
* 拦截所有元注解RedisCache注解的方法
*/
@Pointcut("@annotation(com.seata.business.annotation.RedisCache)")
public void pointcutMethod(){
}
/**
* 环绕处理,先从Redis里获取缓存,查询不到,就查询MySQL数据库,
* 然后再保存到Redis缓存里
* @param joinPoint
* @return
*/
@Around("pointcutMethod()")
public Object around(ProceedingJoinPoint joinPoint){
//前置:从Redis里获取缓存
//先获取目标方法参数
long startTime = System.currentTimeMillis();
String applId = null;
Object[] args = joinPoint.getArgs();
if (args != null && args.length > 0) {
applId = String.valueOf(args[0]);
}
//获取目标方法所在类
String target = joinPoint.getTarget().toString();
String className = target.split("@")[0];
//获取目标方法的方法名称
String methodName = joinPoint.getSignature().getName();
//redis中key格式: applId:方法名称
String redisKey = applId + ":" + className + "." + methodName;
Object obj = redisService.getCacheObject(redisKey);
if(obj!=null){
System.out.println("**********从Redis中查到了数据**********");
System.out.println("Redis的KEY值:"+redisKey);
System.out.println("Redis的VALUE值:"+obj.toString());
return obj;
}
long endTime = System.currentTimeMillis();
System.out.println("Redis缓存AOP处理所用时间:"+(endTime-startTime));
System.out.println("**********没有从Redis查到数据**********");
try{
obj = joinPoint.proceed();
}catch(Throwable e){
e.printStackTrace();
}
System.out.println("**********开始从MySQL查询数据**********");
//后置:将数据库查到的数据保存到Redis
redisService.setCacheObject(redisKey,obj);
if(redisService.hasKey(redisKey)){
System.out.println("**********数据成功保存到Redis缓存!!!**********");
System.out.println("Redis的KEY值:"+redisKey);
System.out.println("Redis的VALUE值:"+obj.toString());
}
return obj;
}
/**
* 增删改操作会先将对应的缓存从redis中删除
* 再重新查询数据库并重新存入redis缓存
* @param joinPoint
*/
@After("execution(* com.seata.business.service.*.*(..)) && !execution(* com.seata.business.service.*.select*(..))&& !execution(* com.seata.business.service.*.find*(..))")
public void after(JoinPoint joinPoint){
String name = joinPoint.getTarget().getClass().getName();
redisService.deleteObject(name);
}
}