@CacheEvict只能單一清除的擴充套件 -模糊-正則清除多條快取 解決
阿新 • • 發佈:2018-12-09
[email protected](value="xx",key="xxx")只能單一刪除,但是
@Cacheable(value = "autocms", key = "#root.targetClass+'.'+#root.method.name+'.'+#p0+'.'+#p1")
public <T> PageInfo<T> getActivityByShowStatus(Map<String, Integer> paramMap, Class<T> 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<String, String> 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<String> stringSet = redis.keys(key); redis.delete(stringSet);//刪除快取 logger.info("清除 " + key + " 快取"); } } }