+ rename SimpleRedisSerializer to JdkSerializationRedisSerializer

+ add GenericToStringSerializer (cannot make it the default since the Class<T> is required)
+ add dedicated StringRedisTemplate
This commit is contained in:
Costin Leau
2010-12-09 13:37:18 +02:00
parent ea20533a37
commit 5fc53cec9c
7 changed files with 178 additions and 27 deletions

View File

@@ -35,8 +35,8 @@ import org.springframework.data.keyvalue.redis.connection.DataType;
import org.springframework.data.keyvalue.redis.connection.RedisConnection;
import org.springframework.data.keyvalue.redis.connection.RedisConnectionFactory;
import org.springframework.data.keyvalue.redis.connection.SortParameters;
import org.springframework.data.keyvalue.redis.serializer.JdkSerializationRedisSerializer;
import org.springframework.data.keyvalue.redis.serializer.RedisSerializer;
import org.springframework.data.keyvalue.redis.serializer.SimpleRedisSerializer;
import org.springframework.data.keyvalue.redis.serializer.StringRedisSerializer;
import org.springframework.transaction.support.TransactionSynchronizationManager;
import org.springframework.util.Assert;
@@ -46,6 +46,8 @@ import org.springframework.util.ClassUtils;
* Helper class that simplifies Redis data access code.
* <p/>
* Performs automatic serialization/deserialization between the given objects and the underlying binary data in the Redis store.
* By default, it uses Java serialization for its objects (through {@link JdkSerializationRedisSerializer}). For String intensive
* operations consider the dedicated {@link StringRedisTemplate}.
* <p/>
* The central method is execute, supporting Redis access code implementing the {@link RedisCallback} interface.
* It provides {@link RedisConnection} handling such that neither the {@link RedisCallback} implementation nor
@@ -55,23 +57,23 @@ import org.springframework.util.ClassUtils;
* Once configured, this class is thread-safe.
*
* <p/>Note that while the template is generified, it is up to the serializers/deserializers to properly convert the given Objects
* to and from binary data. When using a generic serialization mechanism (such as Java serialization or JSON) the types lose their
* importance and can be skipped or only used as syntactic sugar.
* to and from binary data.
* <p/>
* <b>This is the central class in Redis support</b>.
*
* @author Costin Leau
* @param <K> the Redis key type against which the template works (usually a String)
* @param <V> the Redis value type against which the template works
* @see StringRedisTemplate
*/
public class RedisTemplate<K, V> extends RedisAccessor implements RedisOperations<K, V> {
private boolean exposeConnection = false;
private RedisSerializer keySerializer = new StringRedisSerializer();
private RedisSerializer valueSerializer = new SimpleRedisSerializer();
private RedisSerializer hashKeySerializer = new SimpleRedisSerializer();
private RedisSerializer hashValueSerializer = new SimpleRedisSerializer();
private RedisSerializer stringSerializer = new StringRedisSerializer();
private RedisSerializer keySerializer = new JdkSerializationRedisSerializer();
private RedisSerializer valueSerializer = new JdkSerializationRedisSerializer();
private RedisSerializer hashKeySerializer = new JdkSerializationRedisSerializer();
private RedisSerializer hashValueSerializer = new JdkSerializationRedisSerializer();
private RedisSerializer<String> stringSerializer = new StringRedisSerializer();
// cache singleton objects (where possible)
private final ValueOperations<K, V> valueOps = new DefaultValueOperations();
@@ -171,7 +173,7 @@ public class RedisTemplate<K, V> extends RedisAccessor implements RedisOperation
}
/**
* Sets the key serializer to be used by this template. Defaults to {@link SimpleRedisSerializer}.
* Sets the key serializer to be used by this template. Defaults to {@link JdkSerializationRedisSerializer}.
*
* @param serializer
*/
@@ -180,7 +182,7 @@ public class RedisTemplate<K, V> extends RedisAccessor implements RedisOperation
}
/**
* Sets the value serializer to be used by this template. Defaults to {@link SimpleRedisSerializer}.
* Sets the value serializer to be used by this template. Defaults to {@link JdkSerializationRedisSerializer}.
*
* @param serializer
*/
@@ -189,7 +191,7 @@ public class RedisTemplate<K, V> extends RedisAccessor implements RedisOperation
}
/**
* Sets the hash key (or field) serializer to be used by this template. Defaults to {@link SimpleRedisSerializer}.
* Sets the hash key (or field) serializer to be used by this template. Defaults to {@link JdkSerializationRedisSerializer}.
*
* @param hashKeySerializer The hashKeySerializer to set.
*/
@@ -198,7 +200,7 @@ public class RedisTemplate<K, V> extends RedisAccessor implements RedisOperation
}
/**
* Sets the hash value serializer to be used by this template. Defaults to {@link SimpleRedisSerializer}.
* Sets the hash value serializer to be used by this template. Defaults to {@link JdkSerializationRedisSerializer}.
*
* @param hashValueSerializer The hashValueSerializer to set.
*/
@@ -213,7 +215,7 @@ public class RedisTemplate<K, V> extends RedisAccessor implements RedisOperation
* @see ValueOperations#substract(Object, int, int)
* @param stringSerializer The stringValueSerializer to set.
*/
public void setStringSerializer(RedisSerializer<?> stringSerializer) {
public void setStringSerializer(RedisSerializer<String> stringSerializer) {
this.stringSerializer = stringSerializer;
}
@@ -261,7 +263,6 @@ public class RedisTemplate<K, V> extends RedisAccessor implements RedisOperation
return (key != null ? keySerializer.serialize(key) : null);
}
@SuppressWarnings("unchecked")
private byte[] rawString(String key) {
return (key != null ? stringSerializer.serialize(key) : null);
}

View File

@@ -0,0 +1,37 @@
/*
* Copyright 2010 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.keyvalue.redis.core;
import org.springframework.data.keyvalue.redis.serializer.RedisSerializer;
import org.springframework.data.keyvalue.redis.serializer.StringRedisSerializer;
/**
* String-focused extension of RedisTemplate. Since most operations against Redis are String based,
* this class provides a dedicated class that minimizes configuration of its more generic
* {@link template RedisTemplate} especially in terms of serializers.
*
* @author Costin Leau
*/
public class StringRedisTemplate extends RedisTemplate<String, String> {
public StringRedisTemplate() {
RedisSerializer<String> stringSerializer = new StringRedisSerializer();
setKeySerializer(stringSerializer);
setValueSerializer(stringSerializer);
setHashKeySerializer(stringSerializer);
setHashValueSerializer(stringSerializer);
}
}

View File

@@ -0,0 +1,108 @@
/*
* Copyright 2010 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.keyvalue.redis.serializer;
import java.nio.charset.Charset;
import org.springframework.beans.BeansException;
import org.springframework.beans.TypeConverter;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.core.convert.ConversionService;
import org.springframework.util.Assert;
/**
* Generic String to byte[] (and back) serializer. Relies on the Spring {@link ConversionService}
* to transform objects into String and vice versa. The Strings are convert into bytes and vice-versa
* using the specified charset (by default UTF-8).
*
* <b>Note:</b> The conversion service initialization happens automatically if the class is defined
* as a Spring bean.
*
* @author Costin Leau
*/
public class GenericToStringSerializer<T> implements RedisSerializer<T>, BeanFactoryAware {
private final Charset charset;
private Converter converter;
private Class<T> type;
public GenericToStringSerializer(Class<T> type) {
this(type, Charset.forName("UTF8"));
}
public GenericToStringSerializer(Class<T> type, Charset charset) {
Assert.notNull(type);
this.type = type;
this.charset = charset;
}
public void setConversionService(ConversionService conversionService) {
Assert.notNull(conversionService, "non null conversion service required");
converter = new Converter(conversionService);
}
public void setTypeConverter(TypeConverter typeConverter) {
Assert.notNull(typeConverter, "non null type converter required");
converter = new Converter(typeConverter);
}
@Override
public T deserialize(byte[] bytes) {
String string = new String(bytes, charset);
return converter.convert(string, type);
}
@Override
public byte[] serialize(T object) {
String string = converter.convert(object, String.class);
return string.getBytes(charset);
}
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
if (converter != null && beanFactory instanceof ConfigurableBeanFactory) {
ConfigurableBeanFactory cFB = (ConfigurableBeanFactory) beanFactory;
ConversionService conversionService = cFB.getConversionService();
converter = (conversionService != null ? new Converter(conversionService) : new Converter(
cFB.getTypeConverter()));
}
}
private class Converter {
private final ConversionService conversionService;
private final TypeConverter typeConverter;
public Converter(ConversionService conversionService) {
this.conversionService = conversionService;
this.typeConverter = null;
}
public Converter(TypeConverter typeConverter) {
this.conversionService = null;
this.typeConverter = typeConverter;
}
<T> T convert(Object value, Class<T> targetType) {
if (conversionService != null) {
return conversionService.convert(value, targetType);
}
return typeConverter.convertIfNecessary(value, targetType);
}
}
}

View File

@@ -21,12 +21,13 @@ import org.springframework.core.serializer.support.SerializingConverter;
import org.springframework.data.keyvalue.redis.UncategorizedRedisException;
/**
* Simple Redis serializer delegating to the default (Java based) serializer in Spring 3.
* Java Serialization Redis serializer.
* Delegates to the default (Java based) serializer in Spring 3.
*
* @author Mark Pollack
* @author Costin Leau
*/
public class SimpleRedisSerializer implements RedisSerializer<Object> {
public class JdkSerializationRedisSerializer implements RedisSerializer<Object> {
private Converter<Object, byte[]> serializer = new SerializingConverter();
private Converter<byte[], Object> deserializer = new DeserializingConverter();

View File

@@ -17,16 +17,19 @@ package org.springframework.data.keyvalue.redis.serializer;
import java.nio.charset.Charset;
import org.springframework.util.Assert;
/**
* Simple String to byte[] (and back) serializer. Relies on the specified charset
* (by default UTF-8) to properly convert the String into bytes and vice-versa.
*
* Useful when the interaction with the Redis happens mainly through Strings.
* Simple String to byte[] (and back) serializer. Converts Strings into bytes and vice-versa
* using the specified charset (by default UTF-8).
* <p/>
* Useful when the interaction with the Redis happens mainly through Strings.
*
* @author Costin Leau
*/
public class StringRedisSerializer implements RedisSerializer<String> {
private final static byte[] EMPTY_ARRAY = new byte[0];
private final Charset charset;
public StringRedisSerializer() {
@@ -34,6 +37,7 @@ public class StringRedisSerializer implements RedisSerializer<String> {
}
public StringRedisSerializer(Charset charset) {
Assert.notNull(charset);
this.charset = charset;
}
@@ -43,7 +47,7 @@ public class StringRedisSerializer implements RedisSerializer<String> {
}
@Override
public byte[] serialize(String object) {
return object.getBytes(charset);
public byte[] serialize(String string) {
return (string == null ? EMPTY_ARRAY : string.getBytes(charset));
}
}
}

View File

@@ -26,13 +26,13 @@ import org.junit.Test;
import org.springframework.data.keyvalue.redis.Address;
import org.springframework.data.keyvalue.redis.Person;
import org.springframework.data.keyvalue.redis.serializer.RedisSerializer;
import org.springframework.data.keyvalue.redis.serializer.SimpleRedisSerializer;
import org.springframework.data.keyvalue.redis.serializer.JdkSerializationRedisSerializer;
import org.springframework.data.keyvalue.redis.serializer.StringRedisSerializer;
public abstract class AbstractConnectionIntegrationTests {
protected RedisConnection connection;
protected RedisSerializer serializer = new SimpleRedisSerializer();
protected RedisSerializer serializer = new JdkSerializationRedisSerializer();
protected RedisSerializer stringSerializer = new StringRedisSerializer();
private static final String listName = "test-list";

View File

@@ -26,7 +26,7 @@ import org.junit.Test;
import org.springframework.data.keyvalue.redis.Address;
import org.springframework.data.keyvalue.redis.Person;
import org.springframework.data.keyvalue.redis.serializer.RedisSerializer;
import org.springframework.data.keyvalue.redis.serializer.SimpleRedisSerializer;
import org.springframework.data.keyvalue.redis.serializer.JdkSerializationRedisSerializer;
public class SimpleRedisSerializerTests {
@@ -103,7 +103,7 @@ public class SimpleRedisSerializerTests {
@Before
public void setUp() {
serializer = new SimpleRedisSerializer();
serializer = new JdkSerializationRedisSerializer();
}
@After