SpringBoot+Redis缓存自定义注解封装

场景:

项目中通常要使用Redis作为缓存,来提高系统查询的效率,减小数据库的压力,通过封装缓存注解,可以方便的在系统中按需缓存业务数据。

  1. 缓存自定义注解

可定义如模块、redis key、item值(hash数据类型使用)、type(String、Set)、opType(操作类型:Write、Read)、expire(key过期时间,默认为-1,不过期)。

@Target({ ElementType.PARAMETER, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
public @interface Cache {

    int EXPIRE_TIME_DEFAULT_NEVER = -1;

    String module();

    String key();

    String itemKey() default "";

    CacheType type();

    OpType opType();

    String condition() default "";

    int expire() default EXPIRE_TIME_DEFAULT_NEVER;

}
  1. Redis缓存类型
public enum CacheType {

    STRING,

    SET;
}
  1. 操作类型
public enum OpType {

    WRITE,

    READ,

}
  1. 缓存注解切面
@Slf4j
@Aspect
@Component
public class CacheAspect {

    private SpelExpressionParser parserSpel = new SpelExpressionParser();

    private DefaultParameterNameDiscoverer parameterNameDiscoverer= new DefaultParameterNameDiscoverer();
    @Autowired
    private RedisUtil redisUtil;

    @Around("@annotation(cache)")
    public Object interceptor(ProceedingJoinPoint joinPoint, Cache cache) throws Throwable {
        return handleCache(joinPoint, cache);
    }

    protected Object handleCache(final ProceedingJoinPoint joinPoint, Cache cache) throws Throwable {
        Object result = null;
        if(cache!=null){
            result = joinPoint.proceed();
            Object[] arguments = joinPoint.getArgs();
            Map<String,Object> obj = BeanUtil.beanToMap(result);

            if(OpType.WRITE == cache.opType()){
                if(CacheType.SET == cache.type()){
                    redisUtil.hset(cache.module()+cache.key(), String.valueOf(obj.get(cache.itemKey())),result, cache.expire());
                }else if(CacheType.STRING == cache.type()){
                    redisUtil.set(cache.module()+cache.key(),result,cache.expire());
                }
            }else if(OpType.READ == cache.opType()){
                if(CacheType.SET == cache.type()){
                    Object o = getValueBySpEL(cache.condition(),joinPoint);
                    if(o!=null){
                        result = redisUtil.hget(cache.module()+cache.key(), ((String[]) o));
                    }
                }else if(CacheType.STRING == cache.type()){
                    result = redisUtil.get(cache.module()+cache.key());
                }
            }
        }
        log.info("------从cache执行{}操作,结果:{}",cache.opType(),result);
        log.info("------从db执行{}操作,结果:{}",cache.opType(),result);
        return result;
    }

    public Object getValueBySpEL(String key, ProceedingJoinPoint pjp) {
        Expression expression = parserSpel .parseExpression(key);
        EvaluationContext context = new StandardEvaluationContext();
        MethodSignature methodSignature = (MethodSignature) pjp.getSignature();
        Object[] args = pjp.getArgs();
        String[] paramNames = parameterNameDiscoverer.getParameterNames(methodSignature.getMethod());
        for(int i = 0 ; i < args.length ; i++) {
            context.setVariable(paramNames[i], args[i]);
        }
        return expression.getValue(context);
    }
    
}
  1. 使用自定义注解
@Cache(module = Constants.MODULE_NAME_RBAC, key = REDIS_KEY, type = CacheType.SET, opType = OpType.WRITE, itemKey = "configKey")
public SysConfigDTO add(SysConfigBo config) {
    SysConfig sysConfig = BeanUtil.copyProperties(config, SysConfig.class);
    save(sysConfig);
    return BeanUtil.copyProperties(sysConfig, SysConfigDTO.class);
}

@Override
@Cache(module = Constants.MODULE_NAME_RBAC, key = REDIS_KEY, type = CacheType.SET, opType = OpType.WRITE, itemKey = "configKey")
public SysConfigDTO update(SysConfigBo config) {
    SysConfig sysConfig = BeanUtil.copyProperties(config, SysConfig.class);
    updateById(sysConfig);
    return BeanUtil.copyProperties(sysConfig, SysConfigDTO.class);
}

@Override
@Cache(module = Constants.MODULE_NAME_RBAC, key = REDIS_KEY, type = CacheType.SET, opType = OpType.READ,condition = "#keys")
public List<SysConfig> queryByKeys(String[] keys) {
    return null;
}
  1. 技术细节

    自定义注解可以使用SPEL表达式来动态获取方法传参,如:
    通过 condition = “#keys”,可在切面中获取动态参数,此实例是告诉切面按“condition”指定的动态参数值获取缓存中的数据。

@Cache(module = Constants.MODULE_NAME_RBAC, key = REDIS_KEY, type = CacheType.SET, opType = OpType.READ,condition = "#keys")
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring Boot是一个用于创建独立的、基于Spring的应用程序的框架,而Redis是一个开源的内存数据存储系统。结合使用Spring BootRedis可以实现高效的数据缓存和持久化。 在Spring Boot中使用Redis,首先需要在项目的pom.xml文件中添加Redis的依赖。然后,在application.properties或application.yml文件中配置Redis的连接信息,包括主机名、端口号、密码等。 接下来,可以通过使用Spring Data Redis来简化对Redis的操作。Spring Data Redis提供了一系列的注解和模板类,可以方便地进行数据的读取、写入和删除等操作。 以下是一个简单的示例,演示了如何在Spring Boot中使用Redis: 1. 添加依赖: 在pom.xml文件中添加以下依赖: ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> ``` 2. 配置Redis连接信息: 在application.properties或application.yml文件中添加以下配置: ```properties spring.redis.host=127.0.0.1 spring.redis.port=6379 spring.redis.password= ``` 3. 创建Redis操作类: ```java import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Component; @Component public class RedisUtil { @Autowired private RedisTemplate<String, Object> redisTemplate; public void set(String key, Object value) { redisTemplate.opsForValue().set(key, value); } public Object get(String key) { return redisTemplate.opsForValue().get(key); } public void delete(String key) { redisTemplate.delete(key); } } ``` 4. 使用Redis操作类: ```java import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RestController; @RestController public class UserController { @Autowired private RedisUtil redisUtil; @GetMapping("/user/{id}") public User getUser(@PathVariable String id) { // 先从缓存中获取数据 User user = (User) redisUtil.get("user:" + id); if (user == null) { // 如果缓存中不存在,则从数据库中获取数据 user = userService.getUserById(id); // 将数据存入缓存 redisUtil.set("user:" + id, user); } return user; } } ``` 以上示例中,我们创建了一个RedisUtil类来封装Redis的操作,然后在UserController中使用RedisUtil来实现对用户数据的缓存。当请求用户数据时,先从缓存中获取,如果缓存中不存在,则从数据库中获取,并将数据存入缓存

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值