在上一篇中springboot 2.X 集成redis中提到了在spring-boot-starter-data-redis中使用JdkSerializationRedisSerializerl来实现序列化,

这里看下具体是如何实现的。

1.RedisSerializer接口

在spring-data-redis包下,有一个RedisSerializer接口,提供了序列化和反序列化的基本接口。

public interface RedisSerializer<T> {

	/**
* Serialize the given object to binary data.
*
* @param t object to serialize. Can be {@literal null}.
* @return the equivalent binary data. Can be {@literal null}.
*/
@Nullable
byte[] serialize(@Nullable T t) throws SerializationException; /**
* Deserialize an object from the given binary data.
*
* @param bytes object binary representation. Can be {@literal null}.
* @return the equivalent object instance. Can be {@literal null}.
*/
@Nullable
T deserialize(@Nullable byte[] bytes) throws SerializationException; /**
* Obtain a {@link RedisSerializer} using java serialization.<br />
* <strong>Note:</strong> Ensure that your domain objects are actually {@link java.io.Serializable serializable}.
*
* @return never {@literal null}.
* @since 2.1
*/
static RedisSerializer<Object> java() {
return java(null);
} /**
* Obtain a {@link RedisSerializer} using java serialization with the given {@link ClassLoader}.<br />
* <strong>Note:</strong> Ensure that your domain objects are actually {@link java.io.Serializable serializable}.
*
* @param classLoader the {@link ClassLoader} to use for deserialization. Can be {@literal null}.
* @return new instance of {@link RedisSerializer}. Never {@literal null}.
* @since 2.1
*/
static RedisSerializer<Object> java(@Nullable ClassLoader classLoader) {
return new JdkSerializationRedisSerializer(classLoader);
} /**
* Obtain a {@link RedisSerializer} that can read and write JSON using
* <a href="https://github.com/FasterXML/jackson-core">Jackson</a>.
*
* @return never {@literal null}.
* @since 2.1
*/
static RedisSerializer<Object> json() {
return new GenericJackson2JsonRedisSerializer();
} /**
* Obtain a simple {@link java.lang.String} to {@literal byte[]} (and back) serializer using
* {@link java.nio.charset.StandardCharsets#UTF_8 UTF-8} as the default {@link java.nio.charset.Charset}.
*
* @return never {@literal null}.
* @since 2.1
*/
static RedisSerializer<String> string() {
return StringRedisSerializer.UTF_8;
}
}

可以看到byte[] serialize(@Nullable T t)和T deserialize(@Nullable byte[] bytes)就是序列化和反序列化接口,并且下面还定义了java的JdkSerializationRedisSerializer序列化、json的GenericJackson2JsonRedisSerializer和string的StringRedisSerializer.UTF_8.

2.1 JdkSerializationRedisSerializer序列化

public class JdkSerializationRedisSerializer implements RedisSerializer<Object> {

	private final Converter<Object, byte[]> serializer;
private final Converter<byte[], Object> deserializer; /**
* Creates a new {@link JdkSerializationRedisSerializer} using the default class loader.
*/
public JdkSerializationRedisSerializer() {
this(new SerializingConverter(), new DeserializingConverter());
} /**
* Creates a new {@link JdkSerializationRedisSerializer} using a {@link ClassLoader}.
*
* @param classLoader the {@link ClassLoader} to use for deserialization. Can be {@literal null}.
* @since 1.7
*/
public JdkSerializationRedisSerializer(@Nullable ClassLoader classLoader) {
this(new SerializingConverter(), new DeserializingConverter(classLoader));
} /**
* Creates a new {@link JdkSerializationRedisSerializer} using a {@link Converter converters} to serialize and
* deserialize objects.
*
* @param serializer must not be {@literal null}
* @param deserializer must not be {@literal null}
* @since 1.7
*/
public JdkSerializationRedisSerializer(Converter<Object, byte[]> serializer, Converter<byte[], Object> deserializer) { Assert.notNull(serializer, "Serializer must not be null!");
Assert.notNull(deserializer, "Deserializer must not be null!"); this.serializer = serializer;
this.deserializer = deserializer;
} public Object deserialize(@Nullable byte[] bytes) { if (SerializationUtils.isEmpty(bytes)) {
return null;
} try {
return deserializer.convert(bytes);
} catch (Exception ex) {
throw new SerializationException("Cannot deserialize", ex);
}
} @Override
public byte[] serialize(@Nullable Object object) {
if (object == null) {
return SerializationUtils.EMPTY_ARRAY;
}
try {
return serializer.convert(object);
} catch (Exception ex) {
throw new SerializationException("Cannot serialize", ex);
}
}
}

在JdkSerializationRedisSerializer构造方法中,传入了Converter的两个对象,serialize的序列化就使用SerializingConverter的convert方法

public byte[] convert(Object source) {
try {
return this.serializer.serializeToByteArray(source);
}
catch (Throwable ex) {
throw new SerializationFailedException("Failed to serialize object using " +
this.serializer.getClass().getSimpleName(), ex);
}
}

Serializer 接口

void serialize(T object, OutputStream outputStream) throws IOException;

default byte[] serializeToByteArray(T object) throws IOException {
ByteArrayOutputStream out = new ByteArrayOutputStream(1024);
serialize(object, out);
return out.toByteArray();
}

在这里JdkSerializationRedisSerializer中,使用的是DefaultSerializer,它实现了serialize方法:

public class DefaultSerializer implements Serializer<Object> {

	/**
* Writes the source object to an output stream using Java serialization.
* The source object must implement {@link Serializable}.
* @see ObjectOutputStream#writeObject(Object)
*/
@Override
public void serialize(Object object, OutputStream outputStream) throws IOException {
if (!(object instanceof Serializable)) {
throw new IllegalArgumentException(getClass().getSimpleName() + " requires a Serializable payload " +
"but received an object of type [" + object.getClass().getName() + "]");
}
ObjectOutputStream objectOutputStream = new ObjectOutputStream(outputStream);
objectOutputStream.writeObject(object);
objectOutputStream.flush();
} }

可以看到使用了ObjectOutputStream的writeObject方法来实现的,下面会继续调用writeObject0方法,相关可以查看ObjectOutputStream的序列化和反序列化

JdkSerializationRedisSerializer的反序列化方式转化类型有区别,这里就不详细介绍了。

2.2 GenericJackson2JsonRedisSerializer序列化

GenericJackson2JsonRedisSerializer主要使用ObjectMapper来实现。

@Override
public byte[] serialize(@Nullable Object source) throws SerializationException { if (source == null) {
return SerializationUtils.EMPTY_ARRAY;
} try {
return mapper.writeValueAsBytes(source);
} catch (JsonProcessingException e) {
throw new SerializationException("Could not write JSON: " + e.getMessage(), e);
}
} @Override
public Object deserialize(@Nullable byte[] source) throws SerializationException {
return deserialize(source, Object.class);
}
public <T> T deserialize(@Nullable byte[] source, Class<T> type) throws SerializationException { Assert.notNull(type,
"Deserialization type must not be null! Please provide Object.class to make use of Jackson2 default typing."); if (SerializationUtils.isEmpty(source)) {
return null;
} try {
return mapper.readValue(source, type);
} catch (Exception ex) {
throw new SerializationException("Could not read JSON: " + ex.getMessage(), ex);
}
}

查看writeValueAsBytes方法,并且继续向下,可以看到使用了jackson相关包进行json化数据。

private final void _serialize(JsonGenerator gen, Object value,
JsonSerializer<Object> ser, PropertyName rootName)
throws IOException
{
try {
gen.writeStartObject();
gen.writeFieldName(rootName.simpleAsEncoded(_config));
ser.serialize(value, gen, this);
gen.writeEndObject();
} catch (Exception e) {
throw _wrapAsIOE(gen, e);
}
}

2.3 StringRedisSerializer

StringRedisTemplate中使用了UTF_8的编码格式。

public class StringRedisSerializer implements RedisSerializer<String> {

	private final Charset charset;

	/**
* {@link StringRedisSerializer} to use 7 bit ASCII, a.k.a. ISO646-US, a.k.a. the Basic Latin block of the Unicode
* character set.
*
* @see StandardCharsets#US_ASCII
* @since 2.1
*/
public static final StringRedisSerializer US_ASCII = new StringRedisSerializer(StandardCharsets.US_ASCII); /**
* {@link StringRedisSerializer} to use ISO Latin Alphabet No. 1, a.k.a. ISO-LATIN-1.
*
* @see StandardCharsets#ISO_8859_1
* @since 2.1
*/
public static final StringRedisSerializer ISO_8859_1 = new StringRedisSerializer(StandardCharsets.ISO_8859_1); /**
* {@link StringRedisSerializer} to use 8 bit UCS Transformation Format.
*
* @see StandardCharsets#UTF_8
* @since 2.1
*/
public static final StringRedisSerializer UTF_8 = new StringRedisSerializer(StandardCharsets.UTF_8); /**
* Creates a new {@link StringRedisSerializer} using {@link StandardCharsets#UTF_8 UTF-8}.
*/
public StringRedisSerializer() {
this(StandardCharsets.UTF_8);
} /**
* Creates a new {@link StringRedisSerializer} using the given {@link Charset} to encode and decode strings.
*
* @param charset must not be {@literal null}.
*/
public StringRedisSerializer(Charset charset) { Assert.notNull(charset, "Charset must not be null!");
this.charset = charset;
} /*
* (non-Javadoc)
* @see org.springframework.data.redis.serializer.RedisSerializer#deserialize(byte[])
*/
@Override
public String deserialize(@Nullable byte[] bytes) {
return (bytes == null ? null : new String(bytes, charset));
} /*
* (non-Javadoc)
* @see org.springframework.data.redis.serializer.RedisSerializer#serialize(java.lang.Object)
*/
@Override
public byte[] serialize(@Nullable String string) {
return (string == null ? null : string.getBytes(charset));
} @Override
public Class<?> getTargetType() {
return String.class;
}
}

当你的redis数据库里面本来存的是字符串数据或者你要存取的数据就是字符串类型数据的时候,可以使用这种方式,非常简便。

谈谈spring-boot-starter-data-redis序列化的更多相关文章

  1. spring -boot s-tarter 详解

    Starter POMs是可以包含到应用中的一个方便的依赖关系描述符集合.你可以获取所有Spring及相关技术的一站式服务,而不需要翻阅示例代码,拷贝粘贴大量的依赖描述符.例如,如果你想使用Sprin ...

  2. SpringBoot 之Spring Boot Starter依赖包及作用

    Spring Boot 之Spring Boot Starter依赖包及作用 spring-boot-starter 这是Spring Boot的核心启动器,包含了自动配置.日志和YAML. spri ...

  3. Spring Boot Starter列表

    转自:http://blog.sina.com.cn/s/blog_798f713f0102wiy5.html Spring Boot Starter 基本的一共有43种,具体如下: 1)spring ...

  4. 【spring boot】【redis】spring boot 集成redis的发布订阅机制

    一.简单介绍 1.redis的发布订阅功能,很简单. 消息发布者和消息订阅者互相不认得,也不关心对方有谁. 消息发布者,将消息发送给频道(channel). 然后是由 频道(channel)将消息发送 ...

  5. Spring Boot 2整合Redis做缓存

    既然是要用Redis做缓存,自然少不了安装了.但是本文主要讲Spring Boot与Redis整合.安装教程请另行百度! 1.首先是我们的Redis配置类 package com.tyc; impor ...

  6. 【spring boot】【redis】spring boot基于redis的LUA脚本 实现分布式锁

    spring boot基于redis的LUA脚本 实现分布式锁[都是基于redis单点下] 一.spring boot 1.5.X 基于redis 的 lua脚本实现分布式锁 1.pom.xml &l ...

  7. Spring Boot Starter 介绍

    http://www.baeldung.com/spring-boot-starters 作者:baeldung 译者:http://oopsguy.com 1.概述 依赖管理是任何复杂项目的关键部分 ...

  8. Spring Boot (一): Spring Boot starter自定义

    前些日子在公司接触了spring boot和spring cloud,有感于其大大简化了spring的配置过程,十分方便使用者快速构建项目,而且拥有丰富的starter供开发者使用.但是由于其自动化配 ...

  9. Spring Boot + MyBatis + Druid + Redis + Thymeleaf 整合小结

    Spring Boot + MyBatis + Druid + Redis + Thymeleaf 整合小结 这两天闲着没事想利用**Spring Boot**加上阿里的开源数据连接池**Druid* ...

  10. spring boot 中使用redis session

    spring boot 默认的httpsession是存在内存中.这种默认方式有几个缺点:1.当分布式部署时,存在session不一致的问题:2.当服务重启时session就会丢失,这时候用户就需要重 ...

随机推荐

  1. PowerDesigner使用教程(二)

    在PowerDesigner使用教程(一)中已经介绍了基本用法,下面介绍一些使用技巧. 1.  生成sql脚本 Database→Generate Database 选择要输出的文件路径,即文件存储路 ...

  2. canvas锥形渐变进度条

    从一个渐变圆角进度条浅出画一个圆 开始 这一切需要从一个(简单)的需求开始,在最开始对设计第一眼看到这张图的时候,感觉挺简单的嘛,直接用echarts饼图模拟出来一个就好了 echarts 然后上ec ...

  3. 【QT】利用pyqt5实现简单界面

    Topic: 利用pyqt5编写简单界面Env:win10 + Pycharm2018 + Python 3.6.8Date: 2019/4/29 by hw_Chen2018            ...

  4. JS代码静态分析及挖掘

    JavaScript 已经成为现代 Web 浏览器开发中最普遍的技术之一.使用客户端 JavaScript 框架(如 AngularJS,ReactJS 和 Vue.js)构建的应用程序已向前端输送了 ...

  5. itext7史上最全实战总结

    1. itext7史上最全实战总结 1.1. 前言 最近有个需求需要我用Java手动写一份PDF报告,经过考察几种pdf开源代码,最终选取了itext7,此版本为7.1.11,由于发现网上关于该工具的 ...

  6. Rocket - diplomacy - ValName

    https://mp.weixin.qq.com/s/so-2x5KLfYF0IMCCqNThwQ   简单调试ValName实现:   1. 使用     ​​   Desugar之后如下: ​​ ...

  7. Rocket - diplomacy - DUEB参数模型的设计

    https://mp.weixin.qq.com/s/9PEEpe1pkQDN9RWpOGSUCQ   介绍DUEB参数模型的设计,不包含实现(实现对设计做了简化).     1. DUEB   di ...

  8. JavaScript (一) js的介绍及基本语法变量

    个人博客网:https://wushaopei.github.io/    (你想要这里多有) 一.JS 的 介绍 1.JavaScript :简称 : js js 分为三个部分: 1. ECMASc ...

  9. Java实现 LeetCode 680 验证回文字符串 Ⅱ(暴力)

    680. 验证回文字符串 Ⅱ 给定一个非空字符串 s,最多删除一个字符.判断是否能成为回文字符串. 示例 1: 输入: "aba" 输出: True 示例 2: 输入: " ...

  10. Java实现 LeetCode 639解码方法 2(递推)

    639. 解码方法 2 一条包含字母 A-Z 的消息通过以下的方式进行了编码: 'A' -> 1 'B' -> 2 ... 'Z' -> 26 除了上述的条件以外,现在加密字符串可以 ...