springboot中使用redis
Posted zhenghuasheng
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了springboot中使用redis相关的知识,希望对你有一定的参考价值。
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!!!
以上是关于springboot中使用redis的主要内容,如果未能解决你的问题,请参考以下文章
springboot中使用RedisTemplate实现redis数据缓存