springboot整合redis分别实现手动缓存和注解缓存

一、前期准备

  1. 一个构建好的springboot系统
  2. 下载redis安装包,去redis官网下载
  3. 启动redis服务,windows下双击bin目录下的redis-service.exe

二、环境构建

  1. 在项目的pom.xml中引入redis依赖
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
  1. 在项目配置文件application.yml中添加redis配置
spring:
  #redis缓存
  redis:
    open: true  # 是否开启redis缓存  true开启   false关闭
    database: 0
    host: 127.0.0.1
    port: 6379
    password:    # 密码(默认为空)
    timeout: 60000ms  # 连接超时时长(毫秒)
    jedis:
      pool:
        max-active: 1000  # 连接池最大连接数(使用负值表示没有限制)
        max-wait: -1ms      # 连接池最大阻塞等待时间(使用负值表示没有限制)
        max-idle: 10      # 连接池中的最大空闲连接
        min-idle: 5       # 连接池中的最小空闲连接

三、redis手动缓存

1、缓存配置


import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.*;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.time.Duration;

/**
 * 缓存配置类
 * @author 谢小鱼
 * @Date 2019-11-20 11:00
 **/
@Configuration
@EnableCaching
public class RedisConfig extends CachingConfigurerSupport {
    
    @Bean
    public RedisTemplate<String, Object> redisTemplate() {
        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setHashKeySerializer(new StringRedisSerializer());
        redisTemplate.setHashValueSerializer(new StringRedisSerializer());
        redisTemplate.setValueSerializer(new StringRedisSerializer());
        redisTemplate.setConnectionFactory(factory);
        return redisTemplate;
    }
    @Bean
    public HashOperations<String, String, Object> hashOperations(RedisTemplate<String, Object> redisTemplate) {
        return redisTemplate.opsForHash();
    }

    @Bean
    public ValueOperations<String, String> valueOperations(RedisTemplate<String, String> redisTemplate) {
        return redisTemplate.opsForValue();
    }

    @Bean
    public ListOperations<String, Object> listOperations(RedisTemplate<String, Object> redisTemplate) {
        return redisTemplate.opsForList();
    }

    @Bean
    public SetOperations<String, Object> setOperations(RedisTemplate<String, Object> redisTemplate) {
        return redisTemplate.opsForSet();
    }

    @Bean
    public ZSetOperations<String, Object> zSetOperations(RedisTemplate<String, Object> redisTemplate) {
        return redisTemplate.opsForZSet();
    }
}

四、redis注解缓存

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.*;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.time.Duration;

/**
 * 缓存配置类
 * @author 谢小鱼
 * @Date 2019-11-20 11:00
 **/
@Configuration
@EnableCaching
public class RedisConfig extends CachingConfigurerSupport {
    private static final Logger logger = LoggerFactory.getLogger(RedisConfig.class);
    @Autowired
    private RedisConnectionFactory factory;
    /**
     * 默认两小时
     */
    private static final long DURATION_SECOND_7200 = 7200L;
    private static final long DURATION_SECOND_300 = 300L;
    
    @Override
    @Bean
    public KeyGenerator keyGenerator() {
        return new KeyGenerator() {
            @SuppressWarnings("rawtypes")
            @Override
            public Object generate(Object target, Method method, Object... params) {
                StringBuilder sb = new StringBuilder(RedisAutoCacheValue.AUTO_KEY_PREFIX);
                if(target instanceof Proxy) {
                	//如果是代理类
                	Class[] i = target.getClass().getInterfaces();
                	if(i != null  && i.length > 0) {
                		//取第一个即可
                		sb.append(i[0].getName());
                	}else {
                		sb.append(target.getClass().getName());
                	}
                } else if(target instanceof org.springframework.cglib.proxy.Factory){
                    //如果是cglib代理,需要手动去除 $$ 后面的
                    String className = target.getClass().getName();
                    sb.append(className, 0, className.indexOf("$$"));
                } else {
                	sb.append(target.getClass().getName());
                }
                sb.append(".");
                sb.append(method.getName());
                sb.append("_");
                for (Object obj : params) {
                    if (obj != null) {
                        Class cls = obj.getClass();
                        if (cls.isArray()) {
                            //对于基础数据处理
                            logger.info("keyGenerator : {}", cls.getComponentType());
                            if (cls.isAssignableFrom(long.class)) {
                                long[] ay = (long[]) obj;
                                for (long o : ay) {
                                    sb.append(o).append("");
                                }
                            } else if (cls.isAssignableFrom(int.class)) {
                                int[] ay = (int[]) obj;
                                for (int o : ay) {
                                    sb.append(o).append("");
                                }
                            } else if (cls.isAssignableFrom(float.class)) {
                                float[] ay = (float[]) obj;
                                for (float o : ay) {
                                    sb.append(o).append("");
                                }
                            } else if (cls.isAssignableFrom(double.class)) {
                                double[] ay = (double[]) obj;
                                for (double o : ay) {
                                    sb.append(o).append("");
                                }
                            } else if (cls.isAssignableFrom(String.class)) {
                                String[] ay = (String[]) obj;
                                for (String o : ay) {
                                    sb.append(o).append("");
                                }
                            } else {
                                sb.append(obj.toString());
                            }
                            //TODO 对其他类型数组处理
                        } else {
                            sb.append(obj.toString());
                        }
                    } else {
                        sb.append("null");
                    }
                    sb.append("_");
                    //sb.append(obj == null ? "null" : obj.toString());
                }
                sb.delete(sb.length()-1, sb.length());
                return sb.toString();
            }

        };

    }

    /**
     * 默认的缓存管理,存放时效较长的缓存
     * @param redisTemplate
     * @return
     */
    @SuppressWarnings({"rawtypes", "Duplicates"})
    @Primary
    @Bean
    public CacheManager cacheManager(RedisTemplate redisTemplate) {
        RedisCacheConfiguration config = RedisCacheConfiguration
                .defaultCacheConfig()
                //过期时间
                .entryTtl(Duration.ofSeconds(DURATION_SECOND_7200))
                //不缓存null值
                //.disableCachingNullValues()
                //明确manager中的序列化与template一样,防止莫名其妙的问题
                .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(this.keySerializer()))
                .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(this.valueSerializer()));

        RedisCacheManager rcm = RedisCacheManager.builder(redisTemplate.getConnectionFactory()).cacheDefaults(config).transactionAware().build();
        return rcm;
    }

    /**
     * 存放时效较短的缓存(5分钟)
     * @param redisTemplate
     * @return
     */
    @SuppressWarnings({"rawtypes", "Duplicates"})
    @Bean
    public CacheManager cacheManagerIn5Minutes(RedisTemplate redisTemplate) {
        RedisCacheConfiguration config = RedisCacheConfiguration
                .defaultCacheConfig()
                //过期时间
                .entryTtl(Duration.ofSeconds(DURATION_SECOND_300))
                //不缓存null值
                //.disableCachingNullValues()
                //明确manager中的序列化与template一样,防止莫名其妙的问题
                .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(this.keySerializer()))
                .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(this.valueSerializer()));

        RedisCacheManager rcm = RedisCacheManager.builder(redisTemplate.getConnectionFactory()).cacheDefaults(config).transactionAware().build();
        return rcm;
    }
    
    private RedisSerializer<String> keySerializer() {
        return new StringRedisSerializer();
    }
    private RedisSerializer<Object> valueSerializer() {
        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
        ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        //略过不匹配的属性
        om.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

        jackson2JsonRedisSerializer.setObjectMapper(om);
        return jackson2JsonRedisSerializer;
    }
}

自动缓存key:

/**
 * 自动缓存value集中在此
 * @author Leon
 * @Date 2019-11-19 12:38
 **/
public class RedisAutoCacheValue {

    /**
     * 自动生成key前缀
     */
    public static final String AUTO_KEY_PREFIX = "AUTO:";
}


推荐使用注解的方式操作redis,便于维护

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值