编解码器
Spring Integration 的 4.2 版本引入了 Codec
抽象。Codec 对对象进行编码和解码,使其与 byte[]
之间进行转换。它们提供了 Java 序列化的替代方案。一个优点是,通常情况下,对象无需实现 Serializable
。我们提供了一个实现,该实现使用 Kryo 进行序列化,但你可以提供自己的实现,以便在以下任何组件中使用
-
EncodingPayloadTransformer
-
DecodingTransformer
-
CodecMessageConverter
EncodingPayloadTransformer
此转换器使用 codec 将有效负载编码为 byte[]
。它不影响消息头。
有关更多信息,请参阅 Javadoc。
DecodingTransformer
此转换器使用 codec 对 byte[]
进行解码。它需要使用要将对象解码到的 Class
(或解析为 Class
的表达式)进行配置。如果结果对象是 Message<?>
,则不会保留入站头。
有关更多信息,请参阅 Javadoc。
CodecMessageConverter
某些端点(如 TCP 和 Redis)没有消息头概念。它们支持使用 MessageConverter
,CodecMessageConverter
可用于将消息转换为 byte[]
或从 byte[]
转换消息,以便传输。
有关更多信息,请参阅 Javadoc。
Kryo
目前,这是Codec
的唯一实现,它提供了两种Codec
-
PojoCodec
:用于转换器 -
MessageCodec
:用于CodecMessageConverter
框架提供了几个自定义序列化器
-
FileSerializer
-
MessageHeadersSerializer
-
MutableMessageHeadersSerializer
第一个可以通过使用FileKryoRegistrar
初始化与PojoCodec
一起使用。第二个和第三个与MessageCodec
一起使用,该MessageCodec
使用MessageKryoRegistrar
初始化。
自定义 Kryo
默认情况下,Kryo 将未知 Java 类型委托给其FieldSerializer
。Kryo 还为每个基本类型注册了默认序列化器,以及String
、Collection
和Map
。FieldSerializer
使用反射来浏览对象图。一种更有效的方法是实现一个自定义序列化器,该序列化器了解对象的结构并可以直接序列化选定的基本字段。以下示例显示了这样的序列化器
public class AddressSerializer extends Serializer<Address> {
@Override
public void write(Kryo kryo, Output output, Address address) {
output.writeString(address.getStreet());
output.writeString(address.getCity());
output.writeString(address.getCountry());
}
@Override
public Address read(Kryo kryo, Input input, Class<Address> type) {
return new Address(input.readString(), input.readString(), input.readString());
}
}
Serializer
接口公开了Kryo
、Input
和Output
,它们提供了对包含哪些字段和其他内部设置的完全控制,如Kryo 文档中所述。
在注册自定义序列化器时,您需要一个注册 ID。注册 ID 是任意的。但是,在我们的情况下,必须明确定义 ID,因为分布式应用程序中的每个 Kryo 实例都必须使用相同的 ID。Kryo 推荐使用小的正整数,并保留几个 ID(值 < 10)。Spring Integration 目前默认使用 40、41 和 42(用于前面提到的文件和消息头序列化器)。我们建议您从 60 开始,以允许框架扩展。您可以通过配置前面提到的注册器来覆盖这些框架默认值。 |
使用自定义 Kryo 序列化器
如果您需要自定义序列化,请参阅Kryo文档,因为您需要使用本机 API 进行自定义。有关示例,请参阅org.springframework.integration.codec.kryo.MessageCodec
实现。
实现 KryoSerializable
如果您对域对象源代码具有write
访问权限,则可以按此处所述实现KryoSerializable
。在这种情况下,类本身提供序列化方法,不需要进一步配置。但是,基准测试表明,这不如显式注册自定义序列化器那么有效。以下示例显示了自定义 Kryo 序列化器
public class Address implements KryoSerializable {
@Override
public void write(Kryo kryo, Output output) {
output.writeString(this.street);
output.writeString(this.city);
output.writeString(this.country);
}
@Override
public void read(Kryo kryo, Input input) {
this.street = input.readString();
this.city = input.readString();
this.country = input.readString();
}
}
您还可以使用此技术来包装 Kryo 以外的其他序列化库。
使用 @DefaultSerializer
注解
Kryo 还提供了一个 @DefaultSerializer
注解,如 此处 所述。
@DefaultSerializer(SomeClassSerializer.class)
public class SomeClass {
// ...
}
如果您对域对象拥有 write
访问权限,这可能是指定自定义序列化程序的一种更简单的方法。请注意,这不会使用 ID 注册类,这可能使该技术对某些情况无用。