使用切面注解编程实现redis模糊删除数据之二使用spel表达式

传送门:使用切面注解编程实现redis模糊删除数据之一

之前虽然用切面编程实现了redis的模糊查询,但是却没有实现像spring-redis原生的语法一样的spEl表达式,比如#参数名这种形式,然后在网上找了一些资料,实现了和spring-redis一样的spEl表达,可以使用#参数名或者#p0这样的方式,下面是代码

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.annotation.Resource;

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.core.LocalVariableTableParameterNameDiscoverer;
import org.springframework.data.redis.core.RedisTemplate;
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 com.kq.highnet2.framework.base.common.annotation.CacheRemove;

@Aspect
@Component
public class CacheRemoveAspect {
    Logger logger=LoggerFactory.getLogger(this.getClass());
	@Resource(name = "redisTemplate") 
	RedisTemplate<String, String> redis;
	@Pointcut(value = "(execution(* *.*(..)) && "//截获标有@CacheRemove的方法
			+ "@annotation(com.kq.highnet2.framework.base.common.annotation.CacheRemove))")
    private void pointcut() {}
	@AfterReturning(value = "pointcut()")//切面在方法返回值之后
	private void process(JoinPoint joinPoint){
	    MethodSignature signature = (MethodSignature) joinPoint.getSignature();
	    Object[] args = joinPoint.getArgs();//切面方法的参数
	    Method method = signature.getMethod();//切面方法
	    CacheRemove cacheRemove = method.getAnnotation(CacheRemove.class);//获得注解
	    if (cacheRemove != null){
	        String value = cacheRemove.value();//暂时没用
	        String[] keys = cacheRemove.key(); //需要移除的正则key
	        for(String key:keys) {
	        	logger.info(key);
	        	key = parseKey(key, method, args);
	        	Set<String> keys2 = redis.keys(key);//获得redis中符合正则的缓存
	        	redis.delete(keys2);//删除缓存
	        	logger.info("删除缓存:"+key);
	        }
	        
	    }
	}
    /** 
     *    获取缓存的key  
     *    key 定义在注解上,支持SPEL表达式 
     * @param pjp 
     * @return 
     */  
    private String parseKey(String key,Method method,Object [] args){           
        //获取被拦截方法参数名列表(使用Spring支持类库)  
        LocalVariableTableParameterNameDiscoverer u =     
            new LocalVariableTableParameterNameDiscoverer();    
        String [] paraNameArr=u.getParameterNames(method);  
          
        //使用SPEL进行key的解析  
        ExpressionParser parser = new SpelExpressionParser();   
        //SPEL上下文  
        StandardEvaluationContext context = new StandardEvaluationContext();  
        //把方法参数放入SPEL上下文中  
        for(int i=0;i<paraNameArr.length;i++){  
            context.setVariable(paraNameArr[i], args[i]);  
        } 
        List<String> pList = descFormat(key);//获取#p0这样的表达式
        //将p0作为参数放入SPEL上下文中
        for(String p:pList) {
        	context.setVariable(p.substring(1), args[Integer.valueOf(p.substring(2))]);
        }
        return parser.parseExpression(key).getValue(context,String.class);  
    } 
    /**
     * 提取出#p[数字]这样的表达式
     * @param desc
     * @return
     */
    private static List<String> descFormat(String desc){  
        List<String> list = new ArrayList<>();  
        Pattern pattern = Pattern.compile("#p[0-9]+");   
        Matcher matcher = pattern.matcher(desc);   
        while(matcher.find()){   
            String t = matcher.group(0);   
            list.add(t);  
        }  
        return list;  
    }
}
这样就可以和原来@Cacheable等注解上的用法一样了
	@Caching(evict= {
		@CacheEvict(value="baseModulePermissionList",key="'baseModulePermissionList'+#userId"),
	})
	@CacheRemove(value="deletePermission",key = {"'baseButtonPermissionList'+#p0+'*'","'baseViewPermissionList'+#userId+'*'"})
	public void evictPermission(String userId) {
	}

亲测可以使用

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值