ehcache模糊批量移除缓存的方法

网友投稿 573 2023-02-19


ehcache模糊批量移除缓存的方法

前言

众所周知,encache是现在最流行的java开源缓存框架,配置简单,结构清晰,功能强大。通过注解 @Cacheable 可以快速添加方法结果到缓存。通过 @CacheEvict 可以快速清除掉指定的缓存。

但由于 @CacheEvict 注解使用的是key-value的,不支持模糊删除,就会遇到问题。当我用 @Cacheable 配合Spring EL表达式添加了同一方法的多个缓存比如:

@GetMapping("/listOfTask/{page}/")

@Cacheable(value = "BusinessCache", key = "'listOfTask_'+ #page")

public ResponseMessage getTaskList(@PathVariable("page") String page) {

do something...

}

上述代码是分页获取任务信息。用EL表达式获取到参数中的page,并作为缓存的key,使用 @Cacheable 添加到ehcache的缓存中。此时,在缓存中就会出现 listOfTask_1 , listOfTask_2 , listOfTask_3 这种类型的key。

当添加、删除任务时,列表就会发生改变。这时候,就需要把 listOfTask_* 相关的缓存全部去掉。而这时,我不知道缓存中到底缓存了多少和 listOfTask_* 相关的内容,不可能调用 @CacheEvict 挨个删除。

既然ehcache本身无法支持,那就只能靠我们自己实现了。

实现

考虑到使用的注解添加的缓存,那么移除缓存也使用注解处理,可以保持开发的一致性。注解对开发者来说也很友好。那么我们就考虑使用自定义注解来来模糊批量移除缓存。

首先,定义注解 CacheRemove :

@Target({ java.lang.annotation.ElementType.METHOD })

@Retention(RetentionPolicy.RUNTIME)

public @interface CacheRemove {

String value();

String[] key();

}

其中,value 同 ehcache 一样,用于定义要操作的缓存名。key 是一个数组,用于存放多种缓存 key 的正则表达式。起名 CacheRemove 清晰易懂,也不与 ehcache 本身的注解冲突。注解的定义到此为止。接下来,就需要处理注解了,由于使用的 spring 框架,很自然的,就会想到用 AOP 来做注解的具体实现。

注解的目的是批量模糊移除缓存。需考虑如下两个问题:

用什么方式模糊匹配

怎么批量删除key

我给出的处理方式,也是我认为最简单的处理方式是:

用什么方式模糊匹配 —— CacheRemove 中的key传正则,可以传多个,使用正则匹配

怎http://么批量删除key —— 循环所有的key,找到匹配正则的就删除

首先定义类名 CacheRemoveAspect :

@Aspect

@Component

public class CacheRemoveAspect {

@Pointcut(value = "(execution(* *.*(..)) && @annotation(com.example.CacheRemove))")

private void pointcut() {}

do something...

}

在切面中定义切点,使用 execution(* *.*(..) && @annotation(com.example.CacheRemove)) 表示所有带注解类 CacheRemove 都执行, @annotation 中的值是注解的全限定名。

切点定义完毕,下面的重头戏就是切面的具体实现了。一般来说,缓存会在增删改的方法执行完后才要移除。所以使用 @AfterReturning() 来实现。在具体实现中需要做以下几件事:

拦截方法上的注解

判断注解是不是 CacheRemove

由于注解传入的 key 是个数组,循环处理每个key

在循环中编制每个 key 为 pattern, 并循环所有的缓存,移除匹配上的缓存

具体实现http://如下:

@AfterReturning(value = "pointcut()")

private void process(JoinPoint joinPoint){

MethodSignature signature = (MethodSignature) joinPoint.getSignature();

Method method = signature.getMethod();

CacheRemove cacheRemove = method.getAnnotation(CacheRemove.class);

if (cacheRemove != null){

String value = cacheRemove.value();

String[] keys = cacheRemove.key(); //需要移除的正则key

List cacheKeys = CacheUtils.cacheKeys(value);

for (String key : keys){

Pattern pattern = Pattern.compile(key);

for (Object cacheKey: cacheKeys) {

String cacheKeyStr = String.valueOf(cacheKey);

if (pattern.matcher(cacheKeyStr).find()){

CacheUtils.remove(value, cacheKeyStr);

}

}

}

}

}

以上,为 ehcachehttp:// 模糊批量移除缓存的具体实现。其中 BusinessCacheUtils 为自己封装的 ehcache 工具类。主要实现获取缓存池,获取缓存,移除缓存,添加缓存,查看所有缓存等正常功能。代码如下:

public class CacheUtils {

private static CacheManager cacheManager = SpringContextHolder.getBean("ehCacheManagerFactory");

public static Object get(String cacheName, String key) {

Element element = getCache(cacheName).get(key);

return element == null ? null : element.getObjectValue();

}

public static void put(String cacheName, String key, Object value) {

Element element = new Element(key, value);

getCache(cacheName).put(element);

}

public static void remove(String cacheName, String key) {

getCache(cacheName).remove(key);

}

public static List cacheKeys(String cacheName){

return getCache(cacheName).getKeys();

}

/**

* 获得一个Cache,没有则创建一个。

* @param cacheName

* @return

*/

private static Cache getCache(String cacheName) {

Cache cache = cacheManager.getCache(cacheName);

if (cache == null) {

cacheManager.addCache(cacheName);

cache = cacheManager.getCache(cacheName);

cache.getCacheConfiguration().setEternal(true);

}

return cache;

}

public static CacheManager getCacheMhttp://anager() {

return cacheManager;

}

}

至此,整个ehcache 模糊批量移除缓存的功能就实现了。

总结


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:java实现字符串排列组合问题
下一篇:虫师 接口测试(虫师自动化测试)
相关文章

 发表评论

暂时没有评论,来抢沙发吧~