Spring Boot and RESTful API(五)Redis
Spring Boot and RESTful API(5)Redis
Spring Boot and RESTful API(5)Redis
Redis Connection
scan only supported after 2.8.0
https://redis.io/commands/scan
I am using /opt/redis-2.6.14. I need to update my Redis on local machine first.
>wget http://download.redis.io/releases/redis-3.2.9.tar.gz
unzip the file and build the binary
>make
>mkdir /Users/carl/tool/redis-3.2.9
>mkdir /Users/carl/tool/redis-3.2.9/bin
>mkdir /Users/carl/tool/redis-3.2.9/conf
>cp src/redis-server /Users/carl/tool/redis-3.2.9/bin/
>cp src/redis-benchmark /Users/carl/tool/redis-3.2.9/bin/
>cp src/redis-cli /Users/carl/tool/redis-3.2.9/bin/
>cp redis.conf /Users/carl/tool/redis-3.2.9/conf/
Start the Server
>nohup bin/redis-server conf/redis.conf &
Configuration and Code for Spring Redis
pom.xml to include the package
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
YAML configuration file application.yaml
spring:
profiles:
active: dev
redis:
database: 0
host: localhost
port: 6379
Directly have a test Class on the RedisTemplate, RedisTemplateTest.java
package com.sillycat.jobsmonitorapi.repository;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.Cursor;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ScanOptions;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.util.Assert;
@RunWith(SpringRunner.class)
@SpringBootTest
public class RedisTemplateTest {
@Autowired
RedisTemplate<String, String> redisTemplate;
@Test
public void testStringCRUD() {
String key = "language";
String value = "java";
this.redisTemplate.opsForValue().set(key, value);
String result1 = redisTemplate.opsForValue().get(key);
Assert.isTrue(value.equals(result1), "Wrong data from Redis");
this.redisTemplate.delete(key);
String result2 = redisTemplate.opsForValue().get(key);
Assert.isNull(result2, "Data is not deleted successfully from Redis");
}
@Test
public void testScanning() {
this.redisTemplate.opsForValue().set("cache_geo_lat_long_info_by_zipcode_13434", "1");
this.redisTemplate.opsForValue().set("cache_geo_lat_long_info_by_zipcode_12", "2");
this.redisTemplate.opsForValue().set("cache_geo_lat_long_info_by_zipcode_1234", "2");
String pattern = "cache_geo_lat_long_info_by_zipcode_*";
ScanOptions.ScanOptionsBuilder scanOptionsBuilder = new ScanOptions.ScanOptionsBuilder();
scanOptionsBuilder.match(pattern);
Cursor<byte[]> cursors = this.redisTemplate.getConnectionFactory().getConnection().scan(scanOptionsBuilder.build());
for(;cursors.hasNext();){
String tempKey = new String(cursors.next());
if(tempKey.length() == "cache_geo_lat_long_info_by_zipcode_".length() + 4){
System.out.println("find and deleting----------------" + tempKey);
redisTemplate.delete(tempKey);
}
}
String result1 = redisTemplate.opsForValue().get("cache_geo_lat_long_info_by_zipcode_1234");
Assert.isNull(result1, "Data is not deleted successfully from Redis");
}
}
Serializer Object
sample POJO
package
com.sillycat.jobsmonitorapi.domain;
import java.io.Serializable;
public class User implements Serializable{
private static final long serialVersionUID = -4062728253774262930L;
private String userName;
private Integer age;
public User(String userName, Integer age){
this.userName = userName;
this.age = age;
}
..snip.. getter and setter
}
Redis Helper
package com.sillycat.jobsmonitorapi.repository;
import org.springframework.core.convert.converter.Converter;
import org.springframework.core.serializer.support.DeserializingConverter;
import org.springframework.core.serializer.support.SerializingConverter;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.SerializationException;
public class RedisObjectSerializer implements RedisSerializer<Object> {
private Converter<Object, byte[]> serializer = new SerializingConverter();
private Converter<byte[], Object> deserializer = new DeserializingConverter();
static final byte[] EMPTY_ARRAY = new byte[0];
public Object deserialize(byte[] bytes) {
if (isEmpty(bytes)) {
return null;
}
try {
return deserializer.convert(bytes);
} catch (Exception ex) {
throw new SerializationException("Cannot deserialize", ex);
}
}
public byte[] serialize(Object object) {
if (object == null) {
return EMPTY_ARRAY;
}
try {
return serializer.convert(object);
} catch (Exception ex) {
return EMPTY_ARRAY;
}
}
private boolean isEmpty(byte[] data) {
return (data == null || data.length == 0);
}
}
Redis Config
package com.sillycat.jobsmonitorapi.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import com.sillycat.jobsmonitorapi.domain.User;
import com.sillycat.jobsmonitorapi.repository.RedisObjectSerializer;
@Configuration
public class RedisConfig {
@Bean
JedisConnectionFactory jedisConnectionFactory() {
return new JedisConnectionFactory();
}
@Bean
public RedisTemplate<String, User> redisTemplate(RedisConnectionFactory factory) {
RedisTemplate<String, User> template = new RedisTemplate<String, User>();
template.setConnectionFactory(jedisConnectionFactory());
template.setKeySerializer(new StringRedisSerializer());
template.setValueSerializer(new RedisObjectSerializer());
return template;
}
}
Extend the Tester
package com.sillycat.jobsmonitorapi.repository;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.Cursor;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ScanOptions;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.util.Assert;
import com.sillycat.jobsmonitorapi.domain.User;
@RunWith(SpringRunner.class)
@SpringBootTest
public class RedisTemplateTest {
@Autowired
RedisTemplate<String, String> redisTemplateString;
@Autowired
RedisTemplate<String, User> redisTemplateUser;
@Test
public void testStringCRUD() {
String key = "language";
String value = "java";
this.redisTemplateString.opsForValue().set(key, value);
String result1 = redisTemplateString.opsForValue().get(key);
Assert.isTrue(value.equals(result1), "Wrong data from Redis");
this.redisTemplateString.delete(key);
String result2 = redisTemplateString.opsForValue().get(key);
Assert.isNull(result2, "Data is not deleted successfully from Redis");
}
@Test
public void testScanning() {
this.redisTemplateString.opsForValue().set("cache_geo_lat_long_info_by_zipcode_13434", "1");
this.redisTemplateString.opsForValue().set("cache_geo_lat_long_info_by_zipcode_12", "2");
this.redisTemplateString.opsForValue().set("cache_geo_lat_long_info_by_zipcode_1234", "2");
String pattern = "cache_geo_lat_long_info_by_zipcode_*";
ScanOptions.ScanOptionsBuilder scanOptionsBuilder = new ScanOptions.ScanOptionsBuilder();
scanOptionsBuilder.match(pattern);
Cursor<byte[]> cursors = this.redisTemplateString.getConnectionFactory().getConnection()
.scan(scanOptionsBuilder.build());
for (; cursors.hasNext();) {
String tempKey = new String(cursors.next());
if (tempKey.length() == "cache_geo_lat_long_info_by_zipcode_".length() + 4) {
redisTemplateString.delete(tempKey);
}
}
String result1 = redisTemplateString.opsForValue().get("cache_geo_lat_long_info_by_zipcode_1234");
Assert.isNull(result1, "Data is not deleted successfully from Redis");
}
@Test
public void testObjectUser() {
User user1 = new User("sillycat", 35);
redisTemplateUser.opsForValue().set(user1.getUserName(), user1);
User user2 = new User("kiko", 30);
redisTemplateUser.opsForValue().set(user2.getUserName(), user2);
Assert.isTrue(redisTemplateUser.opsForValue().get(user1.getUserName()).getAge().equals(user1.getAge()),
"age not equal");
Assert.isTrue(
redisTemplateUser.opsForValue().get(user2.getUserName()).getUserName().equals(user2.getUserName()),
"username not equal");
}
}
Bean Mapping
http://orika-mapper.github.io/orika-docs/intro.html
Learn from org.springside.modules.utils.mapper.BeanMapper
References:
https://stackoverflow.com/questions/17162725/spring-data-redis-redistemplate-exception/30484834#30484834
http://blog.didispace.com/springbootredis/
http://docs.spring.io/spring-data/redis/docs/1.6.2.RELEASE/reference/html/
Spring Boot and RESTful API(5)Redis
Redis Connection
scan only supported after 2.8.0
https://redis.io/commands/scan
I am using /opt/redis-2.6.14. I need to update my Redis on local machine first.
>wget http://download.redis.io/releases/redis-3.2.9.tar.gz
unzip the file and build the binary
>make
>mkdir /Users/carl/tool/redis-3.2.9
>mkdir /Users/carl/tool/redis-3.2.9/bin
>mkdir /Users/carl/tool/redis-3.2.9/conf
>cp src/redis-server /Users/carl/tool/redis-3.2.9/bin/
>cp src/redis-benchmark /Users/carl/tool/redis-3.2.9/bin/
>cp src/redis-cli /Users/carl/tool/redis-3.2.9/bin/
>cp redis.conf /Users/carl/tool/redis-3.2.9/conf/
Start the Server
>nohup bin/redis-server conf/redis.conf &
Configuration and Code for Spring Redis
pom.xml to include the package
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
YAML configuration file application.yaml
spring:
profiles:
active: dev
redis:
database: 0
host: localhost
port: 6379
Directly have a test Class on the RedisTemplate, RedisTemplateTest.java
package com.sillycat.jobsmonitorapi.repository;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.Cursor;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ScanOptions;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.util.Assert;
@RunWith(SpringRunner.class)
@SpringBootTest
public class RedisTemplateTest {
@Autowired
RedisTemplate<String, String> redisTemplate;
@Test
public void testStringCRUD() {
String key = "language";
String value = "java";
this.redisTemplate.opsForValue().set(key, value);
String result1 = redisTemplate.opsForValue().get(key);
Assert.isTrue(value.equals(result1), "Wrong data from Redis");
this.redisTemplate.delete(key);
String result2 = redisTemplate.opsForValue().get(key);
Assert.isNull(result2, "Data is not deleted successfully from Redis");
}
@Test
public void testScanning() {
this.redisTemplate.opsForValue().set("cache_geo_lat_long_info_by_zipcode_13434", "1");
this.redisTemplate.opsForValue().set("cache_geo_lat_long_info_by_zipcode_12", "2");
this.redisTemplate.opsForValue().set("cache_geo_lat_long_info_by_zipcode_1234", "2");
String pattern = "cache_geo_lat_long_info_by_zipcode_*";
ScanOptions.ScanOptionsBuilder scanOptionsBuilder = new ScanOptions.ScanOptionsBuilder();
scanOptionsBuilder.match(pattern);
Cursor<byte[]> cursors = this.redisTemplate.getConnectionFactory().getConnection().scan(scanOptionsBuilder.build());
for(;cursors.hasNext();){
String tempKey = new String(cursors.next());
if(tempKey.length() == "cache_geo_lat_long_info_by_zipcode_".length() + 4){
System.out.println("find and deleting----------------" + tempKey);
redisTemplate.delete(tempKey);
}
}
String result1 = redisTemplate.opsForValue().get("cache_geo_lat_long_info_by_zipcode_1234");
Assert.isNull(result1, "Data is not deleted successfully from Redis");
}
}
Serializer Object
sample POJO
package
com.sillycat.jobsmonitorapi.domain;
import java.io.Serializable;
public class User implements Serializable{
private static final long serialVersionUID = -4062728253774262930L;
private String userName;
private Integer age;
public User(String userName, Integer age){
this.userName = userName;
this.age = age;
}
..snip.. getter and setter
}
Redis Helper
package com.sillycat.jobsmonitorapi.repository;
import org.springframework.core.convert.converter.Converter;
import org.springframework.core.serializer.support.DeserializingConverter;
import org.springframework.core.serializer.support.SerializingConverter;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.SerializationException;
public class RedisObjectSerializer implements RedisSerializer<Object> {
private Converter<Object, byte[]> serializer = new SerializingConverter();
private Converter<byte[], Object> deserializer = new DeserializingConverter();
static final byte[] EMPTY_ARRAY = new byte[0];
public Object deserialize(byte[] bytes) {
if (isEmpty(bytes)) {
return null;
}
try {
return deserializer.convert(bytes);
} catch (Exception ex) {
throw new SerializationException("Cannot deserialize", ex);
}
}
public byte[] serialize(Object object) {
if (object == null) {
return EMPTY_ARRAY;
}
try {
return serializer.convert(object);
} catch (Exception ex) {
return EMPTY_ARRAY;
}
}
private boolean isEmpty(byte[] data) {
return (data == null || data.length == 0);
}
}
Redis Config
package com.sillycat.jobsmonitorapi.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import com.sillycat.jobsmonitorapi.domain.User;
import com.sillycat.jobsmonitorapi.repository.RedisObjectSerializer;
@Configuration
public class RedisConfig {
@Bean
JedisConnectionFactory jedisConnectionFactory() {
return new JedisConnectionFactory();
}
@Bean
public RedisTemplate<String, User> redisTemplate(RedisConnectionFactory factory) {
RedisTemplate<String, User> template = new RedisTemplate<String, User>();
template.setConnectionFactory(jedisConnectionFactory());
template.setKeySerializer(new StringRedisSerializer());
template.setValueSerializer(new RedisObjectSerializer());
return template;
}
}
Extend the Tester
package com.sillycat.jobsmonitorapi.repository;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.Cursor;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ScanOptions;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.util.Assert;
import com.sillycat.jobsmonitorapi.domain.User;
@RunWith(SpringRunner.class)
@SpringBootTest
public class RedisTemplateTest {
@Autowired
RedisTemplate<String, String> redisTemplateString;
@Autowired
RedisTemplate<String, User> redisTemplateUser;
@Test
public void testStringCRUD() {
String key = "language";
String value = "java";
this.redisTemplateString.opsForValue().set(key, value);
String result1 = redisTemplateString.opsForValue().get(key);
Assert.isTrue(value.equals(result1), "Wrong data from Redis");
this.redisTemplateString.delete(key);
String result2 = redisTemplateString.opsForValue().get(key);
Assert.isNull(result2, "Data is not deleted successfully from Redis");
}
@Test
public void testScanning() {
this.redisTemplateString.opsForValue().set("cache_geo_lat_long_info_by_zipcode_13434", "1");
this.redisTemplateString.opsForValue().set("cache_geo_lat_long_info_by_zipcode_12", "2");
this.redisTemplateString.opsForValue().set("cache_geo_lat_long_info_by_zipcode_1234", "2");
String pattern = "cache_geo_lat_long_info_by_zipcode_*";
ScanOptions.ScanOptionsBuilder scanOptionsBuilder = new ScanOptions.ScanOptionsBuilder();
scanOptionsBuilder.match(pattern);
Cursor<byte[]> cursors = this.redisTemplateString.getConnectionFactory().getConnection()
.scan(scanOptionsBuilder.build());
for (; cursors.hasNext();) {
String tempKey = new String(cursors.next());
if (tempKey.length() == "cache_geo_lat_long_info_by_zipcode_".length() + 4) {
redisTemplateString.delete(tempKey);
}
}
String result1 = redisTemplateString.opsForValue().get("cache_geo_lat_long_info_by_zipcode_1234");
Assert.isNull(result1, "Data is not deleted successfully from Redis");
}
@Test
public void testObjectUser() {
User user1 = new User("sillycat", 35);
redisTemplateUser.opsForValue().set(user1.getUserName(), user1);
User user2 = new User("kiko", 30);
redisTemplateUser.opsForValue().set(user2.getUserName(), user2);
Assert.isTrue(redisTemplateUser.opsForValue().get(user1.getUserName()).getAge().equals(user1.getAge()),
"age not equal");
Assert.isTrue(
redisTemplateUser.opsForValue().get(user2.getUserName()).getUserName().equals(user2.getUserName()),
"username not equal");
}
}
Bean Mapping
http://orika-mapper.github.io/orika-docs/intro.html
Learn from org.springside.modules.utils.mapper.BeanMapper
References:
https://stackoverflow.com/questions/17162725/spring-data-redis-redistemplate-exception/30484834#30484834
http://blog.didispace.com/springbootredis/
http://docs.spring.io/spring-data/redis/docs/1.6.2.RELEASE/reference/html/