1. 异常场景

项目初始集成redis使用的是默认的lettuce客户端,后来因为业务需要切换成redisson客户端 使用redisson客户端后获取原先存入redis中的值出现了报错: JsonParseException: Unexpected character (‘a’ (code 97)): Expected space separating root-level value

2. 解决方案

2.1 设置编解码格式StringCodec

获取所有数据的时候,无引号字符串无法通过JsonJacksonCodec进行解析导致后续报错,所以可以通过设置Codec的方式来进行处理

RMap map = redissonClient.getMap("key", StringCodec.INSTANCE);

Set> entries = map.readAllEntrySet();

缺点:如果原始数据中value存储的是对象,通过设置StringCodec取出的值也会是字符串格式,需要额外进行序列化操作。

2.1 自定义编码格式

默认JacksonCodec编码初始化包含有对象转换设置

protected void init(ObjectMapper objectMapper) {

objectMapper.setSerializationInclusion(Include.NON_NULL);

objectMapper.setVisibility(objectMapper.getSerializationConfig().getDefaultVisibilityChecker().withFieldVisibility(Visibility.ANY).withGetterVisibility(Visibility.NONE).withSetterVisibility(Visibility.NONE).withCreatorVisibility(Visibility.NONE));

objectMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);

objectMapper.enable(new JsonGenerator.Feature[]{Feature.WRITE_BIGDECIMAL_AS_PLAIN});

objectMapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);

objectMapper.enable(new MapperFeature[]{MapperFeature.SORT_PROPERTIES_ALPHABETICALLY});

}

自定义Codec

public class RedissonCodec extends BaseCodec {

protected final ObjectMapper mapObjectMapper;

/**

* @see

*/

private final Encoder encoder = new Encoder() {

@Override

public ByteBuf encode(Object in) throws IOException {

ByteBuf out = ByteBufAllocator.DEFAULT.buffer();

try {

ByteBufOutputStream os = new ByteBufOutputStream(out);

mapObjectMapper.writeValue((OutputStream) os, in);

return os.buffer();

} catch (IOException e) {

out.release();

throw e;

} catch (Exception e) {

out.release();

throw new IOException(e);

}

}

};

private final Decoder decoder = new Decoder() {

@Override

public Object decode(ByteBuf buf, State state) throws IOException {

return mapObjectMapper.readValue((InputStream) new ByteBufInputStream(buf), Object.class);

}

};

public RedissonCodec(ObjectMapper mapObjectMapper) {

this(mapObjectMapper, true);

}

public RedissonCodec(ObjectMapper mapObjectMapper, boolean copy) {

if (copy) {

this.mapObjectMapper = mapObjectMapper.copy();

} else {

this.mapObjectMapper = mapObjectMapper;

}

}

@Override

public Decoder getValueDecoder() {

return decoder;

}

@Override

public Encoder getValueEncoder() {

return encoder;

}

@Override

public ClassLoader getClassLoader() {

if (mapObjectMapper.getTypeFactory().getClassLoader() != null) {

return mapObjectMapper.getTypeFactory().getClassLoader();

}

return super.getClassLoader();

}

}

自定义utils类

public final class RedisUtils {

public static final Codec REDISSON_CODEC;

static {

ObjectMapper om = new ObjectMapper();

om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);

om.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);

REDISSON_CODEC = new RedissonCodec(om);

}

private RedisUtils() {}

}

访问发现还存在报错:

ERROR 20964 --- [isson-netty-2-2] o.r.client.handler.CommandDecoder : Unable to decode data. channel: [id: 0x0d57606b, L:/127.0.0.1:49377 - R:127.0.0.1/127.0.0.1:6379], reply: ReplayingDecoderByteBuf(ridx=47, widx=3583080), command: (HGETALL), promise: java.util.concurrent.CompletableFuture@6727c964[Not completed, 1 dependents], params: [SYS:USER]

com.fasterxml.jackson.core.JsonParseException: Unexpected character ('a' (code 97)): Expected space separating root-level values

at [Source: (io.netty.buffer.ByteBufInputStream); line: 1, column: 12]

还是存在拜纳姆解析问题,显示的JsonParseException解析异常,查看redis中数据,分析原因为hashkey为无引号字符串导致,因此需要额外处理一下hashkey键。

RedissonCodec中添加合适编解码对象

private final Decoder mapKeyDecoder = new Decoder() {

public Object decode(ByteBuf buf, State state) {

String str = buf.toString(CharsetUtil.UTF_8);

buf.readerIndex(buf.readableBytes());

return str;

}

};

private final Encoder mapKeyEncoder = new Encoder() {

public ByteBuf encode(Object in) throws IOException {

ByteBuf out = ByteBufAllocator.DEFAULT.buffer();

out.writeCharSequence(in.toString(), CharsetUtil.UTF_8);

return out;

}

};

@Override

public Decoder getMapKeyDecoder() {

return mapKeyDecoder;

}

@Override

public Encoder getMapKeyEncoder() {

return mapKeyEncoder;

}

获取数据代码:

RMap map = redissonClient.getMap("key", RedisUtils.REDISSON_CODEC);

Set> entries = map.readAllEntrySet();

精彩文章

评论可见,请评论后查看内容,谢谢!!!评论后请刷新页面。

发表评论

返回顶部暗黑模式