Home  >  Article  >  Database  >  How to cache database data to Redis through custom cache annotations in SpringBoot

How to cache database data to Redis through custom cache annotations in SpringBoot

WBOY
WBOYforward
2023-06-01 13:49:061222browse

Implementation

First create a new table bus_student in Mysql

How to cache database data to Redis through custom cache annotations in SpringBoot

Then use code generation based on this table, and the front-end Vue and back-end code generation are combined Add menu.

How to cache database data to Redis through custom cache annotations in SpringBoot

#Then come to the background code. In the background framework, the relevant dependencies and tool classes for operating redis have been added.

But you also need to add aspect dependencies here

        <!-- https://mvnrepository.com/artifact/org.springframework/spring-aspects --><dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aspects</artifactId>
            <version>4.3.14.RELEASE</version>
        </dependency>

Then create annotations for adding redis cache

package com.ruoyi.system.redisAop;


import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;/*
 * @Author
 * @Description 新增redis缓存
 **/@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)public @interface AopCacheEnable {//redis缓存key    String[] key();//redis缓存存活时间默认值(可自定义)long expireTime() default 3600;

}

and deleting redis cache where the configuration class is stored

package com.ruoyi.system.redisAop;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;/*
 * @Description 删除redis缓存注解
 **/@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)public @interface AopCacheEvict {//redis中的key值    String[] key();
}

Then create a new custom cache aspect specific implementation class CacheEnableAspect

Storage location

How to cache database data to Redis through custom cache annotations in SpringBoot##

package com.ruoyi.system.redisAop;


import com.ruoyi.system.domain.BusStudent;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;/*
 * @Description 自定义缓存切面具体实现类
 **/@Aspect
@Componentpublic class CacheEnableAspect {

    @Autowiredpublic RedisTemplate redisCache;/**
     * Mapper层切点 使用到了我们定义的 AopCacheEnable 作为切点表达式。     */@Pointcut("@annotation(com.ruoyi.system.redisAop.AopCacheEnable)")public void queryCache() {
    }/**
     * Mapper层切点 使用到了我们定义的 AopCacheEvict 作为切点表达式。     */@Pointcut("@annotation(com.ruoyi.system.redisAop.AopCacheEvict)")public void ClearCache() {
    }

    @Around("queryCache()")public Object Interceptor(ProceedingJoinPoint pjp) {
        Object result = null;//注解中是否有#标识boolean spelFlg = false;//判断是否需要走数据库查询boolean selectDb = false;//redis中缓存的keyString redisKey = "";//获取当前被切注解的方法名Method method = getMethod(pjp);//获取当前被切方法的注解AopCacheEnable aopCacheEnable = method.getAnnotation(AopCacheEnable.class);//获取方法参数值Object[] arguments = pjp.getArgs();//从注解中获取字符串String[] spels = aopCacheEnable.key();for (String spe1l : spels) {if (spe1l.contains("#")) {//注解中包含#标识,则需要拼接spel字符串,返回redis的存储redisKeyredisKey = spe1l.substring(1) + arguments[0].toString();
            } else {//没有参数或者参数是List的方法,在缓存中的keyredisKey = spe1l;
            }//取出缓存中的数据result = redisCache.opsForValue().get(redisKey);//缓存是空的,则需要重新查询数据库if (result == null || selectDb) {try {
                    result =  pjp.proceed();//从数据库查询到的结果不是空的if (result != null && result instanceof ArrayList) {//将redis中缓存的结果转换成对象listList<BusStudent> students = (List<BusStudent>) result;//判断方法里面的参数是不是BusStudentif (arguments[0] instanceof BusStudent) {//将rediskey-students 存入到redisredisCache.opsForValue().set(redisKey, students, aopCacheEnable.expireTime(), TimeUnit.SECONDS);
                        }
                    }
                } catch (Throwable e) {
                    e.printStackTrace();
                }
            }
        }return result;
    }/*** 定义清除缓存逻辑,先操作数据库,后清除缓存*/@Around(value = "ClearCache()")public Object evict(ProceedingJoinPoint pjp) throws Throwable {//redis中缓存的keyMethod method = getMethod(pjp);// 获取方法的注解AopCacheEvict cacheEvict = method.getAnnotation(AopCacheEvict.class);//先操作dbObject result = pjp.proceed();// 获取注解的key值String[] fieldKeys = cacheEvict.key();for (String spe1l : fieldKeys) {//根据key从缓存中删除            redisCache.delete(spe1l);
        }return result;
    }/**
     * 获取被拦截方法对象     */public Method getMethod(ProceedingJoinPoint pjp) {
        Signature signature = pjp.getSignature();
        MethodSignature methodSignature = (MethodSignature) signature;
        Method targetMethod = methodSignature.getMethod();return targetMethod;
    }
}

Pay attention to the queryCache and ClearCache here, and the cut points inside The expression

corresponds to the two customized AopCacheEnable and AopCacheEvict respectively.

Then before and after the queryCache method of the surrounding notification is executed

Get the parameters of the cut method, the key in the parameter, and then query in redis according to the key,

If If it cannot be found, convert the return result of the method into an object List and store it in redis.

If it can be found, the result will be returned.

Then find the query method and mapper layer of this table. For example, if you want to store the query return results in redis

    @AopCacheEnable(key = "BusStudent",expireTime = 40)public List<BusStudent> selectBusStudentList(BusStudent busStudent);

, then add the mapper methods of adding, editing, and deleting this table.

    /**
     * 新增学生
     *
     * @param busStudent 学生
     * @return 结果     */@AopCacheEvict(key = "BusStudent")public int insertBusStudent(BusStudent busStudent);/**
     * 修改学生
     *
     * @param busStudent 学生
     * @return 结果     */@AopCacheEvict(key = "BusStudent")public int updateBusStudent(BusStudent busStudent);/**
     * 删除学生
     *
     * @param id 学生ID
     * @return 结果     */@AopCacheEvict(key = "BusStudent")public int deleteBusStudentById(Integer id);

Note that the key in the annotation here must be consistent with the key in the annotation of the query above.

Then start the project, if it prompts:

Consider marking one of the beans as @Primary, updating

the consumer to acce

How to cache database data to Redis through custom cache annotations in SpringBoot

Because when sringboot injects the implementation class of the interface through @Autowired, it finds that there are multiple implementation classes, that is, there are multiple classes that inherit this interface, and the spring container does not know which one to use.

Find the redis configuration class and add the @Primary annotation on the RedisTemplate

How to cache database data to Redis through custom cache annotations in SpringBoot

Verify the use of the annotation

Debug startup project, in CacheEnableAspect Query the breakpoint in the annotation, and then call the query method.

You can see that the breakpoint can be entered, and then you can modify the annotation according to the logic and effect you want.

How to cache database data to Redis through custom cache annotations in SpringBoot

How to cache database data to Redis through custom cache annotations in SpringBoot

The above is the detailed content of How to cache database data to Redis through custom cache annotations in SpringBoot. For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:yisu.com. If there is any infringement, please contact admin@php.cn delete