728x90
반응형
redis command를 날렸을 때 Key는 String, Value는 Object class로 받고 싶어서 커스텀 한 redisCodec입니다.
key는 io.lettuce.core.codec.StringCodec, value는 io.lettuce.core.codec.ByteArrayCodec 참조하여 구현
import io.lettuce.core.codec.RedisCodec;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.util.CharsetUtil;
import org.springframework.util.SerializationUtils;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.CharacterCodingException;
import java.nio.charset.Charset;
import java.nio.charset.CharsetEncoder;
import java.nio.charset.CoderResult;
public class ObjectValueCodec<T> implements RedisCodec<String, T> {
private static final byte[] EMPTY = new byte[0];
private final Charset charset = Charset.defaultCharset();
public ObjectValueCodec() {
}
@Override
public String decodeKey(ByteBuffer bytes) {
return Unpooled.wrappedBuffer(bytes).toString(charset);
}
@Override
public T decodeValue(ByteBuffer bytes) {
byte[] ba = getBytes(bytes);
return (T) SerializationUtils.deserialize(ba); // bytes to object
}
@Override
public ByteBuffer encodeKey(String key) {
return encodeAndAllocateBuffer(key);
}
@Override
public ByteBuffer encodeValue(T value) {
byte[] ba = SerializationUtils.serialize(value); // object to bytes
return ByteBuffer.wrap(ba);
}
private static byte[] getBytes(ByteBuffer buffer) {
int remaining = buffer.remaining();
if (remaining == 0) {
return EMPTY;
}
byte[] b = new byte[remaining];
buffer.get(b);
return b;
}
private ByteBuffer encodeAndAllocateBuffer(String key) {
if (key == null) {
return ByteBuffer.wrap(EMPTY);
}
CharsetEncoder encoder = CharsetUtil.encoder(charset);
ByteBuffer buffer = ByteBuffer.allocate((int) (encoder.maxBytesPerChar() * key.length()));
ByteBuf byteBuf = Unpooled.wrappedBuffer(buffer);
byteBuf.clear();
encode(key, byteBuf);
buffer.limit(byteBuf.writerIndex());
return buffer;
}
private void encode(String str, ByteBuf target) {
if (str == null) {
return;
}
CharsetEncoder encoder = CharsetUtil.encoder(charset);
int length = (int) ((double) str.length() * encoder.maxBytesPerChar());
target.ensureWritable(length);
try {
final ByteBuffer dstBuf = target.nioBuffer(0, length);
final int pos = dstBuf.position();
CoderResult cr = encoder.encode(CharBuffer.wrap(str), dstBuf, true);
if (!cr.isUnderflow()) {
cr.throwException();
}
cr = encoder.flush(dstBuf);
if (!cr.isUnderflow()) {
cr.throwException();
}
target.writerIndex(target.writerIndex() + dstBuf.position() - pos);
} catch (CharacterCodingException x) {
throw new IllegalStateException(x);
}
}
}
사용법
@Bean
public RedisCommands<String, UserInfoVO> userRedisCommands() {
return redisClient.connect(new ObjectValueCodec<UserInfoVO>()).sync();
}
728x90
반응형
댓글