前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >RedisTemplate和StringRedisTemplate的区别

RedisTemplate和StringRedisTemplate的区别

作者头像
chengcheng222e
发布2021-11-04 16:33:31
1.7K0
发布2021-11-04 16:33:31
举报
文章被收录于专栏:简栈文化
一.简介

简单的说,RedisTemplateStringRedisTemplate的关系如下:

1.StringRedisTemplateRedisTemplate的子类。 2.StringRedisTemplate的各个序列化策略都是StringRedisSerializer,而RedisTemplate用的是JdkSerializationRedisSerializer

二.RedisTemplate和StringRedisTemplate的代码结构

RedisTemplate类说起。

RedisTemplate类中,定义了这样四个变量:

代码语言:javascript
复制
@Nullable
private RedisSerializer keySerializer = null;
@Nullable
private RedisSerializer valueSerializer = null;
@Nullable
private RedisSerializer hashKeySerializer = null;
@Nullable
private RedisSerializer hashValueSerializer = null;

分别代表了普通keyvalue,和Hash类型的key,value的序列化策略,可以分别设置。

另外定义变量,用来指定默认的序列化策略:

代码语言:javascript
复制
@Nullable
private RedisSerializer<?> defaultSerializer;

RedisTemplate类中,定义了afterPropertiesSet()方法,当Spring创建RedisTemplate类的对象时,会调用这个方法:

代码语言:javascript
复制
public void afterPropertiesSet() {
    super.afterPropertiesSet();
    boolean defaultUsed = false;
    if (this.defaultSerializer == null) {
        this.defaultSerializer = new JdkSerializationRedisSerializer(this.classLoader != null ? this.classLoader : this.getClass().getClassLoader());
    }

    if (this.enableDefaultSerializer) {
        if (this.keySerializer == null) {
            this.keySerializer = this.defaultSerializer;
            defaultUsed = true;
        }

        if (this.valueSerializer == null) {
            this.valueSerializer = this.defaultSerializer;
            defaultUsed = true;
        }

        if (this.hashKeySerializer == null) {
            this.hashKeySerializer = this.defaultSerializer;
            defaultUsed = true;
        }

        if (this.hashValueSerializer == null) {
            this.hashValueSerializer = this.defaultSerializer;
            defaultUsed = true;
        }
    }

    if (this.enableDefaultSerializer && defaultUsed) {
        Assert.notNull(this.defaultSerializer, "default serializer null and not all serializers initialized");
    }

    if (this.scriptExecutor == null) {
        this.scriptExecutor = new DefaultScriptExecutor(this);
    }

    this.initialized = true;
}

可以看到,在默认情况下,RedisTemplate使用的默认序列化策略是JdkSerializationRedisSerializer。包括RedisTemplate下的keyvaluehash-key,hash-value的序列化,都用这种策略。

再来看看StringRedisTemplate,他作为RedisTemplate的子类,只是修改了序列化策略:

代码语言:javascript
复制
public class StringRedisTemplate extends RedisTemplate<String, String> {
    public StringRedisTemplate() {
        RedisSerializer<String> stringSerializer = new StringRedisSerializer();
        this.setKeySerializer(stringSerializer);
        this.setValueSerializer(stringSerializer);
        this.setHashKeySerializer(stringSerializer);
        this.setHashValueSerializer(stringSerializer);
    }

    public StringRedisTemplate(RedisConnectionFactory connectionFactory) {
        this();
        this.setConnectionFactory(connectionFactory);
        this.afterPropertiesSet();
    }

    protected RedisConnection preProcessConnection(RedisConnection connection, boolean existingConnection) {
        return new DefaultStringRedisConnection(connection);
    }
}

以上就是StringRedisTemplate整个类的内容,可以看到,在他的默认构造中,keyvaluehash-keyhash-value都使用的是StringRedisSerializer类作为序列化策略。这也就是StringRedisTemplate和他的父类RedisTemplate的主要区别。

三.序列化策略

更进一步,看一下这个序列化策略是什么。

上面提到的StringRedisSerializerJdkSerializationRedisSerializer都是序列化策略类,他们都实现了一个RedisSerializer<T>接口:

代码语言:javascript
复制
public interface RedisSerializer<T> {
    @Nullable
    byte[] serialize(@Nullable T var1) throws SerializationException;

    @Nullable
    T deserialize(@Nullable byte[] var1) throws SerializationException;
}

接口表达的意思很简单,两个方法,serialize用于序列化,把对象变为byte数组,deserialize用于反序列化,把byte数组转为对象。

StringRedisSerializer

看看StringRedisSerializer是怎么做的:

1.StringRedisSerializer的构造:

代码语言:javascript
复制
public StringRedisSerializer() {
    this(StandardCharsets.UTF_8);
}

public StringRedisSerializer(Charset charset) {
    Assert.notNull(charset, "Charset must not be null!");
    this.charset = charset;
}

定义了编码格式,默认UTF_8

2.StringRedisSerializer的serialize和deserialize方法:

代码语言:javascript
复制
public String deserialize(@Nullable byte[] bytes) {
    return bytes == null ? null : new String(bytes, this.charset);
}

public byte[] serialize(@Nullable String string) {
    return string == null ? null : string.getBytes(this.charset);
}

可以看到,StringRedisSerializer采用的是字符串和对应编码下二进制数组之间的转换。

在这种编码格式下,如果我们向redis保存信息,然后用客户端访问Redis时,只要编码格式一致,就能看到保存信息的原文。保存字符串ABC,客户端看到的也是字符串ABC

JdkSerializationRedisSerializer

然后对比看看JdkSerializationRedisSerializer是怎么做的。

1.JdkSerializationRedisSerializer的构造:

代码语言:javascript
复制
private final Converter<Object, byte[]> serializer;
private final Converter<byte[], Object> deserializer;

public JdkSerializationRedisSerializer() {
    this(new SerializingConverter(), new DeserializingConverter());
}

public JdkSerializationRedisSerializer(ClassLoader classLoader) {
    this(new SerializingConverter(), new DeserializingConverter(classLoader));
}

可以看到,JdkSerializationRedisSerializer定义了两个变量,serializer和deserializer,显然是用来序列化和反序列化的,他们两个的类型是一样的,都是Converter接口,只是泛型不同。

Converter接口:

代码语言:javascript
复制
@FunctionalInterface
public interface Converter<S, T> {
        @Nullable
        T convert(S source);
}

就一个方法。

另外在JdkSerializationRedisSerializer的构造中,对serializer和deserializer进行了初始化,使用SerializingConverter和DeserializingConverter作为实现类。

2.JdkSerializationRedisSerializer的serialize和deserialize方法:

代码语言:javascript
复制
public Object deserialize(@Nullable byte[] bytes) {
    if (SerializationUtils.isEmpty(bytes)) {
        return null;
    } else {
        try {
            return this.deserializer.convert(bytes);
        } catch (Exception var3) {
            throw new SerializationException("Cannot deserialize", var3);
        }
    }
}

public byte[] serialize(@Nullable Object object) {
    if (object == null) {
        return SerializationUtils.EMPTY_ARRAY;
    } else {
        try {
            return (byte[])this.serializer.convert(object);
        } catch (Exception var3) {
            throw new SerializationException("Cannot serialize", var3);
        }
    }
}

其实就是调用了对应Converterconvert方法。

3.关于Converter

既然到这了,就再深入一步,看看SerializingConverter和DeserializingConverter的convert方法。

首先,序列化:

SerializingConverter的相关方法,贴一部分关键的:

代码语言:javascript
复制
public SerializingConverter() {
        this.serializer = new DefaultSerializer();
}

@Override
public byte[] convert(Object source) {
        ByteArrayOutputStream byteStream = new ByteArrayOutputStream(1024);
        try  {
                this.serializer.serialize(source, byteStream);
                return byteStream.toByteArray();
        }
        catch (Throwable ex) {
                throw new SerializationFailedException("Failed to serialize object using " +
                                this.serializer.getClass().getSimpleName(), ex);
        }
}

可以看到,SerializingConverter类定义了serializer变量,用DefaultSerializer类实现,序列化的方式是调用DefaultSerializerserialize方法:

代码语言:javascript
复制
@Override
public void serialize(Object object, OutputStream outputStream) throws IOException {
        if (!(object instanceof Serializable)) {
                throw new IllegalArgumentException(getClass().getSimpleName() + " requires a Serializable payload " +
                                "but received an object of type [" + object.getClass().getName() + "]");
        }
        ObjectOutputStream objectOutputStream = new ObjectOutputStream(outputStream);
        objectOutputStream.writeObject(object);
        objectOutputStream.flush();
}

DefaultSerializerserialize方法使用了ObjectOutputStream,调用writeObject方法序列化对象。

对应的,反序列化:

DeserializingConverter的convert方法,贴一下相关代码:

代码语言:javascript
复制
public DeserializingConverter() {
        this.deserializer = new DefaultDeserializer();
}

@Override
public Object convert(byte[] source) {
        ByteArrayInputStream byteStream = new ByteArrayInputStream(source);
        try {
                return this.deserializer.deserialize(byteStream);
        }
        catch (Throwable ex) {
                throw new SerializationFailedException("Failed to deserialize payload. " +
                                "Is the byte array a result of corresponding serialization for " +
                                this.deserializer.getClass().getSimpleName() + "?", ex);
        }
}

可见DeserializingConverter使用了DefaultDeserializer作为反序列化工具,调用了他的deserialize方法:

代码语言:javascript
复制
@Override
@SuppressWarnings("resource")
public Object deserialize(InputStream inputStream) throws IOException {
        ObjectInputStream objectInputStream = new ConfigurableObjectInputStream(inputStream, this.classLoader);
        try {
                return objectInputStream.readObject();
        }
        catch (ClassNotFoundException ex) {
                throw new NestedIOException("Failed to deserialize object type", ex);
        }
}

对比SerializingConverterDeserializingConverter使用的是ConfigurableObjectInputStream,并调用他的readObject方法进行反序列化。

这种序列化方式,如果保存信息至redis,用客户端查看时,保存的信息看起来像是在原来的字符前面加了几个字符。

比如:

代码语言:javascript
复制
JdkSerializationRedisSerializer jdkSerializer = new JdkSerializationRedisSerializer();
StringRedisSerializer stringSerializer = new StringRedisSerializer();
byte[] jdkByteArr = jdkSerializer.serialize("CSDN博客");
byte[] stringByteArr = stringSerializer.serialize("CSDN博客");

这种情况下,得到的byte数组是:

jdkByteArr

{-84,-19,0,5,116,0,10,67,83,68,78,-27,-115,-102,-27,-82,-94}

stringByteArr:

{67,83,68,78,-27,-115,-102,-27,-82,-94}

StringRedisSerializer把字符串本身转化成byte数组,而JdkSerializationRedisSerializer在数组前面加了几个字符,这些字符也会被保存到redis中。

所以,从数据上来说,这两种序列化策略处理的数据是不会共通的,各人管各人的。

四.关于redisTemplate的Operations

使用redisTemplate时,除了调用execute方法并自定义RedisCallback之外,还可以使用redisTemplate提供的几个Operations接口。

redisTemplate中定义了以下几个Operations

代码语言:javascript
复制
@Nullable
private ValueOperations<K, V> valueOps;
@Nullable
private ListOperations<K, V> listOps;
@Nullable
private SetOperations<K, V> setOps;
@Nullable
private ZSetOperations<K, V> zSetOps;
@Nullable
private GeoOperations<K, V> geoOps;
@Nullable
private HyperLogLogOperations<K, V> hllOps;

这几个Operations接口,分别提供了对不同种类数据的操作方法。

ValueOperations为例,他提供的方法有:

代码语言:javascript
复制
void set(K var1, V var2);

void set(K var1, V var2, long var3, TimeUnit var5);

@Nullable
Boolean setIfAbsent(K var1, V var2);

void multiSet(Map<? extends K, ? extends V> var1);

@Nullable
Boolean multiSetIfAbsent(Map<? extends K, ? extends V> var1);

@Nullable
V get(Object var1);

@Nullable
V getAndSet(K var1, V var2);

@Nullable
List<V> multiGet(Collection<K> var1);

@Nullable
Long increment(K var1, long var2);

@Nullable
Double increment(K var1, double var2);

@Nullable
Integer append(K var1, String var2);

@Nullable
String get(K var1, long var2, long var4);

void set(K var1, V var2, long var3);

@Nullable
Long size(K var1);

@Nullable
Boolean setBit(K var1, long var2, boolean var4);

@Nullable
Boolean getBit(K var1, long var2);

其他的Operations提供的方法各有不同,但是这些Operations的使用方式都是相同的。

不同的Operations分别通过RedisTemplate的以下方法获取:

代码语言:javascript
复制
public ValueOperations<K, V> opsForValue() {
    if (this.valueOps == null) {
        this.valueOps = new DefaultValueOperations(this);
    }

    return this.valueOps;
}

public ListOperations<K, V> opsForList() {
    if (this.listOps == null) {
        this.listOps = new DefaultListOperations(this);
    }

    return this.listOps;
}

public SetOperations<K, V> opsForSet() {
    if (this.setOps == null) {
        this.setOps = new DefaultSetOperations(this);
    }

    return this.setOps;
}

public ZSetOperations<K, V> opsForZSet() {
    if (this.zSetOps == null) {
        this.zSetOps = new DefaultZSetOperations(this);
    }

    return this.zSetOps;
}

public GeoOperations<K, V> opsForGeo() {
    if (this.geoOps == null) {
        this.geoOps = new DefaultGeoOperations(this);
    }

    return this.geoOps;
}

可见,在这些获得Operations的方法中,都提供了一个默认实现类,并且把RedisTemplate对象本身当做参数传给了这个实现类。

还是以ValueOperations为例,RedisTemplate提供的默认实现类是DefaultValueOperations,看看这个类的源码:

代码语言:javascript
复制
package org.springframework.data.redis.core;

import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.TimeUnit;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.AbstractOperations.ValueDeserializingRedisCallback;

class DefaultValueOperations<K, V> extends AbstractOperations<K, V> implements ValueOperations<K, V> {
    DefaultValueOperations(RedisTemplate<K, V> template) {
        super(template);
    }

    public V get(Object key) {
        return this.execute(new AbstractOperations<K, V>.ValueDeserializingRedisCallback(key) {
            protected byte[] inRedis(byte[] rawKey, RedisConnection connection) {
                return connection.get(rawKey);
            }
        }, true);
    }

    public V getAndSet(K key, V newValue) {
        final byte[] rawValue = this.rawValue(newValue);
        return this.execute(new AbstractOperations<K, V>.ValueDeserializingRedisCallback(key) {
            protected byte[] inRedis(byte[] rawKey, RedisConnection connection) {
                return connection.getSet(rawKey, rawValue);
            }
        }, true);
    }

    public Long increment(K key, long delta) {
        byte[] rawKey = this.rawKey(key);
        return (Long)this.execute((connection) -> {
            return connection.incrBy(rawKey, delta);
        }, true);
    }

    public Double increment(K key, double delta) {
        byte[] rawKey = this.rawKey(key);
        return (Double)this.execute((connection) -> {
            return connection.incrBy(rawKey, delta);
        }, true);
    }

    public Integer append(K key, String value) {
        byte[] rawKey = this.rawKey(key);
        byte[] rawString = this.rawString(value);
        return (Integer)this.execute((connection) -> {
            Long result = connection.append(rawKey, rawString);
            return result != null ? result.intValue() : null;
        }, true);
    }

    public String get(K key, long start, long end) {
        byte[] rawKey = this.rawKey(key);
        byte[] rawReturn = (byte[])this.execute((connection) -> {
            return connection.getRange(rawKey, start, end);
        }, true);
        return this.deserializeString(rawReturn);
    }

    public List<V> multiGet(Collection<K> keys) {
        if (keys.isEmpty()) {
            return Collections.emptyList();
        } else {
            byte[][] rawKeys = new byte[keys.size()][];
            int counter = 0;

            Object hashKey;
            for(Iterator var4 = keys.iterator(); var4.hasNext(); rawKeys[counter++] = this.rawKey(hashKey)) {
                hashKey = var4.next();
            }

            List<byte[]> rawValues = (List)this.execute((connection) -> {
                return connection.mGet(rawKeys);
            }, true);
            return this.deserializeValues(rawValues);
        }
    }

    public void multiSet(Map<? extends K, ? extends V> m) {
        if (!m.isEmpty()) {
            Map<byte[], byte[]> rawKeys = new LinkedHashMap(m.size());
            Iterator var3 = m.entrySet().iterator();

            while(var3.hasNext()) {
                Entry<? extends K, ? extends V> entry = (Entry)var3.next();
                rawKeys.put(this.rawKey(entry.getKey()), this.rawValue(entry.getValue()));
            }

            this.execute((connection) -> {
                connection.mSet(rawKeys);
                return null;
            }, true);
        }
    }

    public Boolean multiSetIfAbsent(Map<? extends K, ? extends V> m) {
        if (m.isEmpty()) {
            return true;
        } else {
            Map<byte[], byte[]> rawKeys = new LinkedHashMap(m.size());
            Iterator var3 = m.entrySet().iterator();

            while(var3.hasNext()) {
                Entry<? extends K, ? extends V> entry = (Entry)var3.next();
                rawKeys.put(this.rawKey(entry.getKey()), this.rawValue(entry.getValue()));
            }

            return (Boolean)this.execute((connection) -> {
                return connection.mSetNX(rawKeys);
            }, true);
        }
    }

    public void set(K key, V value) {
        final byte[] rawValue = this.rawValue(value);
        this.execute(new AbstractOperations<K, V>.ValueDeserializingRedisCallback(key) {
            protected byte[] inRedis(byte[] rawKey, RedisConnection connection) {
                connection.set(rawKey, rawValue);
                return null;
            }
        }, true);
    }

    public void set(K key, V value, final long timeout, final TimeUnit unit) {
        final byte[] rawKey = this.rawKey(key);
        final byte[] rawValue = this.rawValue(value);
        this.execute(new RedisCallback<Object>() {
            public Object doInRedis(RedisConnection connection) throws DataAccessException {
                this.potentiallyUsePsetEx(connection);
                return null;
            }

            public void potentiallyUsePsetEx(RedisConnection connection) {
                if (!TimeUnit.MILLISECONDS.equals(unit) || !this.failsafeInvokePsetEx(connection)) {
                    connection.setEx(rawKey, TimeoutUtils.toSeconds(timeout, unit), rawValue);
                }

            }

            private boolean failsafeInvokePsetEx(RedisConnection connection) {
                boolean failed = false;

                try {
                    connection.pSetEx(rawKey, timeout, rawValue);
                } catch (UnsupportedOperationException var4) {
                    failed = true;
                }

                return !failed;
            }
        }, true);
    }

    public Boolean setIfAbsent(K key, V value) {
        byte[] rawKey = this.rawKey(key);
        byte[] rawValue = this.rawValue(value);
        return (Boolean)this.execute((connection) -> {
            return connection.setNX(rawKey, rawValue);
        }, true);
    }

    public void set(K key, V value, long offset) {
        byte[] rawKey = this.rawKey(key);
        byte[] rawValue = this.rawValue(value);
        this.execute((connection) -> {
            connection.setRange(rawKey, rawValue, offset);
            return null;
        }, true);
    }

    public Long size(K key) {
        byte[] rawKey = this.rawKey(key);
        return (Long)this.execute((connection) -> {
            return connection.strLen(rawKey);
        }, true);
    }

    public Boolean setBit(K key, long offset, boolean value) {
        byte[] rawKey = this.rawKey(key);
        return (Boolean)this.execute((connection) -> {
            return connection.setBit(rawKey, offset, value);
        }, true);
    }

    public Boolean getBit(K key, long offset) {
        byte[] rawKey = this.rawKey(key);
        return (Boolean)this.execute((connection) -> {
            return connection.getBit(rawKey, offset);
        }, true);
    }
}

所有Operations实现类都是AbstractOperations的子类,另外各自实现各自的接口。

实现类的方法中多数都是调用了this.execute()方法,这个方法在父类AbstractOperations中,最终调用的其实也是RedisTemplateexecute()方法。

以上面DefaultValueOperationsset()方法为例,看一下代码:

代码语言:javascript
复制
public void set(K key, V value) {
    final byte[] rawValue = this.rawValue(value);
    this.execute(new AbstractOperations<K, V>.ValueDeserializingRedisCallback(key) {
        protected byte[] inRedis(byte[] rawKey, RedisConnection connection) {
            connection.set(rawKey, rawValue);
            return null;
        }
    }, true);
}

首先是对value的处理,调用this.rawValue()方法,把value序列化成byte数组,这个方法在父类AbstractOperations中:

代码语言:javascript
复制
byte[] rawValue(Object value) {
    return this.valueSerializer() == null && value instanceof byte[] ? (byte[])((byte[])value) : this.valueSerializer().serialize(value);
}

可见,代码用的是自己的valueSerializer来序列化value,这个valueSerializer来自RedisTemplate

回到set()方法,value序列化完成后,调用this.execute()方法,给此方法传递的第一个参数是:

代码语言:javascript
复制
new AbstractOperations<K, V>.ValueDeserializingRedisCallback(key) {
    protected byte[] inRedis(byte[] rawKey, RedisConnection connection) {
        connection.set(rawKey, rawValue);
        return null;
    }
}

这个参数实际上是一个ValueDeserializingRedisCallback对象,在其中定义了inRedis()方法的实现。

this.execute()方法在父类AbstractOperations中:

代码语言:javascript
复制
@Nullable
<T> T execute(RedisCallback<T> callback, boolean b) {
    return this.template.execute(callback, b);
}

其中this.template指的就是初始化时传入的RedisTemplate,其execute()方法是这样的:

代码语言:javascript
复制
@Nullable
public <T> T execute(RedisCallback<T> action, boolean exposeConnection) {
    return this.execute(action, exposeConnection, false);
}

然后调用下面的方法:

代码语言:javascript
复制
@Nullable
public <T> T execute(RedisCallback<T> action, boolean exposeConnection, boolean pipeline) {
    Assert.isTrue(this.initialized, "template not initialized; call afterPropertiesSet() before using it");
    Assert.notNull(action, "Callback object must not be null");
    RedisConnectionFactory factory = this.getRequiredConnectionFactory();
    RedisConnection conn = null;

    Object var11;
    try {
        if (this.enableTransactionSupport) {
            conn = RedisConnectionUtils.bindConnection(factory, this.enableTransactionSupport);
        } else {
            conn = RedisConnectionUtils.getConnection(factory);
        }

        boolean existingConnection = TransactionSynchronizationManager.hasResource(factory);
        RedisConnection connToUse = this.preProcessConnection(conn, existingConnection);
        boolean pipelineStatus = connToUse.isPipelined();
        if (pipeline && !pipelineStatus) {
            connToUse.openPipeline();
        }

        RedisConnection connToExpose = exposeConnection ? connToUse : this.createRedisConnectionProxy(connToUse);
        T result = action.doInRedis(connToExpose);
        if (pipeline && !pipelineStatus) {
            connToUse.closePipeline();
        }

        var11 = this.postProcessResult(result, connToUse, existingConnection);
    } finally {
        RedisConnectionUtils.releaseConnection(conn, factory);
    }

    return var11;
}

方法初始化了RedisConnection,最后面调用了RedisCallbackdoInRedis()方法,也就是这一行:

代码语言:javascript
复制
T result = action.doInRedis(connToExpose);

这里的变量action就是在set()方法中自定义的new AbstractOperations<K, V>.ValueDeserializingRedisCallback(key)

ValueDeserializingRedisCallback类是AbstractOperations的内部抽象类,他的doInRedis()方法是这样的:

代码语言:javascript
复制
public final V doInRedis(RedisConnection connection) {
    byte[] result = this.inRedis(AbstractOperations.this.rawKey(this.key), connection);
    return AbstractOperations.this.deserializeValue(result);
}

可见调用了inRedis()方法,其第一个参数是序列化后的key,调用的是AbstractOperationsrawKey()方法,代码如下:

代码语言:javascript
复制
byte[] rawKey(Object key) {
    Assert.notNull(key, "non null key required");
    return this.keySerializer() == null && key instanceof byte[] ? (byte[])((byte[])key) : this.keySerializer().serialize(key);
}

这里把key进行序列化,keySerializer()方法从RedisTemplate中获取keySerializer,并由keySerializerkey进行序列化。

ValueDeserializingRedisCallback类中的inRedis()方法是抽象方法,具体的实现在DefaultValueOperationsset()方法中,也就是这一部分:

代码语言:javascript
复制
protected byte[] inRedis(byte[] rawKey, RedisConnection connection) {
    connection.set(rawKey, rawValue);
    return null;
}

最终调用的是RedisConnectionset()方法,完成Redisset操作。

以上就是在RedisTemplate中使用ValueOperations进行set操作的全部代码流程。

Redis的不同操作分散在RedisTemplate的不同Operations中,只是调用的方法不同,调用流程都差不多。

参考地址
  • https://blog.csdn.net/lkforce/article/details/103685707

如果大家喜欢我的文章,可以关注个人订阅号。欢迎随时留言、交流。如果想加入微信群的话一起讨论的话,请加管理员微信号:chengcheng222e,他会拉你们进群。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-11-10,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 简栈文化 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一.简介
  • 二.RedisTemplate和StringRedisTemplate的代码结构
  • 三.序列化策略
    • StringRedisSerializer
      • JdkSerializationRedisSerializer
      • 四.关于redisTemplate的Operations
      • 参考地址
      相关产品与服务
      云数据库 Redis®
      腾讯云数据库 Redis®(TencentDB for Redis®)是腾讯云打造的兼容 Redis 协议的缓存和存储服务。丰富的数据结构能帮助您完成不同类型的业务场景开发。支持主从热备,提供自动容灾切换、数据备份、故障迁移、实例监控、在线扩容、数据回档等全套的数据库服务。
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档