Using Spring Cache with Redis for Efficient Data Caching in Java Applications
This article explains how to accelerate service response by integrating Redis as a key‑value cache with Spring Cache, covering the three‑step implementation, required Maven dependencies, XML configuration, property settings, a custom Cache implementation class, and common Spring Cache annotations.
Caching is an effective way to speed up service responses, and Redis, as a key‑value database, is widely used for this purpose. Traditional cache handling code can be verbose, requiring three steps: check the cache before execution, query the database if missing, and store the result back in the cache.
Spring Cache provides AOP‑based support that eliminates boilerplate code; a simple annotation can enable caching without modifying existing business logic.
Step 1: Add required dependencies
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.9.0</version>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-redis</artifactId>
<version>1.6.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.3.2</version>
</dependency>Step 2: Configure Spring Cache and Redis connection
applicationContext-redis.xml
<?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"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:cache="http://www.springframework.org/schema/cache"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.2.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-4.2.xsd
http://www.springframework.org/schema/cache
http://www.springframework.org/schema/cache/spring-cache-4.2.xsd">
<!-- Load property files -->
<context:property-placeholder location="classpath:*.properties"/>
<cache:annotation-driven cache-manager="cacheManager"/>
<!-- Redis connection pool -->
<bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig">
<property name="maxIdle" value="${redis.maxIdle}"/>
<property name="maxWaitMillis" value="${redis.maxWait}"/>
<property name="testOnBorrow" value="${redis.testOnBorrow}"/>
</bean>
<!-- Connection factory -->
<bean id="JedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"
p:host-name="${redis.host}" p:port="${redis.port}" p:password="${redis.pass}" p:pool-config-ref="poolConfig"/>
<!-- Redis template -->
<bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
<property name="connectionFactory" ref="JedisConnectionFactory"/>
</bean>
<!-- Cache manager -->
<bean id="cacheManager" class="org.springframework.cache.support.SimpleCacheManager">
<property name="caches">
<set>
<bean class="com.cky.rest.utils.RedisCache">
<property name="redisTemplate" ref="redisTemplate"/>
<property name="name" value="content"/>
</bean>
</set>
</property>
</bean>
</beans>redis.properties
# Redis settings
redis.host=192.168.100.55
redis.port=6379
redis.pass=
redis.database=0
redis.maxIdle=300
redis.maxWait=3000
redis.testOnBorrow=trueStep 3: Implement a custom Cache class
package com.cky.rest.utils;
import java.io.Serializable;
import org.apache.commons.lang3.SerializationUtils;
import org.springframework.cache.Cache;
import org.springframework.cache.support.SimpleValueWrapper;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
public class RedisCache implements Cache {
private RedisTemplate<String, Object> redisTemplate;
private String name;
@Override
public void clear() {
System.out.println("-------緩存清理------");
redisTemplate.execute(new RedisCallback<String>() {
@Override
public String doInRedis(RedisConnection connection) throws DataAccessException {
connection.flushDb();
return "ok";
}
});
}
@Override
public void evict(Object key) {
System.out.println("-------緩存刪除------");
final String keyf = key.toString();
redisTemplate.execute(new RedisCallback<Long>() {
@Override
public Long doInRedis(RedisConnection connection) throws DataAccessException {
return connection.del(keyf.getBytes());
}
});
}
@Override
public ValueWrapper get(Object key) {
System.out.println("------缓存获取-------" + key.toString());
final String keyf = key.toString();
Object object = redisTemplate.execute(new RedisCallback<Object>() {
@Override
public Object doInRedis(RedisConnection connection) throws DataAccessException {
byte[] keyb = keyf.getBytes();
byte[] value = connection.get(keyb);
if (value == null) {
System.out.println("------缓存不存在-------");
return null;
}
return SerializationUtils.deserialize(value);
}
});
return (object != null) ? new SimpleValueWrapper(object) : null;
}
@Override
public void put(Object key, Object value) {
System.out.println("-------加入缓存------");
final String keyString = key.toString();
final Object valuef = value;
final long liveTime = 86400; // 1 day
redisTemplate.execute(new RedisCallback<Long>() {
@Override
public Long doInRedis(RedisConnection connection) throws DataAccessException {
byte[] keyb = keyString.getBytes();
byte[] valueb = SerializationUtils.serialize((Serializable) valuef);
connection.set(keyb, valueb);
if (liveTime > 0) {
connection.expire(keyb, liveTime);
}
return 1L;
}
});
}
// other Cache interface methods omitted for brevity
@Override public String getName() { return this.name; }
@Override public Object getNativeCache() { return this.redisTemplate; }
public void setRedisTemplate(RedisTemplate<String, Object> redisTemplate) { this.redisTemplate = redisTemplate; }
public void setName(String name) { this.name = name; }
}Common Spring Cache annotations:
@Cacheable : Caches the method return value. Requires a cache name (e.g., cacheNames="content") and optionally a key expression.
@CachePut : Executes the method and updates the cache with the result.
@CacheEvict : Removes entries from the cache; supports allEntries and beforeInvocation attributes.
Example usage of @Cacheable with a SpEL key and condition:
@Cacheable(cacheNames="content", key="#user.userId", condition="#user.age < 40")
public User getUser(User user) {
// method body
}The article also notes two typical configuration errors: missing JAR files causing ClassNotFoundException and version mismatches leading to MethodNotFoundException.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Top Architect
Top Architect focuses on sharing practical architecture knowledge, covering enterprise, system, website, large‑scale distributed, and high‑availability architectures, plus architecture adjustments using internet technologies. We welcome idea‑driven, sharing‑oriented architects to exchange and learn together.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
