基于注解实现redis缓存数据

该博客介绍了如何使用Spring AOP和自定义注解实现Redis缓存功能。通过定义`CacheFind`注解,允许开发者指定缓存的key和超时时间。在AOP切面类中,检查缓存中是否存在数据,如果存在则直接返回,否则执行数据库操作并将结果存入Redis。同时提供了一个工具类`ObjectMapperUtil`用于JSON序列化和反序列化。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1,自定义一个注解,参数key是存到redis的key,时间就是缓存多久,默认是0,可以根据自己的业务去顶一个默认值

package com.clpc.un.pafp.statistics.config;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.METHOD)//对方法有效
@Retention(RetentionPolicy.RUNTIME)//运行期有效
public @interface CacheFind {
    public String key();
    public int seconds()default 0;//超时时间
}

定义redis配置IP地址,端口等,注入到bean里面

package com.clpc.un.pafp.statistics.config;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import redis.clients.jedis.Jedis;

@Configuration
@PropertySource("classpath:/properties/redis.properties")
public class RedisConfig {
    @Value("${redis.host}")
    private String host;
    @Value("${redis.port}")
    private Integer port;

    @Bean
    public Jedis jedis(){
        return new Jedis(host,port);
    }
}

 

2,定义aop切入注解,redis存储过则拿redis的数据,否则就去数据库拿,并且缓存到redis

package com.clpc.un.pafp.statistics.aop;

import com.clpc.un.pafp.statistics.config.CacheFind;
import com.clpc.un.pafp.statistics.config.ObjectMapperUtil;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import redis.clients.jedis.Jedis;

import java.util.Arrays;

/**
 * 此类作为缓存的AOP切面类
 */
@Aspect   //标记为切面
@Component  //交给spring管理
public class CacheAop {

    @Value("${Redis.Flag}")
    private Boolean redisFlag;

    @Autowired
    private Jedis jedis;

    /**
     * 实现思路:
     *      1.动态获取key   用户自定义的前缀+用户的参数[0,xx]
     *      2.判断key是否存在
     *      存在: 直接从redis中获取数据 JSON, 需要将json转化为具体对象  按照返回值类型进行转化
     *      不存在: 执行目标方法.获得返回值数据. 将返回值结果转化为JSON格式. 之后保存到缓存中.
     * @param joinPoint
     * @return
     */
    @Around("@annotation(cacheFind)")
    public Object around(ProceedingJoinPoint joinPoint, CacheFind cacheFind){
        Object result = null;
        //1,获取key的前缀
        String key = cacheFind.key();
        //2,获取方法参数
        String argString = Arrays.toString(joinPoint.getArgs());
        key = key+"::"+argString;
        if (redisFlag){
            try {
                //3.判断缓存中是否有数据
                if(jedis.exists(key)){
                    String json = jedis.get(key);
                    //5.获取返回值类型
                    MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
                    result = ObjectMapperUtil.toObject(json,methodSignature.getReturnType());
                    System.out.println("AOP查询redis缓存");
                }else{
                    //表示缓存中没有数据,执行目标方法
                    result = joinPoint.proceed();
                    String json = ObjectMapperUtil.toJSON(result);
                    //4.判断数据中是否有超时时间
                    if(cacheFind.seconds()>0){
                        jedis.setex(key,cacheFind.seconds(),json);
                    }else{
                        jedis.set(key,json);
                    }
                    System.out.println("AOP执行数据库调用!!!!!");
                }
            } catch (Throwable throwable) {
                throwable.printStackTrace();
                throw new RuntimeException(throwable);
            }
        }else{
            //表示缓存中没有数据,执行目标方法
            try {
                result = joinPoint.proceed();
                System.out.println("未启用redis缓存,查询数据库");
            } catch (Throwable throwable) {
                throwable.printStackTrace();
                throw new RuntimeException("AOP方法调用失败");
            }
        }

        return result;
    }
}
ObjectMapperUtil工具类
package com.clpc.un.pafp.statistics.config;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.context.annotation.Configuration;

@Configuration
public class ObjectMapperUtil {
    private static final ObjectMapper MAPPER = new ObjectMapper();

    public static String toJSON(Object target){
        try {
            return MAPPER.writeValueAsString(target);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
            //将检查异常转化为运行时异常.
            throw new RuntimeException(e);
        }
    }

    public static <T> T toObject(String json,Class<T> targetClass){
        try {
            return MAPPER.readValue(json, targetClass);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }
}

使用

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值