zoukankan      html  css  js  c++  java
  • 深入理解Spring Redis的使用 (三)、使用RedisTemplate的操作类访问Redis

    上一篇说了RedisTemplate对注解事务的支持,以及提供的序列化器。

    事务需要开启enableTransactionSupport,然后使用@transactional注解,里面直接通过回调的connection,就不需要自己进行multi和exec的事务开启提交了。但是通过回调去获取connection,完全没有达到一个模版类的功能。所以这篇我们会讲下几种Operations接口提供的方法。

        private ValueOperations<K, V> valueOps;
        private ListOperations<K, V> listOps;
        private SetOperations<K, V> setOps;
        private ZSetOperations<K, V> zSetOps;

    1. RedisOperations接口说明

    这个接口的实现类就是RedisTemplate本身,主要提供了一些对Redis键,事务,运行脚本等命令的支持,不负责数据的读写。

    我们选一段代码看下:

        public void watch(K key) {
            final byte[] rawKey = rawKey(key);
    
            execute(new RedisCallback<Object>() {
    
                public Object doInRedis(RedisConnection connection) {
                    connection.watch(rawKey);
                    return null;
                }
            }, true);
        }

    这个是事务的监视命令,可以看出,里面的实现也是用的回调RedisCallback。这些api都是通过connection的api来进行了封装。

    2. ValueOperations接口说明

    这个接口的实现类为DefaultValueOperations,default这个类同时继承AbstractOperation,我们来看下这个类的构造函数:

        DefaultValueOperations(RedisTemplate<K, V> template) {
            super(template);
        }

    非公开的,需要传入template来构造。但是我们是无法访问的。不过不要急,在RedisTemplate中,已经提供了一个工厂方法:opsForValue()。这个方法会返回一个默认的操作类。另外,我们可以直接通过注解@Resource(name = "redisTemplate")来进行注入。

        @Resource(name = "redisTemplate")
        private ValueOperations<String, Object> vOps;

    是不是很奇怪,毫无父子兄弟关系的两个类,怎么能互相注入呢?这个是Spring的Editor机制,搜索下ValueOperationsEditor这个类就知道了,Spring在注入的时候调用了Editor的setValue方法。了解Spring源码的应该知道。我也是看别人的文章才理解的。文章地址

    其实除了可以通过template注入ValueOperations,还可以注入 上面的其他几种operations以及HashOperations.

    DefaultValueOperations提供了所有Redis字符串类型的操作api。比如set,get,incr等等。使用这些方法,可以方便的直接存储任意的java类型,而不需要自己去将存储的东西序列化以及反序列化。

    注意:泛型的类型,以及序列化器都是来自RedisTemplate。如果要自行进行json或者其他的序列化,就需要在RedisTemplate中进行更改。

    另外,对于成员listOps,setOps,zSetOps这接个操作类,就不再赘述,原理同ValueOperations,是其他几种数据类型的实现。

    3. HashOperations接口说明

    这个接口并没有定义成员变量,猜测是因为对于Hash来说,又增加了额外的Key和Value,泛型无法在成员前额外定义,所以直接提供了方法。不过所幸里面用的是JdkSerializer,所以这个定义了什么类型的泛型都不会产生运行异常。

        public void put(K key, HK hashKey, HV value) {
            final byte[] rawKey = rawKey(key);
            final byte[] rawHashKey = rawHashKey(hashKey);
            final byte[] rawHashValue = rawHashValue(value);
    
            execute(new RedisCallback<Object>() {
    
                public Object doInRedis(RedisConnection connection) {
                    connection.hSet(rawKey, rawHashKey, rawHashValue);
                    return null;
                }
            }, true);
        }

    这个是基本的put方法,可以看出key和hashkey这两个,调用了不同的序列化方法。进行方法查看,看到序列化hashkey用的是template里的hashkeyserializer,默认是jdkserializer,这个会导致在redis控制台,看不出来存了什么key。如果不喜欢,可以通过redistemplate.sethashkeyserializer()来进行设置。

     对于hash结构所有的api,也都在这个类里进行了封装,比如hset变为了put,hget变为get。需要自行去查看api。不要被误导。

    4. 总结

    到这里为止,已经把基本的使用都说完了。说的很粗糙,只是把我觉得容易出现误解的点进行了重点说明,基础的操作还需要大家自己稍微看下。权作一个抛砖引玉的作用吧。接下来,可能会总结下在这两个月用Redis遇到的一些问题进行说明。

    我把代码放在了git上,地址是https://github.com/55375829/learn,里面spjedis就是当时自己学习时候建的项目。

  • 相关阅读:
    知识点拾遗——装饰器
    知识点拾遗——函数部分
    re模块和分组
    re模块进阶
    面向对象总结
    模块总结整理
    项目目录结构
    日志(模块logging)
    位、字节、字符 概念
    socketserver实现并发通讯
  • 原文地址:https://www.cnblogs.com/luochengqiuse/p/4641256.html
Copyright © 2011-2022 走看看