欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Springboot Cache @CacheEvict 无法模糊删除的解决方案

程序员文章站 2022-03-07 17:18:36
目录springbootcache @cacheevict 无法模糊删除以下代码适用于redis@cacheevict根据缓存名称模糊删除看源码可知springbootcache @cacheevic...

springbootcache @cacheevict 无法模糊删除

用@cacheevict删除缓存只能删除指定key的缓存,有些情况需要根据前缀删除所有key的时候,用@cacheevict就做不到了,所以我们自定义一个@cacheremove来处理根据前缀模糊删除所有cache(支持spring el表达式)

以下代码适用于redis

添加依赖

<dependency>
    <groupid>org.springframework.boot</groupid>
    <artifactid>spring-boot-starter-aop</artifactid>
</dependency>

启动类加上 @enableaspectjautoproxy

@cacheremove 代码

package com.marssvn.utils.annotation.cache; 
import java.lang.annotation.retention;
import java.lang.annotation.retentionpolicy;
import java.lang.annotation.target; 
import static java.lang.annotation.elementtype.method;
 
@target({method})
@retention(retentionpolicy.runtime)
public @interface cacheremove {
 
    string[] value() default {};
}

cacheremoveaspect aop实现类代码

package com.marssvn.utils.annotation.cache.aspect; 
import com.marssvn.utils.annotation.cache.cacheremove;
import org.aspectj.lang.joinpoint;
import org.aspectj.lang.annotation.afterreturning;
import org.aspectj.lang.annotation.aspect;
import org.aspectj.lang.reflect.methodsignature;
import org.slf4j.logger;
import org.slf4j.loggerfactory;
import org.springframework.core.localvariabletableparameternamediscoverer;
import org.springframework.data.redis.core.stringredistemplate;
import org.springframework.expression.expressionparser;
import org.springframework.expression.spel.standard.spelexpressionparser;
import org.springframework.expression.spel.support.standardevaluationcontext;
import org.springframework.stereotype.component;
 
import javax.annotation.resource;
import java.lang.reflect.method;
import java.util.set;
 
@aspect
@component
public class cacheremoveaspect {
 
    @resource
    private stringredistemplate stringredistemplate; 
    private logger logger = loggerfactory.getlogger(this.getclass());
 
    @afterreturning("@annotation(com.marssvn.utils.annotation.cache.cacheremove)")
    public void remove(joinpoint point) {
        method method = ((methodsignature) point.getsignature()).getmethod();
        cacheremove cacheremove = method.getannotation(cacheremove.class);
        string[] keys = cacheremove.value();
        for (string key : keys) {
            if (key.contains("#"))
                key = parsekey(key, method, point.getargs());
 
            set<string> deletekeys = stringredistemplate.keys(key);
            stringredistemplate.delete(deletekeys);
            logger.info("cache key: " + key + " deleted");
        }
    }
 
    /**
     * parsekey from spel
     */
    private string parsekey(string key, method method, object [] args){
        localvariabletableparameternamediscoverer u =
                new localvariabletableparameternamediscoverer();
        string[] paranamearr = u.getparameternames(method);
 
        expressionparser parser = new spelexpressionparser();
        standardevaluationcontext context = new standardevaluationcontext();
 
        for (int i = 0; i < paranamearr.length; i++) {
            context.setvariable(paranamearr[i], args[i]);
        }
        return parser.parseexpression(key).getvalue(context, string.class);
    }
}

service中的调用代码

  /**
     * delete repository
     *
     * @param id repositoryid
     */
    @override
    @transactional
    @cacheremove({"repository.list::*", "'repository::id=' + #id", "'repository.tree::id=' + #id + '*'"})
    public void deleterepositorybyid(int id) {
 
        //  business code
    }

@cacheevict根据缓存名称模糊删除

@cacheevict(cachenames = "likename" ,allentries=true)
  • allentries=true 开启全匹配
  • cachenames 填写 模糊删除的name

看源码可知

Springboot Cache @CacheEvict 无法模糊删除的解决方案

以上为个人经验,希望能给大家一个参考,也希望大家多多支持。