Springboot使用内置缓存

Springboot内置了缓存,spring-cache

首先添加对应的依赖

<!--添加springboot缓存的依赖-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-cache</artifactId>
    <version>2.1.6.RELEASE</version>
</dependency>

启动类上添加@EnableCaching,用于开启缓存

在需要缓存的方法上,添加@Cacheable,当方法查询的内容存在于缓存中,则直接从缓存中获取值,否则再去按照方法中的实现去数据库查询并添加到缓存中

//key:缓存的键,使用"#方法形参名称"绑定缓存的键,如果不写,默认绑定方法上所有的形参
@Cacheable(value = "具体的缓存名称,自己命名",key = "#xxx")
public Student getStudent(String id){
    Student student= StudentMapper.selectOne(new QueryWrapper<Student >()
        .eq("id", id));
    return student;
}
在修改、删除方法上添加@CacheEvict用于删除缓存

@CacheEvict(value = "user", key = "'A'")           //删除user模块下名称为A的key也就是user::a

@CacheEvict(value = "user", allEntries = true)  //删除user模块下所有key;

 但是,@CacheEvict不支持多选删除,即无法用于批量删除等操作,因此,需要引入自定义注解来实现!!!

添加一个注解类

/**
 * 由于SpringCache自带的@CacheEvict不支持批量删除,自定义注解实现
 */
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface CacheBatchEvict {
    /**
     * 指定缓存组件
     */
    String[] cacheNames() default {};
    /**
     * key需要指定一个spEL表达式,通过spEL表达式获取方法参数
     */
    String key() default "";
    /**
     * 是否清除所有
     */
    boolean isClearAll() default false;
}

添加一个切面类

@Aspect
@Component
public class CacheBatchEvictAspect {
    @Autowired
    private CacheManager cacheManager;
    /**
     * 定义切入点
     */
    @Pointcut("@annotation(cn.com.dhcc.datafilling.aspect.annotation.CacheBatchEvict)")
    public void pointcut() {

    }

    @Around("pointcut()")
    public Object proceed(ProceedingJoinPoint joinPoint) throws Throwable {
        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
        // 1.获取注解参数值 SpEL表达式
        CacheBatchEvict cacheBatchEvict = methodSignature.getMethod().getAnnotation(CacheBatchEvict.class);
        String[] cacheNames = cacheBatchEvict.cacheNames();
        // 清空所有缓存
        if (cacheBatchEvict.isClearAll()) {
            for (String cacheName : cacheNames) {
                Cache cache = Objects.requireNonNull(cacheManager.getCache(cacheName));
                cache.clear();
            }
        }
        String spEL = cacheBatchEvict.key();
        if (!StringUtils.hasText(spEL)) {
            return null;
        }
        // 2.获取目标方法参数
        List<Object> keyList = generateKeyListBySpEL(spEL, joinPoint);
        if (keyList == null) {
            return null;
        }
        // 3.清除缓存
        for (String cacheName : cacheNames) {
            Cache cache = Objects.requireNonNull(cacheManager.getCache(cacheName));
            for (Object key : keyList) {
                if(cache.evictIfPresent(key)){
                    cache.evict(key);
                }
            }
        }
        // 4.执行目标方法
        return joinPoint.proceed();
    }

    public List<Object> generateKeyListBySpEL(String spEL, ProceedingJoinPoint joinPoint) {
        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
        Method method = methodSignature.getMethod();
        // 创建解析器
        SpelExpressionParser parser = new SpelExpressionParser();
        // 获取表达式
        Expression expression = parser.parseExpression(spEL);
        // 设置解析上下文
        EvaluationContext context = new StandardEvaluationContext();
        Object[] args = joinPoint.getArgs();
        // 获取运行时参数名称
        DefaultParameterNameDiscoverer discover = new DefaultParameterNameDiscoverer();
        String[] parameterNames = discover.getParameterNames(method);
        assert parameterNames != null;
        for (int i = 0; i < parameterNames.length; i++) {
            context.setVariable(parameterNames[i], args[i]);
        }
        // 解析
        List<Object> valueList = (List<Object>) expression.getValue(context);
        if (CollectionUtils.isEmpty(valueList)) {
            return null;
        }
        return valueList;
    }
}

使用时

@CacheBatchEvict(cacheNames = {"自定义的缓存名称"},key = "#形参名称")

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值