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

前言

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

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

@GetMapping("/listOfTask/{page}/")
@Cacheable(value = "BusinessCache", key = "'listOfTask_'+ #page")
public ResponseMessage<PageTaskVO> 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 来做注解的具体实现。

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

  1. 用什么方式模糊匹配
  2. 怎么批量删除key

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

  1. 用什么方式模糊匹配 —— CacheRemove 中的key传正则,可以传多个,使用正则匹配
  2. 怎么批量删除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() 来实现。在具体实现中需要做以下几件事:

  1. 拦截方法上的注解
  2. 判断注解是不是 CacheRemove
  3. 由于注解传入的 key 是个数组,循环处理每个key
  4. 在循环中编制每个 key 为 pattern, 并循环所有的缓存,移除匹配上的缓存

具体实现如下:

@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);
        }
      }
    }
  }
}

以上,为 ehcache 模糊批量移除缓存的具体实现。其中 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 getCacheManager() {
    return cacheManager;
  }

}

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

总结

整个过程思路简单,用到了一些 AOP 的知识就完成了需要的功能。但具体的移除部分代码可考虑进行优化。通过一次缓存的全部循环,就把需要移除的缓存都移除干净,而不是想现在这样有几个key,就全缓存遍历几次。具体实现留给读者自行完成。希望对各位有所帮助。也希望大家多多支持我们。

(0)

相关推荐

  • 详解Spring整合Ehcache管理缓存

    前言 Ehcache 是一个成熟的缓存框架,你可以直接使用它来管理你的缓存. Spring 提供了对缓存功能的抽象:即允许绑定不同的缓存解决方案(如Ehcache),但本身不直接提供缓存功能的实现.它支持注解方式使用缓存,非常方便. 本文先通过Ehcache独立应用的范例来介绍它的基本使用方法,然后再介绍与Spring整合的方法. 概述 Ehcache是什么? EhCache 是一个纯Java的进程内缓存框架,具有快速.精干等特点.它是Hibernate中的默认缓存框架. Ehcache已经发布

  • 详解spring boot集成ehcache 2.x 用于hibernate二级缓存

    本文将介绍如何在spring boot中集成ehcache作为hibernate的二级缓存.各个框架版本如下 spring boot:1.4.3.RELEASE spring framework: 4.3.5.RELEASE hibernate:5.0.1.Final(spring-boot-starter-data-jpa默认依赖) ehcache:2.10.3 项目依赖 <dependency> <groupId>org.springframework.boot</gro

  • 详解SpringBoot缓存的实例代码(EhCache 2.x 篇)

    本篇介绍了SpringBoot 缓存(EhCache 2.x 篇),分享给大家,具体如下: SpringBoot 缓存 在 spring Boot中,通过@EnableCaching注解自动化配置合适的缓存管理器(CacheManager),Spring Boot根据下面的顺序去侦测缓存提供者: Generic JCache (JSR-107) EhCache 2.x Hazelcast Infinispan Redis Guava Simple 关于 Spring Boot 的缓存机制: 高速

  • 详解Spring MVC 集成EHCache缓存

    废话少说,直接上代码: ehcache.xml 文件 <?xml version="1.0" encoding="UTF-8"?> <ehcache dynamicConfig="false" monitoring="off" updateCheck="false" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

  • Java Ehcache缓存框架入门级使用实例

    前言 JAVA缓存实现方案有很多,最基本的自己使用Map去构建缓存,或者使用memcached或Redis,但是上述两种缓存框架都要搭建服务器,而Map自行构建的缓存可能没有很高的使用效率,那么我们可以尝试一下使用Ehcache缓存框架. Ehcache主要基于内存缓存,磁盘缓存为辅的,使用起来方便.下面介绍如何在项目中使用Ehcache 入门使用教程 1.maven引用 <dependency> <groupId>net.sf.ehcache</groupId> &l

  • Spring+EHcache缓存实例详解

    一.ehcahe的介绍 EhCache 是一个纯Java的进程内缓存框架,具有高速.精干等特点,是Hibernate中默认的CacheProvider.Ehcache是一种广泛使用的开源Java分布式缓存. 主要面向通用缓存,Java EE和轻量级容器. 它具有内存和磁盘存储.缓存载入器,缓存扩展,缓存异常处理程序,一个gzip缓存servlet过滤器.支持REST和SOAP api等特点. 优点: 1. 高速 2. 简单 3. 多种缓存策略 4. 缓存数据有两级:内存和磁盘,因此无需操心容量问

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

    前言 众所周知,encache是现在最流行的java开源缓存框架,配置简单,结构清晰,功能强大.通过注解 @Cacheable 可以快速添加方法结果到缓存.通过 @CacheEvict 可以快速清除掉指定的缓存. 但由于 @CacheEvict 注解使用的是key-value的,不支持模糊删除,就会遇到问题.当我用 @Cacheable 配合Spring EL表达式添加了同一方法的多个缓存比如: @GetMapping("/listOfTask/{page}/") @Cacheable

  • 使用ehcache三步搞定springboot缓存的方法示例

    本次内容主要介绍基于Ehcache 3.0来快速实现Spring Boot应用程序的数据缓存功能.在Spring Boot应用程序中,我们可以通过Spring Caching来快速搞定数据缓存.接下来我们将介绍如何在三步之内搞定Spring Boot缓存. 1. 创建一个Spring Boot工程并添加Maven依赖 你所创建的Spring Boot应用程序的maven依赖文件至少应该是下面的样子: <?xml version="1.0" encoding="UTF-8

  • 实现 Java 本地缓存的方法解析

    缓存,我相信大家对它一定不陌生,在项目中,缓存肯定是必不可少的.市面上有非常多的缓存工具,比如 Redis.Guava Cache 或者 EHcache.对于这些工具,我想大家肯定都非常熟悉,所以今天我们不聊它们,我们来聊一聊如何实现本地缓存.参考上面几种工具,要实现一个较好的本地缓存,平头哥认为要从以下三个方面开始. 1.存储集合的选择 实现本地缓存,存储容器肯定是 key/value 形式的数据结构,在 Java 中,也就是我们常用的 Map 集合.Map 中有 HashMap.Hashta

  • JSP 开发之hibernate配置二级缓存的方法

    JSP 开发之hibernate配置二级缓存的方法 hibernate二级缓存也称为进程级的缓存或SessionFactory级的缓存. 二级缓存是全局缓存,它可以被所有的session共享. 二级缓存的生命周期和SessionFactory的生命周期一致,SessionFactory可以管理二级缓存. 常用的缓存插件 Hibernater二级缓存是一个插件,下面是几种常用的缓存插件: EhCache:可作为进程范围的缓存,存放数据的物理介质可以是内存或硬盘,对Hibernate的查询缓存提供了

  • Spring Boot 中使用cache缓存的方法

    一.什么是缓存 Cache Cache 一词最早来自于CPU设计 当CPU要读取一个数据时,首先从CPU缓存中查找,找到就立即读取并送给CPU处理:没有找到,就从速率相对较慢的内存中读取并送给CPU处理,同时把这个数据所在的数据块调入缓存中,可以使得以后对整块数据的读取都从缓存中进行,不必再调用内存.正是这样的读取机制使CPU读取缓存的命中率非常高(大多数CPU可达90%左右),也就是说CPU下一次要读取的数据90%都在CPU缓存中,只有大约10%需要从内存读取.这大大节省了CPU直接读取内存的

  • springboot中使用自定义两级缓存的方法

    工作中用到了springboot的缓存,使用起来挺方便的,直接引入redis或者ehcache这些缓存依赖包和相关缓存的starter依赖包,然后在启动类中加入@EnableCaching注解,然后在需要的地方就可以使用@Cacheable和@CacheEvict使用和删除缓存了.这个使用很简单,相信用过springboot缓存的都会玩,这里就不再多说了.美中不足的是,springboot使用了插件式的集成方式,虽然用起来很方便,但是当你集成ehcache的时候就是用ehcache,集成redi

  • thinkphp5redis缓存新增方法实例讲解

    找到该文件 thinkphp/library/think/cache/driver/Redis.php 进行新增方法 在这里 我就举例几个 如何添加 添加的方法查看 redis教程 /** * 返回列表中指定区间内的元素 * */ public function lrange($key,$start,$end){ return $this->handler->lrange($key,$start,$end); } /** * 在list左边新增元素 * */ public function l

  • Python批量生成字幕图片的方法详解

    目录 说明 前提 放码 说明 视频剪辑时需要为视频添加字幕,添加字幕方法之一:根据字幕文本文件批量生成透明底只有字幕内容的图片文件,如下图,然后将这些图片文件添加到视频剪辑软件轨道中. 于是用pillow这Python图片工具库执行本次批量生成工作. 前提 pip intall pillow 放码 from PIL import Image, ImageDraw, ImageFont import os imageWidth, imageHeight = 1920, 1080 fontsFold

  • Python使用LRU缓存策略进行缓存的方法步骤

    目录 一.Python 缓存 ① 缓存作用 ② 使用 Python 字典实现缓存 二.深入理解 LRU 算法 ① 查看 LRU 缓存的特点 ② 查看 LRU 缓存的结构 三.使用 lru_cache 装饰器 ① @lru_cache 装饰器的实现原理 ② 斐波拉契数列 ③ 使用 @lru_cache 缓存输出结果 ④ 限制 @lru_cache 装饰器大小 ⑤ 使用 @lru_cache 实现 LRU 缓存 ⑥ 解包 @lru_cache 的功能 四.添加缓存过期 五.@lru_cache 装饰

  • thinkPHP5框架整合plupload实现图片批量上传功能的方法

    本文实例讲述了thinkPHP5框架整合plupload实现图片批量上传功能的方法.分享给大家供大家参考,具体如下: 在官网下载plupload http://http//www.plupload.com 或者点击此处本站下载. 这里我们使用的是pluploadQueue 在HTML页面引入相应的css和js,然后根据示例代码修改为自己的代码 <link rel="stylesheet" href="/assets/plupupload/css/jquery.plupl

随机推荐