@CacheEvict只能单一清除的扩展 -模糊-正则清除多条缓存 解决

1.@CacheEvic(value="xx",key="xxx")只能单一删除,但是

    @Cacheable(value = "autocms", key = "#root.targetClass+'.'+#root.method.name+'.'+#p0+'.'+#p1")
    public  PageInfo getActivityByShowStatus(Map paramMap, Class cl) {

会根据不同的参数生成多条缓存数据,之久导致的当出现数据更新的时候更新缓存的困难

解决:

首先找到这一类的缓存的共同点,同一类缓存有着相同的前缀,而java redis客户端支持正则查询和批量的删除

1.问题一:在需要刷新的缓存的时候如何拿到这个前缀,这个问题的取决于你的前缀或者后缀是如何生成的

2.问题二:就是你如何的根据前缀或者后缀去清除redis缓存

实现方式

1.你可以写个工具类,

2写一个服务类注入到Spring中使用的时候直接拿出来

3.你可以使用Sring的Aop代理增强的方式进行处理

我是先使用的第二种,后来改成了第三种

下面直接上代码,代码里面都有注释

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * 功能描述:需要清除的当前类型--当前类
 *
 * @author fuyuchao
 * DATE 2018/9/14.
 */
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface CacheRemove {

    /**
     * 需要清除的大类 例如 autocms 所有缓存
     *
     * @return
     */
    String value() default "";


    /**
     * 需要清除的具体的额类型
     *
     * @return
     */
    String[] key() default {};
}
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.lang.reflect.Method;
import java.util.Set;

/**
 * 功能描述:清除缓存切面类
 *
 * @author fuyuchao
 * DATE 2018/9/14.
 */
@Component
@Aspect
public class CacheRemoveAspect {

    Logger logger = LoggerFactory.getLogger(this.getClass());

    @Resource(name = "redisTemplate")
    RedisTemplate redis;

    //截获标有@CacheRemove的方法
    @Pointcut(value = "(execution(* *.*(..)) && @annotation(com.yooli.cms.cache.CacheRemove))")
    private void pointcut() {
    }

    /**
     * 功能描述: 切面在截获方法返回值之后
     *
     * @return void
     * @throws
     * @author fuyuchao
     * @date 2018/9/14 16:55
     * @params [joinPoint]
     */
    @AfterReturning(value = "pointcut()")
    private void process(JoinPoint joinPoint) {
        //获取被代理的类
        Object target = joinPoint.getTarget();
        //获取切入方法的数据
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        //获取切入方法
        Method method = signature.getMethod();
        //获得注解
        CacheRemove cacheRemove = method.getAnnotation(CacheRemove.class);

        if (cacheRemove != null) {
            //清除当前类的缓存
            cleanRedisCache("*" + target.getClass().toString() + "*");

            String value = cacheRemove.value();
            if (!value.equals("")) {
                //缓存的项目所有redis业务部缓存
                cleanRedisCache("*" + value + "*");
            }
            //需要移除的正则key
            String[] keys = cacheRemove.key();
            for (String key : keys) {
                //指定清除的key的缓存
                cleanRedisCache("*" + key + "*");
            }
        }
    }

    private void cleanRedisCache(String key) {
        if (key != null) {
            Set stringSet = redis.keys(key);
            redis.delete(stringSet);//删除缓存
            logger.info("清除 " + key + " 缓存");
        }
    }
}

参考:https://www.cnblogs.com/zer0Black/p/8410984.html

你可能感兴趣的:(spring,redis,cache)