Spring Boot Redis
August 01, 2018
This page will walk through Spring Boot Data Redis example. Redis is an open source, in memory data-structure store that can be used as database, cache and message broker. Redis supports data-structure such as strings, hashes, lists, sets etc. Redis is a NoSQL storage and uses key/value to store data. Spring Boot provides spring-boot-starter-data-redis
for Redis dependencies. Redis connections are obtained using LettuceConnectionFactory
or JedisConnectionFactory
. Lettuce and Jedis are Java Redis clients. Spring Boot 2.0 uses Lettuce by default. Spring Data provides RedisTemplate
as the central class to interact with data in Redis store. To interact with string data, we can use string-focused extension StringRedisTemplate
of RedisTemplate
. Spring Data provides ListOperations
, SetOperations
, HashOperations
etc to perform operations on Redis data and we can directly inject them in our Spring applications.
Contents
Technologies Used
Find the technologies being used in our example.1. Java 9
2. Spring 5.0.7.RELEASE
3. Spring Boot 2.0.3.RELEASE
4. Maven 3.5.2
5. Eclipse Oxygen
Project Structure
Find the project structure of our demo application in Eclipse.
Maven File
Spring providesspring-boot-starter-data-redis
to resolve Redis dependencies. It provides basic auto configurations for Lettuce and Jedis client libraries. By default Spring Boot 2.0 uses Lettuce. To get pooled connection factory we need to provide commons-pool2
dependency. Find the Maven file.
pom.xml
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.concretepage</groupId> <artifactId>spring-boot-app</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>spring-boot-app</name> <description>Spring Boot Application</description> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.0.3.RELEASE</version> <relativePath/> </parent> <properties> <java.version>9</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-pool2</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <optional>true</optional> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
Using Lettuce Configurations
Spring Boot 2.0 starterspring-boot-starter-data-redis
resolves Lettuce by default. Spring provides LettuceConnectionFactory
to get connections. To get pooled connection factory we need to provide commons-pool2
on the classpath. To work with Lettuce we need following Maven dependencies.
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-pool2</artifactId> </dependency>
spring.redis.*
prefix with Lettuce pool connection properties. Find the Lettuce pool sample configurations.
application.properties
spring.redis.host=localhost spring.redis.port=6379 spring.redis.password= spring.redis.lettuce.pool.max-active=7 spring.redis.lettuce.pool.max-idle=7 spring.redis.lettuce.pool.min-idle=2 spring.redis.lettuce.pool.max-wait=-1ms spring.redis.lettuce.shutdown-timeout=200ms
max-wait
a negative value if we want to block indefinitely.
Using Jedis Configurations
By default Spring Boot 2.0 starterspring-boot-starter-data-redis
uses Lettuce. To use Jedis we need to exclude Lettuce dependency and include Jedis. Find the Maven dependencies to use Jedis.
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> <exclusions> <exclusion> <groupId>io.lettuce</groupId> <artifactId>lettuce-core</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> </dependency>
jedis
dependency will automatically resolve commons-pool2
on the classpath.
To configure Jedis pool we need to use
spring.redis.*
prefix with Jedis pool connection properties. Find the Jedis pool sample configurations.
application.properties
spring.redis.host=localhost spring.redis.port=6379 spring.redis.password= spring.redis.jedis.pool.max-active=7 spring.redis.jedis.pool.max-idle=7 spring.redis.jedis.pool.min-idle=2 spring.redis.jedis.pool.max-wait=-1ms
ListOperations
ListOperations
is used for Redis list specific operations. Find some of its methods.
leftPush(K key, V value): Prepends value to key.
rightPush(K key, V value): Appends value to key.
leftPop(K key): Removes and returns first element in list stored at key.
rightPop(K key): Removes and returns last element in list stored at key.
remove(K key, long count, Object value): Removes the first given number (count) of occurrences of value from the list stored at key.
index(K key, long index): Fetches element at index from list at key.
size(K key): Fetches the size of list stored at key.
Now find the example of
ListOperations
. Here we are performing create, read and delete operations.
FriendDAO.java
package com.concretepage.dao; import javax.annotation.Resource; import org.springframework.data.redis.core.ListOperations; import org.springframework.stereotype.Repository; import com.concretepage.Person; @Repository public class FriendDAO { private static final String KEY = "friendsKey"; @Resource(name="redisTemplate") private ListOperations<String, Person> opsForList; public void addFriend(Person person) { opsForList.leftPush(KEY, person); } public long getNumberOfFriends() { return opsForList.size(KEY); } public Person getFriendAtIndex(Integer index) { return opsForList.index(KEY, index); } public void removeFriend(Person p) { opsForList.remove(KEY, 1, p); } }
package com.concretepage; import java.io.Serializable; public class Person implements Serializable { private static final long serialVersionUID = 1L; private int id; private String name; private int age; public Person() { } public Person(int id, String name, int age) { this.id = id; this.name = name; this.age = age; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String toString() { return id +" - " + name + " - " + age; } @Override public boolean equals(final Object obj) { if (obj == null) { return false; } final Person person = (Person) obj; if (this == person) { return true; } else { return (this.name.equals(person.name) && this.age == person.age); } } @Override public int hashCode() { int hashno = 7; hashno = 13 * hashno + (name == null ? 0 : name.hashCode()); return hashno; } }
SetOperations
SetOperations
performs Redis set specific operations. Find some of its methods.
add(K key, V... values): Adds values to set at key.
members(K key): Fetches all elements of set at key.
size(K key): Fetches size of set at key.
remove(K key, Object... values): Removes given values from set at key and returns the number of removed elements.
Now find the example of
SetOperations
. Here we will perform create, read and delete operations.
FamilyDAO.java
package com.concretepage.dao; import java.util.Set; import javax.annotation.Resource; import org.springframework.data.redis.core.SetOperations; import org.springframework.stereotype.Repository; import com.concretepage.Person; @Repository public class FamilyDAO { private static final String KEY = "myFamilyKey"; @Resource(name="redisTemplate") private SetOperations<String, Person> setOps; public void addFamilyMembers(Person... persons) { setOps.add(KEY, persons); } public Set<Person> getFamilyMembers() { return setOps.members(KEY); } public long getNumberOfFamilyMembers() { return setOps.size(KEY); } public long removeFamilyMembers(Person... persons) { return setOps.remove(KEY, (Object[])persons); } }
HashOperations
HashOperations
performs Redis map specific operations working on a hash. Find some of its methods.
putIfAbsent(H key, HK hashKey, HV value): Sets the value of a hash
hashKey
only if hashKey does not exist.
put(H key, HK hashKey, HV value): Sets the value of a hash
hashKey
.
get(H key, Object hashKey): Fetches value for given
hashKey
from hash at key.
size(H key): Fetches size of hash at key.
entries(H key): Fetches entire hash stored at key.
delete(H key, Object... hashKeys): Deletes given hash
hashKeys
at key.
Find the example of
HashOperations
with create, read, update and delete (CRUD) operations.
EmployeeDAO.java
package com.concretepage.dao; import java.util.Map; import javax.annotation.Resource; import org.springframework.data.redis.core.HashOperations; import org.springframework.stereotype.Repository; import com.concretepage.Person; @Repository public class EmployeeDAO { private static final String KEY = "employeesKey"; @Resource(name="redisTemplate") private HashOperations<String, Integer, Person> hashOps; public void addEmployee(Person person) { hashOps.putIfAbsent(KEY, person.getId(), person); } public void updateEmployee(Person person) { hashOps.put(KEY, person.getId(), person); } public Person getEmployee(Integer id) { return hashOps.get(KEY, id); } public long getNumberOfEmployees() { return hashOps.size(KEY); } public Map<Integer, Person> getAllEmployees() { return hashOps.entries(KEY); } public long deleteEmployees(Integer... ids) { return hashOps.delete(KEY, (Object)ids); } }
StringRedisTemplate
StringRedisTemplate
is the string-focused extension of RedisTemplate
. Most of the time we perform Redis operations with string and hence Spring Data provides a dedicated template i.e. StringRedisTemplate
. Here we will discuss opsForValue()
method of StringRedisTemplate
that will return ValueOperations
. Find some of ValueOperations
methods.
setIfAbsent(K key, V value): Sets key to hold the string value if key is absent.
set(K key, V value): Sets value for key.
get(Object key): Fetches the value of key.
Now find the example of CRUD operations using
StringRedisTemplate
.
UserDAO.java
package com.concretepage.dao; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.stereotype.Repository; @Repository public class UserDAO { private static final String KEY = "userKey"; @Autowired private StringRedisTemplate stringRedisTemplate; public void addUserName(String uname) { stringRedisTemplate.opsForValue().setIfAbsent(KEY, uname); } public void updateUserName(String uname) { stringRedisTemplate.opsForValue().set(KEY, uname); } public String getUserName() { return stringRedisTemplate.opsForValue().get(KEY); } public void deleteUser() { stringRedisTemplate.delete(KEY); } }
RedisTemplate
RedisTemplate
is the central class to interact with the data in Redis store. It performs automatic serialization and deserialization between the given objects and binary data stored in Redis. To inject RedisTemplate
in our Spring Boot applications, we need to create RedisTemplate
bean in JavaConfig as following.
RedisConfig.java
package com.concretepage; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory; import org.springframework.data.redis.core.RedisTemplate; import com.concretepage.Person; @Configuration @ComponentScan("com.concretepage") public class RedisConfig { @Bean public RedisConnectionFactory redisConnectionFactory() { LettuceConnectionFactory connectionFactory = new LettuceConnectionFactory(); return connectionFactory; } @Bean public RedisTemplate<String, Person> redisTemplate() { RedisTemplate<String, Person> redisTemplate = new RedisTemplate<>(); redisTemplate.setConnectionFactory(redisConnectionFactory()); return redisTemplate; } }
RedisTemplate
in our DAO and can use it as following.
FriendDAO.java
package com.concretepage.dao; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Repository; import com.concretepage.Person; @Repository public class FriendDAO { private static final String KEY = "friendsKey"; @Autowired private RedisTemplate<String, Person> redisTemplate; public void addFriend(Person person) { redisTemplate.opsForList().leftPush(KEY, person); } public long getNumberOfFriends() { return redisTemplate.opsForList().size(KEY); } public Person getFriendAtIndex(Integer index) { return redisTemplate.opsForList().index(KEY, index); } public void removeFriend(Person p) { redisTemplate.opsForList().remove(KEY, 1, p); } }
Spring Boot Main Class
Here we are creating Spring Boot main class to execute the application and will test our DAO classes.SpringBootAppStarter.java
package com.concretepage; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.CommandLineRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import com.concretepage.dao.EmployeeDAO; import com.concretepage.dao.FamilyDAO; import com.concretepage.dao.FriendDAO; import com.concretepage.dao.UserDAO; @SpringBootApplication public class SpringBootAppStarter implements CommandLineRunner { @Autowired private FriendDAO friendDAO; @Autowired private FamilyDAO familyDAO; @Autowired private EmployeeDAO empDAO; @Autowired private UserDAO userDAO; public static void main(String[] args) throws Exception { SpringApplication.run(SpringBootAppStarter.class, args); } @Override public void run(String... args) throws Exception { System.out.println("--Example of ListOperations--"); Person p1 = new Person(1, "Mahesh", 30); friendDAO.addFriend(p1); Person p2 = new Person(2, "Krishna", 35); friendDAO.addFriend(p2); System.out.println("Number of friends: " + friendDAO.getNumberOfFriends()); System.out.println(friendDAO.getFriendAtIndex(1)); friendDAO.removeFriend(p2); System.out.println(friendDAO.getFriendAtIndex(1)); //It will return null, because value is deleted. System.out.println("--Example of SetOperations--"); Person p11 = new Person(101, "Ram", 30); Person p12 = new Person(102, "Lakshman", 25); Person p13 = new Person(103, "Bharat", 35); familyDAO.addFamilyMembers(p11, p12, p13); System.out.println("Number of Family members: " + familyDAO.getNumberOfFamilyMembers()); System.out.println(familyDAO.getFamilyMembers()); System.out.println("No. of Removed Family Members: " + familyDAO.removeFamilyMembers(p11, p12)); System.out.println(familyDAO.getFamilyMembers()); System.out.println("--Example of HashOperations--"); Person emp1 = new Person(11, "Ravan", 45); Person emp2 = new Person(12, "Kumbhkarn", 35); Person emp3 = new Person(13, "Vibhisan", 25); empDAO.addEmployee(emp1); empDAO.addEmployee(emp2); empDAO.addEmployee(emp3); System.out.println("No. of Employees: "+ empDAO.getNumberOfEmployees()); System.out.println(empDAO.getAllEmployees()); emp2.setAge(20); empDAO.updateEmployee(emp2); System.out.println(empDAO.getEmployee(12)); System.out.println("--Example of StringRedisTemplate--"); userDAO.addUserName("sriram"); System.out.println(userDAO.getUserName()); userDAO.updateUserName("srikrishna"); System.out.println(userDAO.getUserName()); userDAO.deleteUser(); System.out.println(userDAO.getUserName()); //It will return null, because value is deleted. } }
Run Application
To test our demo application, find the steps given below.1. Install and start Redis using the link.
2. If you are using Windows OS, you can install Cygwin first and then install Redis in it.
3. Redis will start on localhost at port 6379.
4. Download the project source code. Go to the root folder of the project using command prompt and run the command.
mvn spring-boot:run
References
Spring Boot Reference GuideSpring Data Redis Example