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.

Top Architect
Top Architect
Top Architect
Using Spring Cache with Redis for Efficient Data Caching in Java Applications

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=true

Step 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.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

JavaCacheaopspringSpringCache
Top Architect
Written by

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.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.