闲话不说,直接上代码
一、RedisTemplate
/*
* Copyright 2011-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.redis.core;
import java.io.Closeable;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import org.springframework.beans.factory.BeanClassLoaderAware;
import org.springframework.dao.InvalidDataAccessApiUsageException;
import org.springframework.data.redis.RedisSystemException;
import org.springframework.data.redis.connection.DataType;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.RedisKeyCommands;
import org.springframework.data.redis.connection.RedisServerCommands;
import org.springframework.data.redis.connection.RedisTxCommands;
import org.springframework.data.redis.connection.RedisZSetCommands.Tuple;
import org.springframework.data.redis.connection.SortParameters;
import org.springframework.data.redis.core.ZSetOperations.TypedTuple;
import org.springframework.data.redis.core.query.QueryUtils;
import org.springframework.data.redis.core.query.SortQuery;
import org.springframework.data.redis.core.script.DefaultScriptExecutor;
import org.springframework.data.redis.core.script.RedisScript;
import org.springframework.data.redis.core.script.ScriptExecutor;
import org.springframework.data.redis.core.types.RedisClientInfo;
import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.SerializationUtils;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.lang.Nullable;
import org.springframework.transaction.support.TransactionSynchronizationManager;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.CollectionUtils;
/**
* Helper class that simplifies Redis data access code.
* <p/>
* Performs automatic serialization/deserialization between the given objects and the underlying binary data in the
* Redis store. By default, it uses Java serialization for its objects (through {@link JdkSerializationRedisSerializer}
* ). For String intensive operations consider the dedicated {@link StringRedisTemplate}.
* <p/>
* The central method is execute, supporting Redis access code implementing the {@link RedisCallback} interface. It
* provides {@link RedisConnection} handling such that neither the {@link RedisCallback} implementation nor the calling
* code needs to explicitly care about retrieving/closing Redis connections, or handling Connection lifecycle
* exceptions. For typical single step actions, there are various convenience methods.
* <p/>
* Once configured, this class is thread-safe.
* <p/>
* Note that while the template is generified, it is up to the serializers/deserializers to properly convert the given
* Objects to and from binary data.
* <p/>
* <b>This is the central class in Redis support</b>.
*
* @author Costin Leau
* @author Christoph Strobl
* @author Ninad Divadkar
* @author Anqing Shao
* @author Mark Paluch
* @param <K> the Redis key type against which the template works (usually a String)
* @param <V> the Redis value type against which the template works
* @see StringRedisTemplate
*/
public class RedisTemplate<K, V> extends RedisAccessor implements RedisOperations<K, V>, BeanClassLoaderAware {
private boolean enableTransactionSupport = false;
private boolean exposeConnection = false;
private boolean initialized = false;
private boolean enableDefaultSerializer = true;
private @Nullable RedisSerializer<?> defaultSerializer;
private @Nullable ClassLoader classLoader;
@SuppressWarnings("rawtypes") private @Nullable RedisSerializer keySerializer = null;
@SuppressWarnings("rawtypes") private @Nullable RedisSerializer valueSerializer = null;
@SuppressWarnings("rawtypes") private @Nullable RedisSerializer hashKeySerializer = null;
@SuppressWarnings("rawtypes") private @Nullable RedisSerializer hashValueSerializer = null;
private RedisSerializer<String> stringSerializer = RedisSerializer.string();
private @Nullable ScriptExecutor<K> scriptExecutor;
// cache singleton objects (where possible)
private @Nullable ValueOperations<K, V> valueOps;
private @Nullable ListOperations<K, V> listOps;
private @Nullable SetOperations<K, V> setOps;
private @Nullable ZSetOperations<K, V> zSetOps;
private @Nullable GeoOperations<K, V> geoOps;
private @Nullable HyperLogLogOperations<K, V> hllOps;
/**
* Constructs a new <code>RedisTemplate</code> instance.
*/
public RedisTemplate() {}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.RedisAccessor#afterPropertiesSet()
*/
@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;
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.RedisOperations#execute(org.springframework.data.redis.core.RedisCallback)
*/
@Override
@Nullable
public <T> T execute(RedisCallback<T> action) {
return execute(action, isExposeConnection());
}
/**
* Executes the given action object within a connection, which can be exposed or not.
*
* @param <T> return type
* @param action callback object that specifies the Redis action
* @param exposeConnection whether to enforce exposure of the native Redis Connection to callback code
* @return object returned by the action
*/
@Nullable
public <T> T execute(RedisCallback<T> action, boolean exposeConnection) {
return execute(action, exposeConnection, false);
}
/**
* Executes the given action object within a connection that can be exposed or not. Additionally, the connection can
* be pipelined. Note the results of the pipeline are discarded (making it suitable for write-only scenarios).
*
* @param <T> return type
* @param action callback object to execute
* @param exposeConnection whether to enforce exposure of the native Redis Connection to callback code
* @param pipeline whether to pipeline or not the connection for the execution
* @return object returned by the action
*/
@Nullable
public <T> T execute(RedisCallback<T> action, boolean exposeConnection, boolean pipeline) {
Assert.isTrue(initialized, "template not initialized; call afterPropertiesSet() before using it");
Assert.notNull(action, "Callback object must not be null");
RedisConnectionFactory factory = getRequiredConnectionFactory();
RedisConnection conn = null;
try {
if (enableTransactionSupport) {
// only bind resources in case of potential transaction synchronization
conn = RedisConnectionUtils.bindConnection(factory, enableTransactionSupport);
} else {
conn = RedisConnectionUtils.getConnection(factory);
}
boolean existingConnection = TransactionSynchronizationManager.hasResource(factory);
RedisConnection connToUse = preProcessConnection(conn, existingConnection);
boolean pipelineStatus = connToUse.isPipelined();
if (pipeline && !pipelineStatus) {
connToUse.openPipeline();
}
RedisConnection connToExpose = (exposeConnection ? connToUse : createRedisConnectionProxy(connToUse));
T result = action.doInRedis(connToExpose);
// close pipeline
if (pipeline && !pipelineStatus) {
connToUse.closePipeline();
}
// TODO: any other connection processing?
return postProcessResult(result, connToUse, existingConnection);
} finally {
RedisConnectionUtils.releaseConnection(conn, factory);
}
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.RedisOperations#execute(org.springframework.data.redis.core.SessionCallback)
*/
@Override
public <T> T execute(SessionCallback<T> session) {
Assert.isTrue(initialized, "template not initialized; call afterPropertiesSet() before using it");
Assert.notNull(session, "Callback object must not be null");
RedisConnectionFactory factory = getRequiredConnectionFactory();
// bind connection
RedisConnectionUtils.bindConnection(factory, enableTransactionSupport);
try {
return session.execute(this);
} finally {
RedisConnectionUtils.unbindConnection(factory);
}
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.RedisOperations#executePipelined(org.springframework.data.redis.core.SessionCallback)
*/
@Override
public List<Object> executePipelined(SessionCallback<?> session) {
return executePipelined(session, valueSerializer);
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.RedisOperations#executePipelined(org.springframework.data.redis.core.SessionCallback, org.springframework.data.redis.serializer.RedisSerializer)
*/
@Override
public List<Object> executePipelined(SessionCallback<?> session, @Nullable RedisSerializer<?> resultSerializer) {
Assert.isTrue(initialized, "template not initialized; call afterPropertiesSet() before using it");
Assert.notNull(session, "Callback object must not be null");
RedisConnectionFactory factory = getRequiredConnectionFactory();
// bind connection
RedisConnectionUtils.bindConnection(factory, enableTransactionSupport);
try {
return execute((RedisCallback<List<Object>>) connection -> {
connection.openPipeline();
boolean pipelinedClosed = false;
try {
Object result = executeSession(session);
if (result != null) {
throw new InvalidDataAccessApiUsageException(
"Callback cannot return a non-null value as it gets overwritten by the pipeline");
}
List<Object> closePipeline = connection.closePipeline();
pipelinedClosed = true;
return deserializeMixedResults(closePipeline, resultSerializer, hashKeySerializer, hashValueSerializer);
} finally {
if (!pipelinedClosed) {
connection.closePipeline();
}
}
});
} finally {
RedisConnectionUtils.unbindConnection(factory);
}
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.RedisOperations#executePipelined(org.springframework.data.redis.core.RedisCallback)
*/
@Override
public List<Object> executePipelined(RedisCallback<?> action) {
return executePipelined(action, valueSerializer);
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.RedisOperations#executePipelined(org.springframework.data.redis.core.RedisCallback, org.springframework.data.redis.serializer.RedisSerializer)
*/
@Override
public List<Object> executePipelined(RedisCallback<?> action, @Nullable RedisSerializer<?> resultSerializer) {
return execute((RedisCallback<List<Object>>) connection -> {
connection.openPipeline();
boolean pipelinedClosed = false;
try {
Object result = action.doInRedis(connection);
if (result != null) {
throw new InvalidDataAccessApiUsageException(
"Callback cannot return a non-null value as it gets overwritten by the pipeline");
}
List<Object> closePipeline = connection.closePipeline();
pipelinedClosed = true;
return deserializeMixedResults(closePipeline, resultSerializer, hashKeySerializer, hashValueSerializer);
} finally {
if (!pipelinedClosed) {
connection.closePipeline();
}
}
});
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.RedisOperations#execute(org.springframework.data.redis.core.script.RedisScript, java.util.List, java.lang.Object[])
*/
@Override
public <T> T execute(RedisScript<T> script, List<K> keys, Object... args) {
return scriptExecutor.execute(script, keys, args);
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.RedisOperations#execute(org.springframework.data.redis.core.script.RedisScript, org.springframework.data.redis.serializer.RedisSerializer, org.springframework.data.redis.serializer.RedisSerializer, java.util.List, java.lang.Object[])
*/
@Override
public <T> T execute(RedisScript<T> script, RedisSerializer<?> argsSerializer, RedisSerializer<T> resultSerializer,
List<K> keys, Object... args) {
return scriptExecutor.execute(script, argsSerializer, resultSerializer, keys, args);
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.RedisOperations#executeWithStickyConnection(org.springframework.data.redis.core.RedisCallback)
*/
@Override
public <T extends Closeable> T executeWithStickyConnection(RedisCallback<T> callback) {
Assert.isTrue(initialized, "template not initialized; call afterPropertiesSet() before using it");
Assert.notNull(callback, "Callback object must not be null");
RedisConnectionFactory factory = getRequiredConnectionFactory();
RedisConnection connection = preProcessConnection(RedisConnectionUtils.doGetConnection(factory, true, false, false),
false);
return callback.doInRedis(connection);
}
private Object executeSession(SessionCallback<?> session) {
return session.execute(this);
}
protected RedisConnection createRedisConnectionProxy(RedisConnection pm) {
Class<?>[] ifcs = ClassUtils.getAllInterfacesForClass(pm.getClass(), getClass().getClassLoader());
return (RedisConnection) Proxy.newProxyInstance(pm.getClass().getClassLoader(), ifcs,
new CloseSuppressingInvocationHandler(pm));
}
/**
* Processes the connection (before any settings are executed on it). Default implementation returns the connection as
* is.
*
* @param connection redis connection
*/
protected RedisConnection preProcessConnection(RedisConnection connection, boolean existingConnection) {
return connection;
}
@Nullable
protected <T> T postProcessResult(@Nullable T result, RedisConnection conn, boolean existingConnection) {
return result;
}
/**
* Returns whether to expose the native Redis connection to RedisCallback code, or rather a connection proxy (the
* default).
*
* @return whether to expose the native Redis connection or not
*/
public boolean isExposeConnection() {
return exposeConnection;
}
/**
* Sets whether to expose the Redis connection to {@link RedisCallback} code. Default is "false": a proxy will be
* returned, suppressing <tt>quit</tt> and <tt>disconnect</tt> calls.
*
* @param exposeConnection
*/
public void setExposeConnection(boolean exposeConnection) {
this.exposeConnection = exposeConnection;
}
/**
* @return Whether or not the default serializer should be used. If not, any serializers not explicitly set will
* remain null and values will not be serialized or deserialized.
*/
public boolean isEnableDefaultSerializer() {
return enableDefaultSerializer;
}
/**
* @param enableDefaultSerializer Whether or not the default serializer should be used. If not, any serializers not
* explicitly set will remain null and values will not be serialized or deserialized.
*/
public void setEnableDefaultSerializer(boolean enableDefaultSerializer) {
this.enableDefaultSerializer = enableDefaultSerializer;
}
/**
* Returns the default serializer used by this template.
*
* @return template default serializer
*/
@Nullable
public RedisSerializer<?> getDefaultSerializer() {
return defaultSerializer;
}
/**
* Sets the default serializer to use for this template. All serializers (expect the
* {@link #setStringSerializer(RedisSerializer)}) are initialized to this value unless explicitly set. Defaults to
* {@link JdkSerializationRedisSerializer}.
*
* @param serializer default serializer to use
*/
public void setDefaultSerializer(RedisSerializer<?> serializer) {
this.defaultSerializer = serializer;
}
/**
* Sets the key serializer to be used by this template. Defaults to {@link #getDefaultSerializer()}.
*
* @param serializer the key serializer to be used by this template.
*/
public void setKeySerializer(RedisSerializer<?> serializer) {
this.keySerializer = serializer;
}
/**
* Returns the key serializer used by this template.
*
* @return the key serializer used by this template.
*/
@Override
public RedisSerializer<?> getKeySerializer() {
return keySerializer;
}
/**
* Sets the value serializer to be used by this template. Defaults to {@link #getDefaultSerializer()}.
*
* @param serializer the value serializer to be used by this template.
*/
public void setValueSerializer(RedisSerializer<?> serializer) {
this.valueSerializer = serializer;
}
/**
* Returns the value serializer used by this template.
*
* @return the value serializer used by this template.
*/
@Override
public RedisSerializer<?> getValueSerializer() {
return valueSerializer;
}
/**
* Returns the hashKeySerializer.
*
* @return Returns the hashKeySerializer
*/
@Override
public RedisSerializer<?> getHashKeySerializer() {
return hashKeySerializer;
}
/**
* Sets the hash key (or field) serializer to be used by this template. Defaults to {@link #getDefaultSerializer()}.
*
* @param hashKeySerializer The hashKeySerializer to set.
*/
public void setHashKeySerializer(RedisSerializer<?> hashKeySerializer) {
this.hashKeySerializer = hashKeySerializer;
}
/**
* Returns the hashValueSerializer.
*
* @return Returns the hashValueSerializer
*/
@Override
public RedisSerializer<?> getHashValueSerializer() {
return hashValueSerializer;
}
/**
* Sets the hash value serializer to be used by this template. Defaults to {@link #getDefaultSerializer()}.
*
* @param hashValueSerializer The hashValueSerializer to set.
*/
public void setHashValueSerializer(RedisSerializer<?> hashValueSerializer) {
this.hashValueSerializer = hashValueSerializer;
}
/**
* Returns the stringSerializer.
*
* @return Returns the stringSerializer
*/
public RedisSerializer<String> getStringSerializer() {
return stringSerializer;
}
/**
* Sets the string value serializer to be used by this template (when the arguments or return types are always
* strings). Defaults to {@link StringRedisSerializer}.
*
* @see ValueOperations#get(Object, long, long)
* @param stringSerializer The stringValueSerializer to set.
*/
public void setStringSerializer(RedisSerializer<String> stringSerializer) {
this.stringSerializer = stringSerializer;
}
/**
* @param scriptExecutor The {@link ScriptExecutor} to use for executing Redis scripts
*/
public void setScriptExecutor(ScriptExecutor<K> scriptExecutor) {
this.scriptExecutor = scriptExecutor;
}
@SuppressWarnings("unchecked")
private byte[] rawKey(Object key) {
Assert.notNull(key, "non null key required");
if (keySerializer == null && key instanceof byte[]) {
return (byte[]) key;
}
return keySerializer.serialize(key);
}
private byte[] rawString(String key) {
return stringSerializer.serialize(key);
}
@SuppressWarnings("unchecked")
private byte[] rawValue(Object value) {
if (valueSerializer == null && value instanceof byte[]) {
return (byte[]) value;
}
return valueSerializer.serialize(value);
}
private byte[][] rawKeys(Collection<K> keys) {
final byte[][] rawKeys = new byte[keys.size()][];
int i = 0;
for (K key : keys) {
rawKeys[i++] = rawKey(key);
}
return rawKeys;
}
@SuppressWarnings("unchecked")
private K deserializeKey(byte[] value) {
return keySerializer != null ? (K) keySerializer.deserialize(value) : (K) value;
}
@SuppressWarnings({ "unchecked", "rawtypes" })
@Nullable
private List<Object> deserializeMixedResults(@Nullable List<Object> rawValues,
@Nullable RedisSerializer valueSerializer, @Nullable RedisSerializer hashKeySerializer,
@Nullable RedisSerializer hashValueSerializer) {
if (rawValues == null) {
return null;
}
List<Object> values = new ArrayList<>();
for (Object rawValue : rawValues) {
if (rawValue instanceof byte[] && valueSerializer != null) {
values.add(valueSerializer.deserialize((byte[]) rawValue));
} else if (rawValue instanceof List) {
// Lists are the only potential Collections of mixed values....
values.add(deserializeMixedResults((List) rawValue, valueSerializer, hashKeySerializer, hashValueSerializer));
} else if (rawValue instanceof Set && !(((Set) rawValue).isEmpty())) {
values.add(deserializeSet((Set) rawValue, valueSerializer));
} else if (rawValue instanceof Map && !(((Map) rawValue).isEmpty())
&& ((Map) rawValue).values().iterator().next() instanceof byte[]) {
values.add(SerializationUtils.deserialize((Map) rawValue, hashKeySerializer, hashValueSerializer));
} else {
values.add(rawValue);
}
}
return values;
}
@SuppressWarnings({ "rawtypes", "unchecked" })
private Set<?> deserializeSet(Set rawSet, @Nullable RedisSerializer valueSerializer) {
if (rawSet.isEmpty()) {
return rawSet;
}
Object setValue = rawSet.iterator().next();
if (setValue instanceof byte[] && valueSerializer != null) {
return (SerializationUtils.deserialize(rawSet, valueSerializer));
} else if (setValue instanceof Tuple) {
return convertTupleValues(rawSet, valueSerializer);
} else {
return rawSet;
}
}
@SuppressWarnings({ "unchecked", "rawtypes" })
private Set<TypedTuple<V>> convertTupleValues(Set<Tuple> rawValues, @Nullable RedisSerializer valueSerializer) {
Set<TypedTuple<V>> set = new LinkedHashSet<>(rawValues.size());
for (Tuple rawValue : rawValues) {
Object value = rawValue.getValue();
if (valueSerializer != null) {
value = valueSerializer.deserialize(rawValue.getValue());
}
set.add(new DefaultTypedTuple(value, rawValue.getScore()));
}
return set;
}
//
// RedisOperations
//
/**
* Execute a transaction, using the default {@link RedisSerializer}s to deserialize any results that are byte[]s or
* Collections or Maps of byte[]s or Tuples. Other result types (Long, Boolean, etc) are left as-is in the converted
* results. If conversion of tx results has been disabled in the {@link RedisConnectionFactory}, the results of exec
* will be returned without deserialization. This check is mostly for backwards compatibility with 1.0.
*
* @return The (possibly deserialized) results of transaction exec
*/
@Override
public List<Object> exec() {
List<Object> results = execRaw();
if (getRequiredConnectionFactory().getConvertPipelineAndTxResults()) {
return deserializeMixedResults(results, valueSerializer, hashKeySerializer, hashValueSerializer);
} else {
return results;
}
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.RedisOperations#exec(org.springframework.data.redis.serializer.RedisSerializer)
*/
@Override
public List<Object> exec(RedisSerializer<?> valueSerializer) {
return deserializeMixedResults(execRaw(), valueSerializer, valueSerializer, valueSerializer);
}
protected List<Object> execRaw() {
List<Object> raw = execute(RedisTxCommands::exec);
return raw == null ? Collections.emptyList() : raw;
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.RedisOperations#delete(java.lang.Object)
*/
@Override
public Boolean delete(K key) {
byte[] rawKey = rawKey(key);
Long result = execute(connection -> connection.del(rawKey), true);
return result != null && result.intValue() == 1;
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.RedisOperations#delete(java.util.Collection)
*/
@Override
public Long delete(Collection<K> keys) {
if (CollectionUtils.isEmpty(keys)) {
return 0L;
}
byte[][] rawKeys = rawKeys(keys);
return execute(connection -> connection.del(rawKeys), true);
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.RedisOperations#unlink(java.lang.Object)
*/
@Override
public Boolean unlink(K key) {
byte[] rawKey = rawKey(key);
Long result = execute(connection -> connection.unlink(rawKey), true);
return result != null && result.intValue() == 1;
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.RedisOperations#unlink(java.util.Collection)
*/
@Override
public Long unlink(Collection<K> keys) {
if (CollectionUtils.isEmpty(keys)) {
return 0L;
}
byte[][] rawKeys = rawKeys(keys);
return execute(connection -> connection.unlink(rawKeys), true);
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.RedisOperations#hasKey(java.lang.Object)
*/
@Override
public Boolean hasKey(K key) {
byte[] rawKey = rawKey(key);
return execute(connection -> connection.exists(rawKey), true);
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.RedisOperations#countExistingKeys(java.util.Collection)
*/
@Override
public Long countExistingKeys(Collection<K> keys) {
Assert.notNull(keys, "Keys must not be null!");
byte[][] rawKeys = rawKeys(keys);
return execute(connection -> connection.exists(rawKeys), true);
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.RedisOperations#expire(java.lang.Object, long, java.util.concurrent.TimeUnit)
*/
@Override
public Boolean expire(K key, final long timeout, final TimeUnit unit) {
byte[] rawKey = rawKey(key);
long rawTimeout = TimeoutUtils.toMillis(timeout, unit);
return execute(connection -> {
try {
return connection.pExpire(rawKey, rawTimeout);
} catch (Exception e) {
// Driver may not support pExpire or we may be running on Redis 2.4
return connection.expire(rawKey, TimeoutUtils.toSeconds(timeout, unit));
}
}, true);
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.RedisOperations#expireAt(java.lang.Object, java.util.Date)
*/
@Override
public Boolean expireAt(K key, final Date date) {
byte[] rawKey = rawKey(key);
return execute(connection -> {
try {
return connection.pExpireAt(rawKey, date.getTime());
} catch (Exception e) {
return connection.expireAt(rawKey, date.getTime() / 1000);
}
}, true);
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.RedisOperations#convertAndSend(java.lang.String, java.lang.Object)
*/
@Override
public void convertAndSend(String channel, Object message) {
Assert.hasText(channel, "a non-empty channel is required");
byte[] rawChannel = rawString(channel);
byte[] rawMessage = rawValue(message);
execute(connection -> {
connection.publish(rawChannel, rawMessage);
return null;
}, true);
}
//
// Value operations
//
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.RedisOperations#getExpire(java.lang.Object)
*/
@Override
public Long getExpire(K key) {
byte[] rawKey = rawKey(key);
return execute(connection -> connection.ttl(rawKey), true);
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.RedisOperations#getExpire(java.lang.Object, java.util.concurrent.TimeUnit)
*/
@Override
public Long getExpire(K key, final TimeUnit timeUnit) {
byte[] rawKey = rawKey(key);
return execute(connection -> {
try {
return connection.pTtl(rawKey, timeUnit);
} catch (Exception e) {
// Driver may not support pTtl or we may be running on Redis 2.4
return connection.ttl(rawKey, timeUnit);
}
}, true);
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.RedisOperations#keys(java.lang.Object)
*/
@Override
@SuppressWarnings("unchecked")
public Set<K> keys(K pattern) {
byte[] rawKey = rawKey(pattern);
Set<byte[]> rawKeys = execute(connection -> connection.keys(rawKey), true);
return keySerializer != null ? SerializationUtils.deserialize(rawKeys, keySerializer) : (Set<K>) rawKeys;
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.RedisOperations#persist(java.lang.Object)
*/
@Override
public Boolean persist(K key) {
byte[] rawKey = rawKey(key);
return execute(connection -> connection.persist(rawKey), true);
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.RedisOperations#move(java.lang.Object, int)
*/
@Override
public Boolean move(K key, final int dbIndex) {
byte[] rawKey = rawKey(key);
return execute(connection -> connection.move(rawKey, dbIndex), true);
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.RedisOperations#randomKey()
*/
@Override
public K randomKey() {
byte[] rawKey = execute(RedisKeyCommands::randomKey, true);
return deserializeKey(rawKey);
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.RedisOperations#rename(java.lang.Object, java.lang.Object)
*/
@Override
public void rename(K oldKey, K newKey) {
byte[] rawOldKey = rawKey(oldKey);
byte[] rawNewKey = rawKey(newKey);
execute(connection -> {
connection.rename(rawOldKey, rawNewKey);
return null;
}, true);
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.RedisOperations#renameIfAbsent(java.lang.Object, java.lang.Object)
*/
@Override
public Boolean renameIfAbsent(K oldKey, K newKey) {
byte[] rawOldKey = rawKey(oldKey);
byte[] rawNewKey = rawKey(newKey);
return execute(connection -> connection.renameNX(rawOldKey, rawNewKey), true);
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.RedisOperations#type(java.lang.Object)
*/
@Override
public DataType type(K key) {
byte[] rawKey = rawKey(key);
return execute(connection -> connection.type(rawKey), true);
}
/**
* Executes the Redis dump command and returns the results. Redis uses a non-standard serialization mechanism and
* includes checksum information, thus the raw bytes are returned as opposed to deserializing with valueSerializer.
* Use the return value of dump as the value argument to restore
*
* @param key The key to dump
* @return results The results of the dump operation
*/
@Override
public byte[] dump(K key) {
byte[] rawKey = rawKey(key);
return execute(connection -> connection.dump(rawKey), true);
}
/**
* Executes the Redis restore command. The value passed in should be the exact serialized data returned from
* {@link #dump(Object)}, since Redis uses a non-standard serialization mechanism.
*
* @param key The key to restore
* @param value The value to restore, as returned by {@link #dump(Object)}
* @param timeToLive An expiration for the restored key, or 0 for no expiration
* @param unit The time unit for timeToLive
* @param replace use {@literal true} to replace a potentially existing value instead of erroring.
* @throws RedisSystemException if the key you are attempting to restore already exists and {@code replace} is set to
* {@literal false}.
*/
@Override
public void restore(K key, final byte[] value, long timeToLive, TimeUnit unit, boolean replace) {
byte[] rawKey = rawKey(key);
long rawTimeout = TimeoutUtils.toMillis(timeToLive, unit);
execute(connection -> {
connection.restore(rawKey, rawTimeout, value, replace);
return null;
}, true);
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.RedisOperations#multi()
*/
@Override
public void multi() {
execute(connection -> {
connection.multi();
return null;
}, true);
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.RedisOperations#discard()
*/
@Override
public void discard() {
execute(connection -> {
connection.discard();
return null;
}, true);
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.RedisOperations#watch(java.lang.Object)
*/
@Override
public void watch(K key) {
byte[] rawKey = rawKey(key);
execute(connection -> {
connection.watch(rawKey);
return null;
}, true);
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.RedisOperations#watch(java.util.Collection)
*/
@Override
public void watch(Collection<K> keys) {
byte[][] rawKeys = rawKeys(keys);
execute(connection -> {
connection.watch(rawKeys);
return null;
}, true);
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.RedisOperations#unwatch()
*/
@Override
public void unwatch() {
execute(connection -> {
connection.unwatch();
return null;
}, true);
}
// Sort operations
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.RedisOperations#sort(org.springframework.data.redis.core.query.SortQuery)
*/
@Override
@SuppressWarnings("unchecked")
public List<V> sort(SortQuery<K> query) {
return sort(query, valueSerializer);
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.RedisOperations#sort(org.springframework.data.redis.core.query.SortQuery, org.springframework.data.redis.serializer.RedisSerializer)
*/
@Override
public <T> List<T> sort(SortQuery<K> query, @Nullable RedisSerializer<T> resultSerializer) {
byte[] rawKey = rawKey(query.getKey());
SortParameters params = QueryUtils.convertQuery(query, stringSerializer);
List<byte[]> vals = execute(connection -> connection.sort(rawKey, params), true);
return SerializationUtils.deserialize(vals, resultSerializer);
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.RedisOperations#sort(org.springframework.data.redis.core.query.SortQuery, org.springframework.data.redis.core.BulkMapper)
*/
@Override
@SuppressWarnings("unchecked")
public <T> List<T> sort(SortQuery<K> query, BulkMapper<T, V> bulkMapper) {
return sort(query, bulkMapper, valueSerializer);
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.RedisOperations#sort(org.springframework.data.redis.core.query.SortQuery, org.springframework.data.redis.core.BulkMapper, org.springframework.data.redis.serializer.RedisSerializer)
*/
@Override
public <T, S> List<T> sort(SortQuery<K> query, BulkMapper<T, S> bulkMapper,
@Nullable RedisSerializer<S> resultSerializer) {
List<S> values = sort(query, resultSerializer);
if (values == null || values.isEmpty()) {
return Collections.emptyList();
}
int bulkSize = query.getGetPattern().size();
List<T> result = new ArrayList<>(values.size() / bulkSize + 1);
List<S> bulk = new ArrayList<>(bulkSize);
for (S s : values) {
bulk.add(s);
if (bulk.size() == bulkSize) {
result.add(bulkMapper.mapBulk(Collections.unmodifiableList(bulk)));
// create a new list (we could reuse the old one but the client might hang on to it for some reason)
bulk = new ArrayList<>(bulkSize);
}
}
return result;
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.RedisOperations#sort(org.springframework.data.redis.core.query.SortQuery, java.lang.Object)
*/
@Override
public Long sort(SortQuery<K> query, K storeKey) {
byte[] rawStoreKey = rawKey(storeKey);
byte[] rawKey = rawKey(query.getKey());
SortParameters params = QueryUtils.convertQuery(query, stringSerializer);
return execute(connection -> connection.sort(rawKey, params, rawStoreKey), true);
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.RedisOperations#killClient(java.lang.Object)
*/
@Override
public void killClient(final String host, final int port) {
execute((RedisCallback<Void>) connection -> {
connection.killClient(host, port);
return null;
});
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.RedisOperations#getClientList()
*/
@Override
public List<RedisClientInfo> getClientList() {
return execute(RedisServerCommands::getClientList);
}
/*
* @see org.springframework.data.redis.core.RedisOperations#slaveOf(java.lang.String, int)
*/
@Override
public void slaveOf(final String host, final int port) {
execute((RedisCallback<Void>) connection -> {
connection.slaveOf(host, port);
return null;
});
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.RedisOperations#slaveOfNoOne()
*/
@Override
public void slaveOfNoOne() {
execute((RedisCallback<Void>) connection -> {
connection.slaveOfNoOne();
return null;
});
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.RedisOperations#opsForCluster()
*/
@Override
public ClusterOperations<K, V> opsForCluster() {
return new DefaultClusterOperations<>(this);
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.RedisOperations#opsForGeo()
*/
@Override
public GeoOperations<K, V> opsForGeo() {
if (geoOps == null) {
geoOps = new DefaultGeoOperations<>(this);
}
return geoOps;
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.RedisOperations#boundGeoOps(java.lang.Object)
*/
@Override
public BoundGeoOperations<K, V> boundGeoOps(K key) {
return new DefaultBoundGeoOperations<>(key, this);
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.RedisOperations#boundHashOps(java.lang.Object)
*/
@Override
public <HK, HV> BoundHashOperations<K, HK, HV> boundHashOps(K key) {
return new DefaultBoundHashOperations<>(key, this);
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.RedisOperations#opsForHash()
*/
@Override
public <HK, HV> HashOperations<K, HK, HV> opsForHash() {
return new DefaultHashOperations<>(this);
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.RedisOperations#opsForHyperLogLog()
*/
@Override
public HyperLogLogOperations<K, V> opsForHyperLogLog() {
if (hllOps == null) {
hllOps = new DefaultHyperLogLogOperations<>(this);
}
return hllOps;
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.RedisOperations#opsForList()
*/
@Override
public ListOperations<K, V> opsForList() {
if (listOps == null) {
listOps = new DefaultListOperations<>(this);
}
return listOps;
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.RedisOperations#boundListOps(java.lang.Object)
*/
@Override
public BoundListOperations<K, V> boundListOps(K key) {
return new DefaultBoundListOperations<>(key, this);
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.RedisOperations#boundSetOps(java.lang.Object)
*/
@Override
public BoundSetOperations<K, V> boundSetOps(K key) {
return new DefaultBoundSetOperations<>(key, this);
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.RedisOperations#opsForSet()
*/
@Override
public SetOperations<K, V> opsForSet() {
if (setOps == null) {
setOps = new DefaultSetOperations<>(this);
}
return setOps;
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.RedisOperations#boundValueOps(java.lang.Object)
*/
@Override
public BoundValueOperations<K, V> boundValueOps(K key) {
return new DefaultBoundValueOperations<>(key, this);
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.RedisOperations#opsForValue()
*/
@Override
public ValueOperations<K, V> opsForValue() {
if (valueOps == null) {
valueOps = new DefaultValueOperations<>(this);
}
return valueOps;
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.RedisOperations#boundZSetOps(java.lang.Object)
*/
@Override
public BoundZSetOperations<K, V> boundZSetOps(K key) {
return new DefaultBoundZSetOperations<>(key, this);
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.core.RedisOperations#opsForZSet()
*/
@Override
public ZSetOperations<K, V> opsForZSet() {
if (zSetOps == null) {
zSetOps = new DefaultZSetOperations<>(this);
}
return zSetOps;
}
/**
* If set to {@code true} {@link RedisTemplate} will use {@literal MULTI...EXEC|DISCARD} to keep track of operations.
*
* @param enableTransactionSupport
* @since 1.3
*/
public void setEnableTransactionSupport(boolean enableTransactionSupport) {
this.enableTransactionSupport = enableTransactionSupport;
}
/**
* Set the {@link ClassLoader} to be used for the default {@link JdkSerializationRedisSerializer} in case no other
* {@link RedisSerializer} is explicitly set as the default one.
*
* @param classLoader can be {@literal null}.
* @see org.springframework.beans.factory.BeanClassLoaderAware#setBeanClassLoader
* @since 1.8
*/
@Override
public void setBeanClassLoader(ClassLoader classLoader) {
this.classLoader = classLoader;
}
}
二、RedisUtils
public class RedisUtils {
private RedisTemplate<Object, Object> redisTemplate;
@Value("${jwt.online-key}")
private String onlineKey;
public RedisUtils(RedisTemplate<Object, Object> redisTemplate) {
this.redisTemplate = redisTemplate;
}
// =============================common============================
/**
* 指定缓存失效时间
* @param key 键
* @param time 时间(秒)
*/
public boolean expire(String key, long time) {
try {
if (time > 0) {
redisTemplate.expire(key, time, TimeUnit.SECONDS);
}
} catch (Exception e) {
e.printStackTrace();
return false;
}
return true;
}
/**
* 根据 key 获取过期时间
* @param key 键 不能为null
* @return 时间(秒) 返回0代表为永久有效
*/
public long getExpire(Object key) {
return redisTemplate.getExpire(key, TimeUnit.SECONDS);
}
/**
* 查找匹配key
* @param pattern key
* @return /
*/
public List<String> scan(String pattern) {
ScanOptions options = ScanOptions.scanOptions().match(pattern).build();
RedisConnectionFactory factory = redisTemplate.getConnectionFactory();
RedisConnection rc = Objects.requireNonNull(factory).getConnection();
Cursor<byte[]> cursor = rc.scan(options);
List<String> result = new ArrayList<>();
while (cursor.hasNext()) {
result.add(new String(cursor.next()));
}
try {
RedisConnectionUtils.releaseConnection(rc, factory);
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
/**
* 分页查询 key
* @param patternKey key
* @param page 页码
* @param size 每页数目
* @return /
*/
public List<String> findKeysForPage(String patternKey, int page, int size) {
ScanOptions options = ScanOptions.scanOptions().match(patternKey).build();
RedisConnectionFactory factory = redisTemplate.getConnectionFactory();
RedisConnection rc = Objects.requireNonNull(factory).getConnection();
Cursor<byte[]> cursor = rc.scan(options);
List<String> result = new ArrayList<>(size);
int tmpIndex = 0;
int fromIndex = page * size;
int toIndex = page * size + size;
while (cursor.hasNext()) {
if (tmpIndex >= fromIndex && tmpIndex < toIndex) {
result.add(new String(cursor.next()));
tmpIndex++;
continue;
}
// 获取到满足条件的数据后,就可以退出了
if(tmpIndex >=toIndex) {
break;
}
tmpIndex++;
cursor.next();
}
try {
RedisConnectionUtils.releaseConnection(rc, factory);
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
/**
* 判断key是否存在
* @param key 键
* @return true 存在 false不存在
*/
public boolean hasKey(String key) {
try {
return redisTemplate.hasKey(key);
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 删除缓存
* @param key 可以传一个值 或多个
*/
public void del(String... key) {
if (key != null && key.length > 0) {
if (key.length == 1) {
redisTemplate.delete(key[0]);
} else {
redisTemplate.delete(CollectionUtils.arrayToList(key));
}
}
}
// ============================String=============================
/**
* 普通缓存获取
* @param key 键
* @return 值
*/
public Object get(String key) {
return key == null ? null : redisTemplate.opsForValue().get(key);
}
/**
* 批量获取
* @param keys
* @return
*/
public List<Object> multiGet(List<String> keys) {
Object obj = redisTemplate.opsForValue().multiGet(Collections.singleton(keys));
return null;
}
/**
* 普通缓存放入
* @param key 键
* @param value 值
* @return true成功 false失败
*/
public boolean set(String key, Object value) {
try {
redisTemplate.opsForValue().set(key, value);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 普通缓存放入并设置时间
* @param key 键
* @param value 值
* @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期
* @return true成功 false 失败
*/
public boolean set(String key, Object value, long time) {
try {
if (time > 0) {
redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);
} else {
set(key, value);
}
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 普通缓存放入并设置时间
* @param key 键
* @param value 值
* @param time 时间
* @param timeUnit 类型
* @return true成功 false 失败
*/
public boolean set(String key, Object value, long time, TimeUnit timeUnit) {
try {
if (time > 0) {
redisTemplate.opsForValue().set(key, value, time, timeUnit);
} else {
set(key, value);
}
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
// ================================Map=================================
/**
* HashGet
* @param key 键 不能为null
* @param item 项 不能为null
* @return 值
*/
public Object hget(String key, String item) {
return redisTemplate.opsForHash().get(key, item);
}
/**
* 获取hashKey对应的所有键值
* @param key 键
* @return 对应的多个键值
*/
public Map<Object, Object> hmget(String key) {
return redisTemplate.opsForHash().entries(key);
}
/**
* HashSet
* @param key 键
* @param map 对应多个键值
* @return true 成功 false 失败
*/
public boolean hmset(String key, Map<String, Object> map) {
try {
redisTemplate.opsForHash().putAll(key, map);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* HashSet 并设置时间
* @param key 键
* @param map 对应多个键值
* @param time 时间(秒)
* @return true成功 false失败
*/
public boolean hmset(String key, Map<String, Object> map, long time) {
try {
redisTemplate.opsForHash().putAll(key, map);
if (time > 0) {
expire(key, time);
}
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 向一张hash表中放入数据,如果不存在将创建
*
* @param key 键
* @param item 项
* @param value 值
* @return true 成功 false失败
*/
public boolean hset(String key, String item, Object value) {
try {
redisTemplate.opsForHash().put(key, item, value);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 向一张hash表中放入数据,如果不存在将创建
*
* @param key 键
* @param item 项
* @param value 值
* @param time 时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间
* @return true 成功 false失败
*/
public boolean hset(String key, String item, Object value, long time) {
try {
redisTemplate.opsForHash().put(key, item, value);
if (time > 0) {
expire(key, time);
}
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 删除hash表中的值
*
* @param key 键 不能为null
* @param item 项 可以使多个 不能为null
*/
public void hdel(String key, Object... item) {
redisTemplate.opsForHash().delete(key, item);
}
/**
* 判断hash表中是否有该项的值
*
* @param key 键 不能为null
* @param item 项 不能为null
* @return true 存在 false不存在
*/
public boolean hHasKey(String key, String item) {
return redisTemplate.opsForHash().hasKey(key, item);
}
/**
* hash递增 如果不存在,就会创建一个 并把新增后的值返回
*
* @param key 键
* @param item 项
* @param by 要增加几(大于0)
* @return
*/
public double hincr(String key, String item, double by) {
return redisTemplate.opsForHash().increment(key, item, by);
}
/**
* hash递减
*
* @param key 键
* @param item 项
* @param by 要减少记(小于0)
* @return
*/
public double hdecr(String key, String item, double by) {
return redisTemplate.opsForHash().increment(key, item, -by);
}
// ============================set=============================
/**
* 根据key获取Set中的所有值
*
* @param key 键
* @return
*/
public Set<Object> sGet(String key) {
try {
return redisTemplate.opsForSet().members(key);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* 根据value从一个set中查询,是否存在
*
* @param key 键
* @param value 值
* @return true 存在 false不存在
*/
public boolean sHasKey(String key, Object value) {
try {
return redisTemplate.opsForSet().isMember(key, value);
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 将数据放入set缓存
*
* @param key 键
* @param values 值 可以是多个
* @return 成功个数
*/
public long sSet(String key, Object... values) {
try {
return redisTemplate.opsForSet().add(key, values);
} catch (Exception e) {
e.printStackTrace();
return 0;
}
}
/**
* 将set数据放入缓存
* @param key 键
* @param time 时间(秒)
* @param values 值 可以是多个
* @return 成功个数
*/
public long sSetAndTime(String key, long time, Object... values) {
try {
Long count = redisTemplate.opsForSet().add(key, values);
if (time > 0) {
expire(key, time);
}
return count;
} catch (Exception e) {
e.printStackTrace();
return 0;
}
}
/**
* 获取set缓存的长度
* @param key 键
* @return
*/
public long sGetSetSize(String key) {
try {
return redisTemplate.opsForSet().size(key);
} catch (Exception e) {
e.printStackTrace();
return 0;
}
}
/**
* 移除值为value的
* @param key 键
* @param values 值 可以是多个
* @return 移除的个数
*/
public long setRemove(String key, Object... values) {
try {
Long count = redisTemplate.opsForSet().remove(key, values);
return count;
} catch (Exception e) {
e.printStackTrace();
return 0;
}
}
// ===============================list=================================
/**
* 获取list缓存的内容
* @param key 键
* @param start 开始
* @param end 结束 0 到 -1代表所有值
* @return
*/
public List<Object> lGet(String key, long start, long end) {
try {
return redisTemplate.opsForList().range(key, start, end);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* 获取list缓存的长度
* @param key 键
* @return
*/
public long lGetListSize(String key) {
try {
return redisTemplate.opsForList().size(key);
} catch (Exception e) {
e.printStackTrace();
return 0;
}
}
/**
* 通过索引 获取list中的值
* @param key 键
* @param index 索引 index>=0时, 0 表头,1 第二个元素,依次类推;index<0时,-1,表尾,-2倒数第二个元素,依次类推
* @return
*/
public Object lGetIndex(String key, long index) {
try {
return redisTemplate.opsForList().index(key, index);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* 将list放入缓存
* @param key 键
* @param value 值
* @return
*/
public boolean lSet(String key, Object value) {
try {
redisTemplate.opsForList().rightPush(key, value);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 将list放入缓存
* @param key 键
* @param value 值
* @param time 时间(秒)
* @return
*/
public boolean lSet(String key, Object value, long time) {
try {
redisTemplate.opsForList().rightPush(key, value);
if (time > 0) {
expire(key, time);
}
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 将list放入缓存
* @param key 键
* @param value 值
* @return
*/
public boolean lSet(String key, List<Object> value) {
try {
redisTemplate.opsForList().rightPushAll(key, value);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 将list放入缓存
* @param key 键
* @param value 值
* @param time 时间(秒)
* @return
*/
public boolean lSet(String key, List<Object> value, long time) {
try {
redisTemplate.opsForList().rightPushAll(key, value);
if (time > 0) {
expire(key, time);
}
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 根据索引修改list中的某条数据
* @param key 键
* @param index 索引
* @param value 值
* @return /
*/
public boolean lUpdateIndex(String key, long index, Object value) {
try {
redisTemplate.opsForList().set(key, index, value);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 移除N个值为value
* @param key 键
* @param count 移除多少个
* @param value 值
* @return 移除的个数
*/
public long lRemove(String key, long count, Object value) {
try {
return redisTemplate.opsForList().remove(key, count, value);
} catch (Exception e) {
e.printStackTrace();
return 0;
}
}
}