-
Jedis与RedisTemplate的区别:
Jedis是Redis官方推荐的面向Java的操作Redis的客户端,可以用JedisPool来获得连接进行get、set、del等操作相对简单,而RedisTemplate是SpringDataRedis中对JedisApi的高度封装。
SpringDataRedis相对于Jedis来说可以方便地更换Redis的Java客户端,比Jedis多了自动管理连接池的特性,方便与其他Spring框架进行搭配使用如:SpringCache
参考:https://blog.csdn.net/varyall/article/details/83476970 -
redisTemplate与stringRedisTemplate的区别
第一点,StringRedisTemplate继承了RedisTemplate。
第二点,RedisTemplate是一个泛型类,而StringRedisTemplate则不是。
第三点,StringRedisTemplate只能对key=String,value=String的键值对进行操作,RedisTemplate可以对任何类型的key-value键值对操作。
第四点,是他们各自序列化的方式不同,但最终都是得到了一个字节数组,殊途同归,StringRedisTemplate使用的是StringRedisSerializer类;RedisTemplate使用的是JdkSerializationRedisSerializer类。反序列化,则是一个得到String,一个得到Object
这两个类是springboot-data-redis对Redis进行操作的实现类。打开StringRedisTemplate和RedisTemplate的源码,发现StringRedisTemplate继承了RedisTemplate,一般来说子类应该比父类有用更强大的功能,而此处却不是,因为RedisTemplate是泛型类,而在StringRedisTemplate继承RedisTemplate类时,则是指定了泛型的类型,两个String。
这就直接导致了,StringRedisTemplate只能处理String-String的键值对数据,而RedisTemplate则可以处理任何类型的键值对。
RedisTemplate源码:
public class RedisTemplate<K, V> extends RedisAccessor implements RedisOperations<K, V>, BeanClassLoaderAware {}
StringRedisTemplate源码:
public class StringRedisTemplate extends RedisTemplate<String, String> {}
参考:https://jingyan.baidu.com/article/f7ff0bfcc5c4152e26bb13bc.html
- 序列化:
redis中对序列化的应用主要是在四个方面,分别是
keySerializer、valueSerializer、hashKeySerialiser、hashValueSerializer。可以从StringRedisTemplate的源码中体现出来:
/**
* Constructs a new <code>StringRedisTemplate</code> instance. {@link #setConnectionFactory(RedisConnectionFactory)}
* and {@link #afterPropertiesSet()} still need to be called.
*/
public StringRedisTemplate() {
setKeySerializer(RedisSerializer.string());
setValueSerializer(RedisSerializer.string());
setHashKeySerializer(RedisSerializer.string());
setHashValueSerializer(RedisSerializer.string());
}
在redisTemplate中采用的序列化机制默认都是JdkSerializationRedisSerializer,源码:
@Override
public void afterPropertiesSet() {
super.afterPropertiesSet();
boolean defaultUsed = false;
if (defaultSerializer == null) {
defaultSerializer = new JdkSerializationRedisSerializer(
classLoader != null ? classLoader : this.getClass().getClassLoader());
}
if (enableDefaultSerializer) {
if (keySerializer == null) {
keySerializer = defaultSerializer;
defaultUsed = true;
}
if (valueSerializer == null) {
valueSerializer = defaultSerializer;
defaultUsed = true;
}
if (hashKeySerializer == null) {
hashKeySerializer = defaultSerializer;
defaultUsed = true;
}
if (hashValueSerializer == null) {
hashValueSerializer = defaultSerializer;
defaultUsed = true;
}
}
if (enableDefaultSerializer && defaultUsed) {
Assert.notNull(defaultSerializer, "default serializer null and not all serializers initialized");
}
if (scriptExecutor == null) {
this.scriptExecutor = new DefaultScriptExecutor<>(this);
}
initialized = true;
}
而在StringRedisTemplate中默认采用的序列化机制是:StringRedisSerializer,源码:
/**
* Constructs a new <code>StringRedisTemplate</code> instance. {@link #setConnectionFactory(RedisConnectionFactory)}
* and {@link #afterPropertiesSet()} still need to be called.
*/
public StringRedisTemplate() {
setKeySerializer(RedisSerializer.string());
setValueSerializer(RedisSerializer.string());
setHashKeySerializer(RedisSerializer.string());
setHashValueSerializer(RedisSerializer.string());
}
/**
* Obtain a simple {@link java.lang.String} to {@literal byte[]} (and back) serializer using
* {@link java.nio.charset.StandardCharsets#UTF_8 UTF-8} as the default {@link java.nio.charset.Charset}.
*
* @return never {@literal null}.
* @since 2.1
*/
static RedisSerializer<String> string() {
return StringRedisSerializer.UTF_8;
}
public static final StringRedisSerializer UTF_8 = new StringRedisSerializer(StandardCharsets.UTF_8);
无论是JdkSerializationRedisSerializer还是StringRedisSerializer都实现泛型接口RedisSerializer, 源码:
/**
* Basic interface serialization and deserialization of Objects to byte arrays (binary data). It is recommended that
* implementations are designed to handle null objects/empty arrays on serialization and deserialization side. Note that
* Redis does not accept null keys or values but can return null replies (for non existing keys).
*
* @author Mark Pollack
* @author Costin Leau
* @author Christoph Strobl
*/
public interface RedisSerializer<T> {}
/**
* Java Serialization Redis serializer. Delegates to the default (Java based) {@link DefaultSerializer serializer} and
* {@link DefaultDeserializer}. This {@link RedisSerializer serializer} can be constructed with either custom
* {@link ClassLoader} or own {@link Converter converters}.
*
* @author Mark Pollack
* @author Costin Leau
* @author Mark Paluch
* @author Christoph Strobl
*/
public class JdkSerializationRedisSerializer implements RedisSerializer<Object> {}
/**
* Simple {@link java.lang.String} to {@literal byte[]} (and back) serializer. Converts {@link java.lang.String Strings}
* into bytes and vice-versa using the specified charset (by default {@literal UTF-8}).
* <p>
* Useful when the interaction with the Redis happens mainly through Strings.
* <p>
* Does not perform any {@literal null} conversion since empty strings are valid keys/values.
* * @author Costin Leau
* @author Christoph Strobl
* @author Mark Paluch
*/
public class StringRedisSerializer implements RedisSerializer<String> {}
除此外,spring-data-redis中还有几个也实现了RedisSerializer接口的序列化类,它们之间的区别如下:
-
GenericToStringSerializer: 可以将任何对象泛化为字符串并序列化
-
Jackson2JsonRedisSerializer: 跟JacksonJsonRedisSerializer实际上是一样的
-
JacksonJsonRedisSerializer: 序列化object对象为json字符串,jackson-json工具提供了javabean与json之间的转换能力,可以将pojo实例序列化成json格式存储在redis中,也可以将json格式的数据转换成pojo实例。因为jackson工具在序列化和反序列化时,需要明确指定Class类型,因此此策略封装起来稍微复杂。【需要jackson-mapper-asl工具支持】
-
JdkSerializationRedisSerializer: 序列化java对象(被序列化的对象必须实现Serializable接口),使用JDK本身序列化机制,将pojo类通ObjectInputStream/ObjectOutputStream进行序列化操作,最终redis-server中将存储字节序列。是目前最常用的序列化策略
-
StringRedisSerializer: 简单的字符串序列化,根据指定的charset对数据的字节序列编码成string,是“new String(bytes, charset)”和“string.getBytes(charset)”的直接封装。是最轻量级和高效的策略。
-
GenericToStringSerializer:类似StringRedisSerializer的字符串序列化
-
GenericJackson2JsonRedisSerializer:类似Jackson2JsonRedisSerializer,但使用时构造函数不用特定的类
-
OxmSerializer:提供了将javabean与xml之间的转换能力,目前可用的三方支持包括jaxb,apache-xmlbeans;redis存储的数据将是xml工具。不过使用此策略,编程将会有些难度,而且效率最低;不建议使用。【需要spring-oxm模块的支持】
- ObjectMapper介绍
ObjectMapper类是Jackson库的主要类。它提供一些功能将转换成Java对象匹配JSON结构,反之亦然。它使用JsonParser和JsonGenerator的实例实现JSON实际的读/写。
ObjectMapper objectMapper = new ObjectMapper();
/**序列化的时候序列对象的所有属性
* Include.ALWAYS 是序列化对像所有属性
* Include.NON_NULL 只有不为null的字段才被序列化
* Include.NON_EMPTY 如果为null或者 空字符串和空集合都不会被序列化
* /
objectMapper.setSerializationInclusion(Include.ALWAYS);
//反序列化的时候如果多了其他属性,不抛出异常
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
//如果是空对象的时候,不抛异常
objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
//取消时间的转化格式,默认是时间戳,可以取消,同时需要设置要表现的时间格式
objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"))
// 属性访问器可以访问任何属性,jackson的自动检测机制可以任何级别的字段都可以识别
objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY)
// 非final类型
objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL)
jackson 1.x和2.x版本的注解是放置在不同的包下的
1.x是在jackson core jar包org.codehaus.jackson.annotate下
2.x是在jackson-databind包com.fasterxml.jackson.annotation下
https://blog.csdn.net/xiaoyu411502/article/details/45001317
- 总结:
- Jdk序列化速度快,占用空间大,不易查看,通过redis命令查看类似\xAC\xED\x00\x05t\x00\x011不方便,Hash最好还是用GenericJackson2JsonRedisSerializer
- 可以通过手动配置, 将redisTemplate的序列化方式进行更改,推荐将所有Template的key都采用String的序列化方式,而value的序列化方式可以采用不同的序列化方式
- 注意:
- RedisTemplate的key指定成StringRedisSerializer序列化会报类型转换错误,如XXX类不能转换成String。
- 使用Jackson2JsonRedisSerializer序列化的时候,如果实体类上没有set方法反序列化会报错
- 对于已存在redis中的数据,如果此时重新编写redisTemplate取获取数据,则一定要确认redis中的数类型,如果不能确认的,则默认使用StringRedisTemplate。因为取redis中反序列化的结果如果和存的不一致会抛异常,尽量保证项目中的redisTemplate保持不变
- spring redis的相关配置
spring.redis.host=
spring.redis.port=
# 连接池中最少空闲的连接数
spring.redis.jedis.pool.min-idle=
# 当连接池资源耗尽时,调用者最大的阻塞时间,超出时将抛出异常。单位:ms,默认-1,表示永不超时
spring.redis.jedis.pool.max-wait=
# 连接池的最大数据库连接数。设为0表示无限制,如果是jedis 2.4以后用redis.maxTotal
spring.redis.jedis.pool.max-active=
# 连接池中最大空闲的连接数数
spring.redis.jedis.pool.max-idle=
spring.redis.database=
spring.redis.timeout=
这篇博客介绍了RedisTemplate与Jedis的区别,以及RedisTemplate和StringRedisTemplate在SpringDataRedis中的作用。RedisTemplate提供更灵活的键值对操作,而StringRedisTemplate限制为String键值对。文章还详细讨论了两种模板的序列化机制,包括JdkSerializationRedisSerializer和StringRedisSerializer,并推荐使用Jackson2JsonRedisSerializer进行序列化,以方便查看和处理数据。

1018

被折叠的 条评论
为什么被折叠?



