Spring Boot Integration
Introduction
Running Redis from redis-cli teaches you the commands, but production applications need a client library. In the Java ecosystem, two drivers dominate—Jedis and Lettuce—while Spring Data Redis provides a convenient abstraction layer on top of either one. This chapter compares the drivers, shows how Spring Data Redis simplifies daily operations, and walks through a complete Spring Boot project that connects to Redis, caches method results, and implements a practical distributed lock.
Prerequisites
- Java 17 or newer
- Maven or Gradle installed
- Familiarity with Spring Boot basics
- A running Redis server (local or Docker) on port 6379
Jedis vs Lettuce
Both libraries are mature and well-supported. The choice usually comes down to threading model and API preference.
| Feature | Jedis | Lettuce |
|---|---|---|
| Threading | Blocking I/O; use connection pools | Async non-blocking I/O on Netty; share one connection |
| Reactive API | No native support | Full support for Mono and Flux |
| Sentinel / Cluster | Supported | Supported with better topology refresh |
| Spring Boot default | Optional | Default since Spring Boot 2.0 |
| Maintenance | Active | Active (preferred by Spring team) |
Tip
Start with Lettuce
If you are building a new Spring Boot application, use Lettuce. It is the default driver, supports reactive stacks, and eliminates connection-pool tuning headaches.
A Minimal Jedis Example
<!-- pom.xml -->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>5.1.0</version>
</dependency>A Minimal Lettuce Example
<!-- pom.xml -->
<dependency>
<groupId>io.lettuce</groupId>
<artifactId>lettuce-core</artifactId>
<version>6.3.0.RELEASE</version>
</dependency>Spring Data Redis
Spring Data Redis abstracts driver details behind familiar RedisTemplate and StringRedisTemplate APIs. It also provides annotation-driven caching that can replace manual Redis calls entirely.
Adding Dependencies
<!-- pom.xml -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>No version is needed because Spring Boot manages it.
Connection Settings
Spring Boot auto-configures a StringRedisTemplate and a RedisConnectionFactory from these properties.
Using StringRedisTemplate
StringRedisTemplate uses StringRedisSerializer for both keys and values, which is what you want for most text-based caching.
Working with Hashes
Serialization: The JSON Problem
By default, RedisTemplate uses Java serialization, which produces unreadable binary data. For JSON storage, configure a custom RedisTemplate:
Warning
JSON Type Information
GenericJackson2JsonRedisSerializer embeds a @class field so Jackson can deserialize polymorphic types. If you refactor package names, old cache entries may fail to deserialize. Plan cache versioning or TTLs around major refactors.
Annotation-Driven Caching
Spring Cache abstracts the cache provider entirely. Switching from an in-memory ConcurrentHashMap to Redis is a one-line configuration change.
Enable Caching
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Configuration;
@Configuration
@EnableCaching
public class CacheConfig {
}Cache Annotations
Custom TTL per Cache
Spring Cache does not expose TTL directly in annotations. Define it in configuration:
Implementing a Distributed Lock
Distributed locks prevent multiple instances of your application from performing the same critical operation simultaneously. Redis makes this possible with SETNX (Set if Not eXists) and expiration.
Basic Lock with StringRedisTemplate
Warning
This Is a Simplified Lock
The example above omits token verification and lock extension. For production systems, use Redisson or implement the full Redlock algorithm with token-matching Lua scripts to avoid accidentally releasing another client's lock.
Connecting to Sentinel and Cluster
Spring Boot connects to Sentinel or Cluster with purely configuration changes—no code modifications required.
Sentinel
spring:
data:
redis:
sentinel:
master: mymaster
nodes:
- sentinel1.example.com:26379
- sentinel2.example.com:26379
- sentinel3.example.com:26379
password: your-master-passwordCluster
spring:
data:
redis:
cluster:
nodes:
- redis1.example.com:6379
- redis2.example.com:6379
- redis3.example.com:6379
max-redirects: 3The StringRedisTemplate and cache annotations work identically regardless of topology.
FAQ
Should I use Jedis or Lettuce with Spring Boot?
Use Lettuce unless you have a specific reason not to. It is the Spring Boot default, handles high concurrency without connection pools, and supports reactive programming.
Why does my cached object fail to deserialize?
Common causes: the class was moved or renamed, Jackson does not have a no-arg constructor, or the serializer was changed without clearing old cache entries. Set a TTL or manually flush the cache after deploys that change serialized classes.
Can I use Spring Cache with Redis Cluster?
Yes. The cache abstraction is agnostic to the underlying topology. Configure spring.data.redis.cluster.nodes and Spring Data Redis handles routing.
How do I monitor cache hit rates in Spring?
Enable Micrometer metrics:
management:
metrics:
enable:
cache: trueThen observe cache.gets, cache.hits, and cache.misses in your metrics dashboard.
Is RedisTemplate thread-safe?
Yes. Once configured, RedisTemplate (and StringRedisTemplate) can be shared across multiple threads. Under Lettuce, the connection itself is multiplexed across threads safely.