springboot中使用redis

本文详细介绍如何在SpringBoot项目中配置并使用Redis,包括添加依赖、配置连接、自定义序列化方式及缓存管理。

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

springboot中使用redis

有关redis的基本知识不在此阐述,redis相关注解的使用请查看另外一篇文章:Spring Cache集成redis

直接上代码:

step 1:加入pom依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

step 2:创建redis配置
springboot配置文件中加入redis连接配置

spring.redis.database=0
spring.redis.host=
spring.redis.password=
spring.redis.pool.max-active=100
spring.redis.pool.max-idle=8
spring.redis.pool.max-wait=-1
spring.redis.pool.min-idle=0
spring.redis.port=6379
#spring.redis.sentinel.master= # Name of Redis server.
#spring.redis.sentinel.nodes= # Comma-separated list of host:port pairs.
spring.redis.timeout=10000

/**
 *
 * @author zhenghuasheng
 * @date 2016/5/9
 */

@Configuration
@EnableCaching
public class RedisConfig extends CachingConfigurerSupport {

    @Value(value = "${spring.redis.password}")
    private String redisPassword;

    @Bean
    public KeyGenerator localKeyGenerator(){
        return (target, method, params) -> {
            StringBuilder sb = new StringBuilder();
            sb.append(target.getClass().getName());
            sb.append(method.getName());
            for (Object obj : params) {
                if (obj != null) {
                    sb.append(obj.toString());
                }
            }
            return sb.toString();
        };
    }

    @Bean
    public CacheManager cacheManager(@SuppressWarnings("rawtypes") RedisTemplate redisTemplate) {
        RedisCacheManager redisCacheManager =  new RedisCacheManager(redisTemplate);
        redisCacheManager.setUsePrefix(true);
        redisCacheManager.setDefaultExpiration(1800L);
        return redisCacheManager;
    }

    @Bean
    public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory factory) {
        StringRedisTemplate template = new StringRedisTemplate(factory);

        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
//        JdkSerializationRedisSerializer jdkSerializationRedisSerializer = new JdkSerializationRedisSerializer();
        ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(om);
        template.setKeySerializer(new StringRedisSerializer());
        template.setValueSerializer(jackson2JsonRedisSerializer);
        template.afterPropertiesSet();
        return template;
    }
//    @Bean
//    public JedisConnectionFactory redisConnectionFactory() {
//        JedisConnectionFactory factory = new JedisConnectionFactory();
//        factory.setPassword(redisPassword);
//        factory.setPoolConfig(new JedisPoolConfig());
////        factory.setHostName(host);
////        factory.setPort(port);
////        factory.setTimeout(timeout); //设置连接超时时间
//        return factory;
//    }
}

说明:@EnableCaching注解是spring framework中的注解驱动的缓存管理功能。自spring版本3.1起加入了该注解。如果你使用了这个注解,那么你就不需要在XML文件中配置cache manager了。

当你在配置类(@Configuration)上使用@EnableCaching注解时,会触发一个post processor,这会扫描每一个spring bean,查看是否已经存在注解对应的缓存。如果找到了,就会自动创建一个代理拦截方法调用,使用缓存的bean执行处理。

localKeyGenerator():为自定义缓存key的生成方法。
redisConnectionFactory():可以自定义factory的属性,也可以使用默认配置
redisTemplate(RedisConnectionFactory factory):此处配置redis的序列化配置,
当我们的数据存储到Redis的时候,我们的键(key)和值(value)都是通过Spring提供的Serializer序列化到数据库的。RedisTemplate默认使用的是JdkSerializationRedisSerializer,StringRedisTemplate默认使用的是StringRedisSerializer。

Spring Data JPA为我们提供了下面的Serializer:GenericToStringSerializer、Jackson2JsonRedisSerializer、JacksonJsonRedisSerializer、JdkSerializationRedisSerializer、OxmSerializer、StringRedisSerializer。

序列化方式对比:

JdkSerializationRedisSerializer: 使用JDK提供的序列化功能。 优点是反序列化时不需要提供类型信息(class),但缺点是需要实现Serializable接口,还有序列化后的结果非常庞大,是JSON格式的5倍左右,这样就会消耗redis服务器的大量内存。
Jackson2JsonRedisSerializer: 使用Jackson库将对象序列化为JSON字符串。优点是速度快,序列化后的字符串短小精悍,不需要实现Serializable接口。但缺点也非常致命,那就是此类的构造函数中有一个类型参数,必须提供要序列化对象的类型信息(.class对象)。 通过查看源代码,发现其只在反序列化过程中用到了类型信息。

在此,我们使用的是StringRedisTemplate
StringRedisTemplate template = new StringRedisTemplate(factory);

这会有个问题,序列化会报类型转换错误,如XXX类不能转换成String。

问题分析:
使用StringRedisSerializer做key的序列化时,StringRedisSerializer的泛型指定的是String,传其他对象就会报类型转换错误,在使用@Cacheable注解是key属性就只能传String进来。把这个序列化方式重写了,将泛型改成Object。源码:

/**
 * @author zhenghuasheng
 * @date 2018/8/23.16:49
 */
public class StringRedisSerializer implements RedisSerializer<Object> {
    private final Charset charset;

    private final String target = "\"";

    private final String replacement = "";

    public StringRedisSerializer() {
        this(Charset.forName("UTF8"));
    }

    public StringRedisSerializer(Charset charset) {
        Assert.notNull(charset, "Charset must not be null!");
        this.charset = charset;
    }

    @Override
    public String deserialize(byte[] bytes) {
        return (bytes == null ? null : new String(bytes, charset));
    }

    @Override
    public byte[] serialize(Object object) {
        if (object == null) {
            return null;
        }
        String string = JSON.toJSONString(object);
        string = string.replace(target, replacement);
        return string.getBytes(charset);
    }
}

value的序列化使用jackson2JsonRedisSerializer
template.setValueSerializer(jackson2JsonRedisSerializer);
这里可能还有个不是问题的问题,如果存储的class中 字段无set方法时,会出现反序列化失败,在此我们为了避免该问题,可以将value的序列化使用fastjson来实现

/**
 * @author zhenghuasheng
 * @date 2018/8/23.20:28
 */
public class FastJsonRedisSerializer<T> implements RedisSerializer<T>{

    public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8");

    private Class<T> clazz;

    public FastJsonRedisSerializer(Class<T> clazz) {
        super();
        this.clazz = clazz;
    }

    @Override
    public byte[] serialize(T t) throws SerializationException {
        if (t == null) {
            return new byte[0];
        }
        return JSON.toJSONString(t).getBytes(DEFAULT_CHARSET);
    }

    @Override
    public T deserialize(byte[] bytes) throws SerializationException {
        if (bytes == null || bytes.length <= 0) {
            return null;
        }
        String str = new String(bytes, DEFAULT_CHARSET);
        return (T) JSON.parseObject(str, clazz);
    }
}

更改对应的配置

@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
    RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
    redisTemplate.setConnectionFactory(redisConnectionFactory);

FastJsonRedisSerializer<Object> fastJsonRedisSerializer = new FastJsonRedisSerializer<>(Object.class);
// 全局开启AutoType,不建议使用
// ParserConfig.getGlobalInstance().setAutoTypeSupport(true);
// 建议使用这种方式,小范围指定白名单
ParserConfig.getGlobalInstance().addAccept("com.jz");

// 设置值(value)的序列化采用FastJsonRedisSerializer。
redisTemplate.setValueSerializer(fastJsonRedisSerializer);
redisTemplate.setHashValueSerializer(fastJsonRedisSerializer);
// 设置键(key)的序列化采用StringRedisSerializer。
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setHashKeySerializer(new StringRedisSerializer());

redisTemplate.afterPropertiesSet();
return redisTemplate;

}

redis的相关配置已经完成,可以使用相关注解或 RedisTemplate 来操作redis!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值