Working with Objects through RedisTemplate
Most users are likely to use RedisTemplate
and its corresponding package, org.springframework.data.redis.core
or its reactive variant ReactiveRedisTemplate
.
The template is, in fact, the central class of the Redis module, due to its rich feature set.
The template offers a high-level abstraction for Redis interactions.
While [Reactive]RedisConnection
offers low-level methods that accept and return binary values (byte
arrays), the template takes care of serialization and connection management, freeing the user from dealing with such details.
The RedisTemplate
class implements the RedisOperations
interface and its reactive variant ReactiveRedisTemplate
implements ReactiveRedisOperations
.
The preferred way to reference operations on a [Reactive]RedisTemplate instance is through the
[Reactive]RedisOperations interface.
|
Moreover, the template provides operations views (following the grouping from the Redis command reference) that offer rich, generified interfaces for working against a certain type or certain key (through the KeyBound
interfaces) as described in the following table:
Operational views
-
Imperative
-
Reactive
Interface | Description |
---|---|
Key Type Operations |
|
Redis geospatial operations, such as |
|
Redis hash operations |
|
Redis HyperLogLog operations, such as |
|
Redis list operations |
|
Redis set operations |
|
Redis string (or value) operations |
|
Redis zset (or sorted set) operations |
|
Key Bound Operations |
|
Redis key bound geospatial operations |
|
Redis hash key bound operations |
|
Redis key bound operations |
|
Redis list key bound operations |
|
Redis set key bound operations |
|
Redis string (or value) key bound operations |
|
Redis zset (or sorted set) key bound operations |
Interface | Description |
---|---|
Key Type Operations |
|
Redis geospatial operations such as |
|
Redis hash operations |
|
Redis HyperLogLog operations such as ( |
|
Redis list operations |
|
Redis set operations |
|
Redis string (or value) operations |
|
Redis zset (or sorted set) operations |
Once configured, the template is thread-safe and can be reused across multiple instances.
RedisTemplate
uses a Java-based serializer for most of its operations.
This means that any object written or read by the template is serialized and deserialized through Java.
You can change the serialization mechanism on the template, and the Redis module offers several implementations, which are available in the org.springframework.data.redis.serializer
package.
See Serializers for more information.
You can also set any of the serializers to null and use RedisTemplate with raw byte arrays by setting the enableDefaultSerializer
property to false
.
Note that the template requires all keys to be non-null.
However, values can be null as long as the underlying serializer accepts them.
Read the Javadoc of each serializer for more information.
For cases where you need a certain template view, declare the view as a dependency and inject the template.
The container automatically performs the conversion, eliminating the opsFor[X]
calls, as shown in the following example:
-
Java Imperative
-
Java Reactive
-
XML
@Configuration
class MyConfig {
@Bean
LettuceConnectionFactory connectionFactory() {
return new LettuceConnectionFactory();
}
@Bean
RedisTemplate<String, String> redisTemplate(RedisConnectionFactory connectionFactory) {
RedisTemplate<String, String> template = new RedisTemplate<>();
template.setConnectionFactory(connectionFactory);
return template;
}
}
@Configuration
class MyConfig {
@Bean
LettuceConnectionFactory connectionFactory() {
return new LettuceConnectionFactory();
}
@Bean
ReactiveRedisTemplate<String, String> ReactiveRedisTemplate(ReactoveRedisConnectionFactory connectionFactory) {
return new ReactiveRedisTemplate<>(connectionFactory, RedisSerializationContext.string());
}
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="redisConnectionFactory" class="org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory"/>
<!-- redis template definition -->
<bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate" p:connection-factory-ref="redisConnectionFactory"/>
...
</beans>
[Reactive]RedisTemplate
-
Imperative
-
Reactive
public class Example {
// inject the actual operations
@Autowired
private RedisOperations<String, String> operations;
// inject the template as ListOperations
@Resource(name="redisTemplate")
private ListOperations<String, String> listOps;
public void addLink(String userId, URL url) {
listOps.leftPush(userId, url.toExternalForm());
}
}
public class Example {
// inject the actual template
@Autowired
private ReactiveRedisOperations<String, String> operations;
public Mono<Long> addLink(String userId, URL url) {
return operations.opsForList().leftPush(userId, url.toExternalForm());
}
}
String-focused Convenience Classes
Since it is quite common for the keys and values stored in Redis to be java.lang.String
, the Redis modules provides two extensions to RedisConnection
and RedisTemplate
, respectively the StringRedisConnection
(and its DefaultStringRedisConnection
implementation) and StringRedisTemplate
as a convenient one-stop solution for intensive String operations.
In addition to being bound to String
keys, the template and the connection use the StringRedisSerializer
underneath, which means the stored keys and values are human-readable (assuming the same encoding is used both in Redis and your code).
The following listings show an example:
-
Java Imperative
-
Java Reactive
-
XML
@Configuration
class RedisConfiguration {
@Bean
LettuceConnectionFactory redisConnectionFactory() {
return new LettuceConnectionFactory();
}
@Bean
StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory) {
StringRedisTemplate template = new StringRedisTemplate();
template.setConnectionFactory(redisConnectionFactory);
return template;
}
}
@Configuration
class RedisConfiguration {
@Bean
LettuceConnectionFactory redisConnectionFactory() {
return new LettuceConnectionFactory();
}
@Bean
ReactiveStringRedisTemplate reactiveRedisTemplate(ReactiveRedisConnectionFactory factory) {
return new ReactiveStringRedisTemplate<>(factory);
}
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="redisConnectionFactory" class="org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory"/>
<bean id="stringRedisTemplate" class="org.springframework.data.redis.core.StringRedisTemplate" p:connection-factory-ref="redisConnectionFactory"/>
</beans>
-
Imperative
-
Reactive
public class Example {
@Autowired
private StringRedisTemplate redisTemplate;
public void addLink(String userId, URL url) {
redisTemplate.opsForList().leftPush(userId, url.toExternalForm());
}
}
public class Example {
@Autowired
private ReactiveStringRedisTemplate redisTemplate;
public Mono<Long> addLink(String userId, URL url) {
return redisTemplate.opsForList().leftPush(userId, url.toExternalForm());
}
}
As with the other Spring templates, RedisTemplate
and StringRedisTemplate
let you talk directly to Redis through the RedisCallback
interface.
This feature gives complete control to you, as it talks directly to the RedisConnection
.
Note that the callback receives an instance of StringRedisConnection
when a StringRedisTemplate
is used.
The following example shows how to use the RedisCallback
interface:
public void useCallback() {
redisOperations.execute(new RedisCallback<Object>() {
public Object doInRedis(RedisConnection connection) throws DataAccessException {
Long size = connection.dbSize();
// Can cast to StringRedisConnection if using a StringRedisTemplate
((StringRedisConnection)connection).set("key", "value");
}
});
}
Serializers
From the framework perspective, the data stored in Redis is only bytes. While Redis itself supports various types, for the most part, these refer to the way the data is stored rather than what it represents. It is up to the user to decide whether the information gets translated into strings or any other objects.
In Spring Data, the conversion between the user (custom) types and raw data (and vice-versa) is handled by Spring Data Redis in the org.springframework.data.redis.serializer
package.
This package contains two types of serializers that, as the name implies, take care of the serialization process:
-
Two-way serializers based on
RedisSerializer
. -
Element readers and writers that use
RedisElementReader
andRedisElementWriter
.
The main difference between these variants is that RedisSerializer
primarily serializes to byte[]
while readers and writers use ByteBuffer
.
Multiple implementations are available (including two that have been already mentioned in this documentation):
-
JdkSerializationRedisSerializer
, which is used by default forRedisCache
andRedisTemplate
. -
the
StringRedisSerializer
.
However, one can use OxmSerializer
for Object/XML mapping through Spring OXM support or Jackson2JsonRedisSerializer
or GenericJackson2JsonRedisSerializer
for storing data in JSON format.
Do note that the storage format is not limited only to values. It can be used for keys, values, or hashes without any restrictions.
By default, If you are concerned about security vulnerabilities due to Java serialization, consider the general-purpose serialization filter mechanism at the core JVM level: |