RedisTemplate操作Redis详解之连接Redis及自定义序列化

2024-05-13 1492阅读

连接到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异常层次结构,以便您可以在不更改任何代码的情况下切换连接器,因为操作语义保持不变。

当按照上篇文档配置好Redis后,IOC会加载ConnectionFactory,我们可以直接注入,然后创建连接操作Redis。

RedisConnection提供了Redis 各大数据类型的操作API:

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;
    }
}
    @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接口),如下表所述:

界面 描述
按键类型操作
GeoOperationsRedis的地理空间操作的,比如GEOADD,GEORADIUS...
HashOperationsRedis哈希操作
HyperLogLogOperationsRedis的HyperLogLog操作,例如PFADD,PFCONT,...
ListOperationsRedis列表操作
SetOperationsRedis设置操作
ValueOperationsRedis字符串(或值)操作
ZSetOperationsRedis zset(或排序集)操作
关键绑定操作
BoundGeoOperationsRedis键绑定地理空间操作
BoundHashOperationsRedis哈希键绑定操作
BoundKeyOperationsRedis按键绑定操作
BoundListOperationsRedis列表键绑定操作
BoundSetOperations

Redis设置键绑定操作

BoundValueOperationsRedis字符串(或值)键绑定操作
BoundZSetOperationsRedis zset(或排序集)键绑定操作

序列化器

自带序列化器

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。

    框架自带各种序列化器:

    RedisTemplate操作Redis详解之连接Redis及自定义序列化

    名称说明
    OxmSerializer通过Spring OXM支持将其用于对象/XML映射
    ByteArrayRedisSerializerByte数组序列化
    GenericJackson2JsonRedisSerializer以JSON格式去存储数据,会保存序列化的对象的包名和类名,反序列化时以这个作为标示就可以反序列化成指定的对象。效率低,占用内存高
    GenericToStringSerializer可以将任何对象泛化为字符串并序列化
    StringRedisSerializer简单的字符串序列化
    JdkSerializationRedisSerializerJDK序列化,默认用于RedisCache和RedisTemplate
    Jackson2JsonRedisSerializer以JSON格式去存储数据,需要指明序列化的类Class,可以使用Object.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;

        
                  io.protostuff
                  protostuff-runtime
                  1.7.4
              
              
                  io.protostuff
                  protostuff-core
                  1.7.4
              
              
                  org.projectlombok
                  lombok
              

      1、 实现RedisSerializer接口;

      @Slf4j
      public class ProtoStuffRedisSerializer implements RedisSerializer {
         
           
          // RuntimeSchema是一个包含业务对象所有信息的类,包括类信息、字段信息
          private static final Schema 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 protoStuffWrapper = new ProtoStuffWrapper();
                  // 反序列
                  ProtostuffIOUtil.mergeFrom(bytes, protoStuffWrapper, schema);
                  return protoStuffWrapper.getT();
              } catch (Exception e) {
         
           
                  throw new RuntimeException(e);
              }
          }
          /**
           * 序列化包装类,深度克隆,避免无法获取schema
           *
           * @param  业务对象
           */
          public static class ProtoStuffWrapper 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 clone() {
         
           
                  try {
         
           
                      return (ProtoStuffWrapper) super.clone();
                  } catch (CloneNotSupportedException e) {
         
           
                      return new ProtoStuffWrapper();
                  }
              }
          }
      }

      1、 创建RedisTemplate,设置序列化;

       /**
           * 创建RedisTemplate
           *
           * @param redisConnectionFactory 连接工厂
           * @param                     值类型
           * @return RedisTemplate
           */
          @Bean(name = "redisTemplate")
          public  RedisTemplate redisTemplate(RedisConnectionFactory redisConnectionFactory) {
         
           
              RedisTemplate redisTemplate = new RedisTemplate();
              // 设置连接工厂
              redisTemplate.setConnectionFactory(redisConnectionFactory);
              // String序列化对象
              RedisSerializer stringRedisSerializer = RedisSerializer.string();
              // ProtoStuff序列化
              ProtoStuffRedisSerializer 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;
          }

      1、 添加测试实体类;

      @ToString
      @Data
      public class User {
         
           
          String userName;
          String password;
          int age;
      }

      1、 添加测试类测试;

      @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());
          }

      RedisTemplate操作Redis详解之连接Redis及自定义序列化

VPS购买请点击我

免责声明:我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理! 图片声明:本站部分配图来自人工智能系统AI生成,觅知网授权图片,PxHere摄影无版权图库和百度,360,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们,邮箱:ciyunidc@ciyunshuju.com。本站只作为美观性配图使用,无任何非法侵犯第三方意图,一切解释权归图片著作权方,本站不承担任何责任。如有恶意碰瓷者,必当奉陪到底严惩不贷!

目录[+]