Redis进阶
01、Redis进阶:Nosql数据库简介
02、Redis进阶:多种方式安装Redis6.2.2
03、Redis进阶:Redis常用五大数据类型
04、Redis进阶:Redis三种特殊数据类型之Bitmaps、HyperLogLog、Geospatial
05、Redis进阶:Redis持久化规则之RDB及AOF
06、Redis进阶:Redis发布订阅及SpringBoot集成Redis实现发布订阅消息
07、Redis进阶:Redis事务详解
08、Redis进阶:Redis之主从复制详解
09、Redis进阶:Redis之哨兵模式(sentinel)详解
10、Redis进阶:Redis集群搭建
11、Redis进阶:Redis6新特性
12、Redis进阶:SpringBoot集成Redis环境搭建及配置详解
13、Redis进阶:RedisTemplate操作Redis详解之连接Redis及自定义序列化
14、Redis进阶:RedisTemplate操作Redis之API详解
15、Redis进阶:Redis之面试常问缓存穿透+缓存击穿+缓存雪崩
本文档使用 MrDoc 发布
-
+
首页
13、Redis进阶:RedisTemplate操作Redis详解之连接Redis及自定义序列化
### 连接到Redis ------------ 使用Redis和Spring时的首要任务之一是通过IoC容器连接到Redis。为此,需要Java连接器(或绑定)。无论选择哪种库,您都只需要使用一组Spring Data Redis API(在所有连接器中行为一致):org.springframework.data.redis.connection软件包及其RedisConnection与RedisConnectionFactory接口,用于处理和检索与Redis的活动连接。 **RedisConnection和RedisConnectionFactory** RedisConnection提供了Redis通信的核心构建块,因为它处理与Redis后端的通信。它还会自动将基础连接库异常转换为Spring一致的DAO异常层次结构,以便您可以在不更改任何代码的情况下切换连接器,因为操作语义保持不变。 当按照上篇文档配置好Redi后,IOC会加载ConnectionFactory,我们可以直接注入,然后创建连接操作Redis。 RedisConnection提供了Redis各大数据类型的操作API: ```c public interface RedisConnection extends RedisCommands, AutoCloseable { default RedisGeoCommands geoCommands() { return this; } default RedisHashCommands hashCommands() { return this; } default RedisHyperLogLogCommands hyperLogLogCommands() { return this; } default RedisKeyCommands keyCommands() { return this; } default RedisListCommands listCommands() { return this; } default RedisSetCommands setCommands() { return this; } default RedisScriptingCommands scriptingCommands() { return this; } default RedisServerCommands serverCommands() { return this; } default RedisStreamCommands streamCommands() { return this; } default RedisStringCommands stringCommands() { return this; } default RedisZSetCommands zSetCommands() { return this; } } ``` ```c @Autowired LettuceConnectionFactory lettuceConnectionFactory; @Test void lettuceConnectionFactoryTest() { RedisConnection connection = lettuceConnectionFactory.getConnection(); Boolean result = connection.set("k".getBytes(), "1".getBytes()); System.err.println(result); byte[] bytes = connection.get("k".getBytes()); assert bytes != null; System.err.println("k:" + new String(bytes)); } ``` **RedisTemplate简介** 大多数用户可能会使用RedisTemplate及其相应的软件包org.springframework.data.redis.core。实际上,由于模板具有丰富的功能集,因此它是Redis模块的中心类。该模板为Redis交互提供了高级抽象。虽然RedisConnection提供了接受和返回二进制值(byte数组)的低级方法,但是模板负责序列化和连接管理,使用户无需处理此类细节。 此外,该模板提供了操作视图(根据Redis命令参考进行分组),提供了丰富的,通用的接口,用于针对某种类型或某些键(通过KeyBound接口),如下表所述:  ### 序列化器 **自带序列化器** RedisTemplate大多数操作都使用基于Java的序列化器。这意味着模板编写或读取的任何对象都将通过Java进行序列化和反序列化。您可以在模板上更改序列化机制,Redis模块提供了几种实现,可在org.springframework.data.redis.serializer软件包中找到,您还可以将任何序列化器设置为null,并通过将enableDefaultSerializer属性设置为来将RedisTemplate与原始字节数组一起使用false。请注意,模板要求所有键都不为空。但是,只要基础串行器接受这些值,它们就可以为空。 从框架的角度来看,Redis中存储的数据仅为字节。尽管Redis本身支持各种类型,但在大多数情况下,它们是指数据的存储方式而不是数据的表示方式。由用户决定是否将信息转换为字符串或任何其他对象。 在Spring Data中,用户(自定义)类型和原始数据之间的转换(反之亦然)在org.springframework.data.redis.serializer包中的Redis中进行处理。 该软件包包含两种类型的序列化器,它们负责序列化过程: - 基于的两路串行器RedisSerializer。 - 使用RedisElementReader和的元素读取器和写入器RedisElementWriter。 **框架自带各种序列化器:**  | 名称 | 说明 | | --- | --- | OxmSerializer |通过Spring OXM支持将其用于对象/ XML映射 ByteArrayRedisSerializer |Byte数组序列化 GenericJackson2JsonRedisSerializer |以JSON格式去存储数据,会保存序列化的对象的包名和类名,反序列化时以这个作为标示就可以反序列化成指定的对象。效率低,占用内存高 GenericToStringSerializer |可以将任何对象泛化为字符串并序列化 StringRedisSerializer |简单的字符串序列化 JdkSerializationRedisSerializer |JDK序列化, 默认用于RedisCache和RedisTemplate Jackson2JsonRedisSerializer |以JSON格式去存储数据 ,需要指明序列化的类Class,可以使用Obejct.class ### 自定义序列化器 RedisTemplate 默认使用JDK序列化,可以使用自带其他的序列化,或者自己实现第三方序列化方式,比如: - google:Protobuf - faceBook:Thrift - kryo - hessian - fst - Jackson - Gson - FastJson **Protobuf序列化** ProtoBuf (Google Protocol Buffer)是由google公司用于数据交换的序列结构化数据格式,具有跨平台、跨语言、可扩展特性,类型于常用的XML及JSON,但具有更小的传输体积、更高的编码、解码能力,特别适合于数据存储、网络数据传输等对存储体积、实时性要求高的领域。 **优点**:性能好,效率高。支持向后兼容和向前兼容。支持多种编程语言(java,c++,python); **缺点**:二进制格式导致可读性差(二进制格式) **RedisTemplate使用 Protobuf** 1、 添加pom; ```c <dependency> <groupId>io.protostuff</groupId> <artifactId>protostuff-runtime</artifactId> <version>1.7.4</version> </dependency> <dependency> <groupId>io.protostuff</groupId> <artifactId>protostuff-core</artifactId> <version>1.7.4</version> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency> ``` 实现RedisSerializer接口; ```c @Slf4j public class ProtoStuffRedisSerializer<T> implements RedisSerializer<T> { // RuntimeSchema是一个包含业务对象所有信息的类,包括类信息、字段信息 private static final Schema<ProtoStuffWrapper> schema = RuntimeSchema.getSchema(ProtoStuffWrapper.class); /** * 序列化:对象=》字节数组 * * @param t 需要序列化的对象t * @return 二进制 * @throws SerializationException 序列化异常 */ @Override public byte[] serialize(T t) throws SerializationException { if (t == null) { return null; } // 开辟了512字节缓存,用来存放业务对象序列化之后存放的地方,如果空间不足,会自动扩展扩展 LinkedBuffer buffer = LinkedBuffer.allocate(LinkedBuffer.DEFAULT_BUFFER_SIZE); byte[] bytes; try { // 序列化 bytes = ProtostuffIOUtil.toByteArray(new ProtoStuffWrapper<>(t), schema, buffer); } finally { buffer.clear(); } return bytes; } /** * 反序列化 字节数组=》对象 * * @param bytes 字节数组 * @return 对象 * @throws SerializationException 序列化异常 */ @Override public T deserialize(byte[] bytes) throws SerializationException { if (bytes == null || bytes.length == 0) { return null; } try { ProtoStuffWrapper<T> protoStuffWrapper = new ProtoStuffWrapper<>(); // 反序列 ProtostuffIOUtil.mergeFrom(bytes, protoStuffWrapper, schema); return protoStuffWrapper.getT(); } catch (Exception e) { throw new RuntimeException(e); } } /** * 序列化包装类,深度克隆,避免无法获取schema * * @param <T> 业务对象 */ public static class ProtoStuffWrapper<T> implements Cloneable { private T t; ProtoStuffWrapper() { } ProtoStuffWrapper(T t) { this.t = t; } public T getT() { return t; } public void setT(T t) { this.t = t; } @Override @SuppressWarnings("unchecked") public ProtoStuffWrapper<T> clone() { try { return (ProtoStuffWrapper<T>) super.clone(); } catch (CloneNotSupportedException e) { return new ProtoStuffWrapper<T>(); } } } } ``` 创建RedisTemplate,设置序列化; ``` /** * 创建RedisTemplate * * @param redisConnectionFactory 连接工厂 * @param <T> 值类型 * @return RedisTemplate */ @Bean(name = "redisTemplate") public <T> RedisTemplate<String, T> redisTemplate(RedisConnectionFactory redisConnectionFactory) { RedisTemplate<String, T> redisTemplate = new RedisTemplate<>(); // 设置连接工厂 redisTemplate.setConnectionFactory(redisConnectionFactory); // String序列化对象 RedisSerializer<String> stringRedisSerializer = RedisSerializer.string(); // ProtoStuff序列化 ProtoStuffRedisSerializer<T> protoStuffRedisSerializer = new ProtoStuffRedisSerializer<>(); // 序列化配置=>Key redisTemplate.setKeySerializer(stringRedisSerializer); // 所有Key都设置为字符串,方便阅读 redisTemplate.setHashKeySerializer(protoStuffRedisSerializer); // 设置Hash数据结构中的Key // 序列化配置=>Value redisTemplate.setValueSerializer(protoStuffRedisSerializer); // 所有Value redisTemplate.setHashValueSerializer(protoStuffRedisSerializer); // Hash数据结构中的Value redisTemplate.afterPropertiesSet(); return redisTemplate; } ``` 添加测试实体类; ```c @ToString @Data public class User { String userName; String password; int age; } ``` 添加测试类测试; ```c @Test void protoStuffTest() { User user = new User(); user.setAge(20); user.setUserName("韩梅梅"); user.setPassword("123456"); redisTemplate.boundValueOps("k").set(user); User user1 = redisTemplate.boundValueOps("k").get(); redisTemplate.boundHashOps("hash").putIfAbsent("kkk","vvv"); System.err.println(user1.toString()); } ``` 
李智
2025年3月17日 13:34
转发文档
收藏文档
上一篇
下一篇
手机扫码
复制链接
手机扫一扫转发分享
复制链接
Markdown文件
分享
链接
类型
密码
更新密码