缓存编码和 Marshalling
编码数据网格缓存和 marshall Java 对象
摘要
Red Hat Data Grid
Data Grid 是一个高性能分布式内存数据存储。
- 无架构数据结构
- 将不同对象存储为键值对的灵活性。
- 基于网格的数据存储
- 旨在在集群中分发和复制数据。
- 弹性扩展
- 动态调整节点数量,以便在不中断服务的情况下满足需求。
- 数据互操作性
- 从不同端点在网格中存储、检索和查询数据。
Data Grid 文档
红帽客户门户网站中提供了 Data Grid 的文档。
Data Grid 下载
访问 红帽客户门户上的 Data Grid 软件下载。
您必须有一个红帽帐户才能访问和下载数据中心软件。
使开源包含更多
红帽致力于替换我们的代码、文档和 Web 属性中存在问题的语言。我们从这四个术语开始:master、slave、黑名单和白名单。由于此项工作十分艰巨,这些更改将在即将推出的几个发行版本中逐步实施。有关更多详情,请参阅我们的首席技术官 Chris Wright 提供的消息。
第 1 章 配置缓存编码
了解如何使用不同介质类型配置 Data Grid 缓存,以及编码如何影响您可以使用 Data Grid 的方法。
1.1. 缓存编码
编码是由介质类型标识的格式,Data Grid 用于将条目(键/值对)存储在缓存中。
远程缓存
Data Grid Server 使用在缓存配置中设置的编码将条目存储在远程缓存中。
hot Rod 和 REST 客户端包括一个介质类型,其中包含他们向 Data Grid 服务器发出的每个请求。为了处理使用不同介质类型的多个客户端,Data Grid 服务器会将数据按需转换为缓存配置中设置的介质类型。
如果远程缓存没有任何编码配置,Data Grid 服务器会在没有任何介质类型信息的情况下将键和值存储为通用 byte[]
,这可能会在为客户端请求不同格式转换数据时造成意外的结果。
使用 ProtoStream 编码
当客户端请求包含无法转换为或从缓存配置中设置的介质类型时,数据网格服务器会返回错误。
如果要使用多个客户端,如 Data Grid Console 或 CLI、Hot Rod 或 REST,建议使用 application/x-protostream
介质类型配置缓存编码。ProtoStream 编码还允许您使用服务器端任务,并对远程缓存执行索引查询。
嵌入式缓存
默认情况下,数据仓库将条目存储在嵌入式缓存中,存为旧 Java 对象(POJO)。
对于集群嵌入式缓存,Data Grid 需要将所有 POJO 回一个字节阵列,该数组可以在节点间复制,然后取消合并回 POJO。这意味着,如果您没有配置另一个 marshaller,则必须确保数据仓库可以使用 ProtoStream marshaller 序列化您的 POJO。
如果您将 mutable POJO 存储在嵌入式缓存中,则应始终使用新的 POJO 实例更新值。例如,如果您将 HashMap
存储为键/值对,Data Grid 集群的其他成员不会看到对映射的任何本地修改。另外,如果在 Data Grid 编译对象的同时更新 Map 实例,则可能会出现 ConcurrentModificationException
。
1.2. protobuf 缓存编码
协议缓冲(Protobuf)是结构化数据的轻量级二进制介质类型。作为缓存编码,Protobuf 为您提供了面向 Hot Rod 和 REST 端点的不同编程语言之间的客户端应用程序之间的互操作性。
Data Grid 使用 ProtoStream 库,使用 application/x-protostream
介质类型将缓存编码为 Protobuf。
以下示例显示了描述 Person
对象的 Protobuf 信息:
message Person { optional int32 id = 1; optional string name = 2; optional string surname = 3; optional Address address = 4; repeated PhoneNumber phoneNumbers = 5; optional uint32 age = 6; enum Gender { MALE = 0; FEMALE = 1; } }
message Person {
optional int32 id = 1;
optional string name = 2;
optional string surname = 3;
optional Address address = 4;
repeated PhoneNumber phoneNumbers = 5;
optional uint32 age = 6;
enum Gender {
MALE = 0;
FEMALE = 1;
}
}
Copy to clipboardCopied互操作性
由于它是不受信任的语言,Protobuf 编码的意味着 Data Grid 可以处理来自使用 Java、C++、C++、Python、Go 等编写的客户端应用程序的请求。
protobuf 还使不同远程端点(Hot Rod 或 REST)上的客户端能够在同一数据上运行。由于它使用 REST API,您可以通过 Data Grid 控制台访问和使用 Protobuf 编码的缓存。
您不能将 Data Grid 控制台与 application/x-protostream
以外的任何二进制编码一起使用。
您应该始终将 Protobuf 缓存编码与 application/x-protostream
介质类型集成,以与任何红帽技术集成,因为它允许应用程序和服务之间的通信。
查询
Data Grid 需要缓存中数据的结构化表示,以便快速可靠的查询。要使用 Ickle 查询语言搜索缓存,您需要注册描述您的对象的 Protobuf 模式。
自定义类型
Data Grid 包括 ProtoStream API 的实现,它支持经常使用的类型,包括 String
和 Integer
。如果要在缓存中存储自定义类型,请使用 ProtoStream marshalling 生成并注册带有 Data Grid 的序列化上下文,以便它可以在所有对象中使用。
1.2.1. 将缓存编码为 ProtoStream
将 Data Grid 配置为使用 ProtoStream 库将缓存条目存储为协议缓冲(Protobuf)。
流程
-
为键和值指定
application/x-protostream
介质类型。
声明
<distributed-cache> <encoding> <key media-type="application/x-protostream"/> <value media-type="application/x-protostream"/> </encoding> </distributed-cache>
<distributed-cache>
<encoding>
<key media-type="application/x-protostream"/>
<value media-type="application/x-protostream"/>
</encoding>
</distributed-cache>
Copy to clipboardCopiedprogrammatic
//Create cache configuration that encodes keys and values as ProtoStream ConfigurationBuilder builder = new ConfigurationBuilder(); builder.clustering().cacheMode(CacheMode.DIST_SYNC) .encoding().key().mediaType("application/x-protostream") .encoding().value().mediaType("application/x-protostream");
//Create cache configuration that encodes keys and values as ProtoStream
ConfigurationBuilder builder = new ConfigurationBuilder();
builder.clustering().cacheMode(CacheMode.DIST_SYNC)
.encoding().key().mediaType("application/x-protostream")
.encoding().value().mediaType("application/x-protostream");
Copy to clipboardCopied或者,您也可以对键和值使用相同的编码:
声明
<encoding media-type="application/x-protostream"/>
<encoding media-type="application/x-protostream"/>
Copy to clipboardCopiedprogrammatic
.encoding().mediaType("application/x-protostream");
.encoding().mediaType("application/x-protostream");
Copy to clipboardCopied1.3. 基于文本的缓存编码
基于文本的编码是人类可读的内容,如纯文本。经典 "Hello World" 示例条目可以存储在缓存中,如下所示:
key=hello value=world
key=hello
value=world
Copy to clipboardCopied
如果您使用 文本/
解释介质类型对缓存进行编码,Data Grid 可以转换为并从以下介质类型转换:
-
application/xml
-
application/json
-
application/x-protostream
以下示例配置使用 text/plain 对键和值进行编码;charset=UTF-8
介质类型:
<distributed-cache> <encoding> <key media-type="text/plain; charset=UTF-8"/> <value media-type="text/plain; charset=UTF-8"/> </encoding> </distributed-cache>
<distributed-cache>
<encoding>
<key media-type="text/plain; charset=UTF-8"/>
<value media-type="text/plain; charset=UTF-8"/>
</encoding>
</distributed-cache>
Copy to clipboardCopied1.3.1. 客户端和基于文本的编码
如果您将编码配置为使用基于文本的介质类型存储键和值,那么您还需要配置客户端以便在这些缓存上运行。
hot Rod 客户端
Data Grid 使用 ProtoStream 库来原生处理 String
和 byte[]
类型。如果您使用 文本/
解释介质类型配置缓存编码,Hotot Rod 客户端可能不一定要求任何 marshaller 配置来执行缓存操作。
对于其他基于文本的介质类型,如 JSON 或 XML,Hotot Rod 客户端可以使用 org.infinispan.commons.marshall.UTF8StringMarshaller
marshaller marshaller,它们转换为 文本/
解释介质类型。
REST 客户端
REST 客户端必须在请求标头中包含缓存的介质类型。
例如,如果您将缓存编码配置为 文本/解释;charset=UTF-8
,则 REST 客户端应发送以下标头:
-
accept: text/plain; charset=UTF-8
用于读取操作。 -
content-Type: text/plain; charset=UTF-8
或Key-Content-Type: text/plain; charset=UTF-8
用于写入操作。
1.4. Marshalled Java 对象
Data Grid 将 marshalled Java 对象存储在缓存中作为字节数组。例如,以下是作为内存中值存储的 Person
对象的简单表示:
value=[61 6c 61 6e 0a 70 61 72 74 72 69 64 67 65]
value=[61 6c 61 6e 0a 70 61 72 74 72 69 64 67 65]
Copy to clipboardCopied要将 marshalled 对象存储到缓存中,您应该使用 ProtoStream marshaller,除非存在严格的要求。例如,当从旧版本的 Data Grid 迁移客户端应用程序时,您可能需要临时将 JBoss marshalling 与 Hot Rod Java 客户端一起使用。
Data Grid 将 marshalled Java 对象存储为带有以下介质类型的字节阵列:
-
application/x-protostream
-
application/x-jboss-marshalling
-
application/x-java-serialized-object
在存储未归档的 Java 对象时,Data Grid 使用 equals ()
和 hashCode ()
的对象实现。在存储 marshalled 对象时,比较 marshalled 字节以相等和散列。
1.4.1. 客户端和 marshalled 对象
当您将 Hot Rod Java 客户端配置为使用 marshaller 时,您必须使用该 marshaller 的编码来配置您的缓存。
每个 marshaller 使用不同的介质类型来生成 byte[]
内容,客户端可以传送到 Data Grid Server。从服务器读取时,客户端 marshaller 会执行相反的操作,使用介质类型从 byte[]
内容生成数据。
您的缓存编码必须与 Hot Rod 客户端 marshaller 兼容。例如,如果您将缓存编码配置为 application/x-protostream
,您可以将 ProtoStream marshaller 与客户端一同操作。但是,如果客户端 marshaller 使用 Data Grid 无法转换为或从 application/x-protostream
转换的编码,Data Grid 会抛出错误消息。
如果您使用 JavaSerializationMarshaller
或 GenericJBossMarshaller
,您应该分别使用 application/x-java-serialized-object
或 application/x-jboss-marshalling
介质类型对缓存进行编码。
ProtoStream 转换为 JSON 转换
Data Grid 将使用 application/x-protostream
介质类型编码的键和值转换为 application/json
。
这允许 REST 客户端在请求标头中包含 JSON 介质类型,并对使用 ProtoStream 编码的缓存执行操作:
-
接受:用于读取操作的应用程序/json
。 -
content-Type:用于写入操作的 application/json
。
1.5. 普通旧 Java 对象(POJO)
为获得最佳性能,Data Grid 建议将未归档的 POJO 存储在嵌入式缓存中。但是,您可以使用以下介质类型配置键和值:
-
application/x-java-object
1.5.1. 客户端和 POJO
虽然 Data Grid 不建议这样做,但客户端可以在存储带有 application/x-java-object
介质类型的 POJO 的缓存中操作。
hot Rod 客户端
热 Rod 客户端 marshallers 必须可供 Data Grid Server 使用,以便它可以反序列化 Java 对象。默认情况下,ProtoStream 和 Java Serialization marshallers 在服务器上可用。
REST 客户端
REST 客户端必须使用 JSON 或 XML 作为键和值,以便 Data Grid 可以转换为 POJO。
Data Grid 要求您将 Java 类添加到 deserialization allowlist 中,以便将 XML 转换为 POJO。
1.6. 在 Data Grid Server 安装中添加 JAR
通过将自定义 JAR 文件添加到 classpath,为 Data Grid 服务器提供自定义 JAR 文件。
Data Grid 仅在启动时加载 JAR 文件。
您应该安全地关闭集群中的所有节点,并在使集群重新启动前提供给每个节点使用任何 JAR 文件。
您应该仅将自定义 JAR 文件添加到
$114G_HOME/server/lib
目录中。$114G_HOME/lib
目录为 Data Grid JAR 文件保留。
流程
- 如果 Data Grid Server 正在运行,则停止它。
将 JAR 文件添加到
server/lib
目录中,例如:├── server │ └── lib │ └── UserObjects.jar
Copy to clipboardCopied├── server │ └── lib │ └── UserObjects.jar
第 2 章 使用 ProtoStream Marshalling 自定义对象
Marshalling 是一个将 Java 对象转换为二进制格式的进程,可在网络中传输或存储到磁盘。反向进程 unmarshalling 将数据从二进制格式转换为 Java 对象。
Data Grid 执行 marshalling 和 unmarshalling to:
- 将数据发送到集群中的其他 Data Grid 节点。
- 将数据存储至持久缓存存储中。
- 在客户端和远程缓存之间传输对象。
- 将对象存储在 JVM 堆之外的原生内存中。
-
当缓存编码不是
application/x-java-object
时,将对象存储在 JVM 堆内存中。
在 Data Grid 缓存中保存自定义对象时,您应该将基于 Protobuf 的 marshalling 与 ProtoStream marshaller 搭配使用。
2.1. ProtoStream marshalling
Data Grid 提供 ProtoStream API,以便您可以将所有 Java 对象作为协议缓冲缓冲(Protobuf)。
ProtoStream 原生支持许多不同的 Java 数据类型,这意味着您不需要为这些类型配置 ProtoStream marshalling。对于自定义或用户类型,您需要提供一些信息,以便数据中心可以将所有这些对象转移到您的缓存中。
SerializationContext
-
包含 Protobuf 类型定义、从 Protobuf 模式(
.proto
文件)以及附带的 marshallers 加载的存储库。 SerializationContextInitializer
-
初始化
SerializationContext
的接口。
其他资源
2.1.1. ProtoStream 类型
Data Grid 使用 ProtoStream 库,它可以为键和值处理以下类型,在使用原语类型时,会取消选择的等效项:
-
byte[]
-
BYTE
-
字符串
-
整数
-
Long
-
�
-
浮点值
-
布尔值
-
短
-
字符
-
java.util.Date
-
java.time.Instant
额外的类型集合
ProtoStream 库包括几个用于常见 Java 类型的适配器类,例如:
-
java.math.BigDecimal
-
java.math.BigInteger
-
java.util.UUID
Data Grid 为 protostream-types
工件中的一些常见 JDK 类提供所有适配器类,它们包含在 infinispan-core
和 infinispan-client-hotrod
依赖项中。您不需要任何配置将适配器类存储为键或值。
但是,如果要使用适配器类作为 ProtoStream-annotated POJOS 中的可 marshallable 字段,您可以使用以下方法进行:
-
使用
AutoProtoSchemaBuilder
注解的dependentOn
元素指定CommonTypesSchema
和CommonContainerTypesSchema
类。
@AutoProtoSchemaBuilder(dependsOn = {org.infinispan.protostream.types.java.CommonTypes, org.infinispan.protostream.types.java.CommonContainerTypes}, schemaFileName = "library.proto", schemaFilePath = "proto", schemaPackageName = "example") public interface LibraryInitalizer extends SerializationContextInitializer { }
@AutoProtoSchemaBuilder(dependsOn = {org.infinispan.protostream.types.java.CommonTypes, org.infinispan.protostream.types.java.CommonContainerTypes}, schemaFileName = "library.proto", schemaFilePath = "proto", schemaPackageName = "example")
public interface LibraryInitalizer extends SerializationContextInitializer {
}
Copy to clipboardCopied-
使用
AutoProtoSchemaBuilder
注解的includeClasses
元素指定所需的适配器类
@AutoProtoSchemaBuilder(includeClasses = { Author.class, Book.class, UUIDAdapter.class, java.math.BigInteger }, schemaFileName = "library.proto", schemaFilePath = "proto", schemaPackageName = "library") public interface LibraryInitalizer extends SerializationContextInitializer { }
@AutoProtoSchemaBuilder(includeClasses = { Author.class, Book.class, UUIDAdapter.class, java.math.BigInteger }, schemaFileName = "library.proto", schemaFilePath = "proto", schemaPackageName = "library")
public interface LibraryInitalizer extends SerializationContextInitializer {
}
Copy to clipboardCopied2.1.2. ProtoStream 注解
ProtoStream API 包含可添加到 Java 应用程序的注解,以定义 Protobuf 模式,它为对象提供结构化格式。
本主题提供有关 ProtoStream 注解的更多详情。如需更多信息,您应该参考 org.infinispan.protostream.annotations 软件包中的文档。
ProtoField
@ProtoField
定义一个 Protobuf 消息字段。
此注解是必需的,适用于字段以及 getter 和 setter 方法。类必须至少使用 @ProtoField
注解一个字段,然后才能将它作为 Protobuf。
参数 | 值 | 可选或必需的 | 描述 |
---|---|---|---|
| 整数 | 必填 | 标签号在类内必须是唯一的。 |
| 类型 | 选填 | 声明字段的 Protobuf 类型。如果没有指定类型,它将从 Java 属性推断出来。
您可以使用 |
| 类 | 选填 | 如果属性类型是接口或抽象类,则指示实际集合类型。 |
| 类 | 选填 | 如果属性类型是抽象类或接口,则指示实际 Java 类型。该值必须是可立即为属性类型的 Java 类型分配。
如果您使用 |
| 字符串 | 选填 | 指定 Protobuf 模式的名称。 |
| 字符串 | 选填 | 在从缓存中读取时,请指定字段的默认值。该值必须遵循 Java 字段类型的正确语法。 |
ProtoFactory
@ProtoFactory
标记单一构造器或静态工厂方法,用于创建消息类实例。
您可以使用此注解来支持不可变消息类。所有使用 @ProtoField
注解的字段都必须包含在参数中。
-
@ProtoFactory
结构或方法的字段名称和参数必须与对应的 Protobuf 消息匹配,但顺序并不重要。 -
如果您没有将
@ProtoFactory
注解构造器添加到类,则该类必须具有默认的 no-argument 构造器,否则编译过程中出现错误。
AutoProtoSchemaBuilder
@AutoProtoSchemaBuilder
生成类或接口的实施,用于扩展 SerializationContextInitializer
。
如果活跃,ProtoStream 处理器会在编译时以 Impl
后缀或您使用 className
参数指定的名称编译时生成实施。
includeClasses
或 basePackages
参数引用 ProtoStream 处理器应该扫描并包含在 Protobuf 模式和 marshaller 中。如果您没有设置其中一个参数,ProtoStream 处理器会扫描整个源路径,这可能会导致意外的结果,我们不建议这样做。您还可以将 excludeClasses
参数与 basePackages
参数一起使用,以排除类。
schemaFileName
和 schemaPackageName
参数在此名称下注册生成的 Protobuf 模式。如果没有设置这些参数,则会将注解的简单类名称与未命名或默认软件包一起使用。模式名称必须以 .proto
文件扩展名结尾。您还可以使用 marshallersOnly
来只生成 marshallers,并阻止 Protobuf 模式生成。
ProtoStream 进程自动生成 META-INF/services
服务元数据文件,您可以使用该文件以便 Data Grid 服务器自动获取 JAR 注册 Protobuf 模式。
dependentOn
参数列出了用于首先执行 SerializedContextInitializer
的注解类。如果类没有实施 SerializedContextInitializer
,或者没有使用 AutoProtoSchemaBuilder
注解,则会出现编译时间错误。
ProtoAdapter
@ProtoAdapter
是无法直接注解的类或枚举的 marshalling 适配器。
如果您使用此注解:
-
注释类,注解类必须具有一个
@ProtoFactory
注解工厂方法,用于每个字段的 marshalled 类和注解的 accessor 方法。这些方法可以是 instance 或 static 方法,其第一个参数必须是 marshalled 类。 - 目标 enum 中必须存在具有相同命名的 enum 值。
ProtoDoc 和 ProtoDocs
@ProtoDoc
和 @ProtoDocs
是人类可读的文本,用于记录生成的模式的消息类型、枚举或字段。
您可以使用这些注解为 Ickle 查询配置索引。
ProtoName
@ProtoName
是一个可选注解,用于指定 Protobuf 消息或枚举类型名称,并替换 @ProtoMessage
注释。
ProtoEnumValue
@ProtoEnumValue
定义 Protobuf enum 值。您只能将此注解应用到 Java enum 的成员。
ProtoReserved 和 ProtoReservedStatements
@ProtoReserved
和 @ProtoReservedStatements
向生成的消息或枚举定义添加 reserved
语句,以防止以后使用数字、范围和名称。
ProtoTypeId
@ProtoTypeId
(可选)为 Protobuf 消息或 enum 类型指定全局唯一的数字类型标识符。
您不应该将此注解添加到类中,因为 Data Grid 在内部使用它,标识符可以在不注意到的情况下更改。
ProtoUnknownFieldSet
@ProtoUnknownFieldSet
(可选)表示字段或类型为 {@link org.infinispan.protostream.UnknownFieldSet}
的 JavaBean 属性,它存储任何未知字段。
Data Grid 不建议使用此注解,因为 Google 不再支持它,并可能在以后被删除。
2.2. 创建序列化上下文初始化器
序列化上下文初始化程序可让您在 Data Grid 中注册以下内容:
- 描述用户类型的 protobuf 模式。
- 提供序列化和反序列化功能的 Marshallers。
在高级别中,您应该执行以下操作来创建序列化上下文初始化器:
- 在 Java 类中添加 ProtoStream 注解。
-
使用 Data Grid 提供的 ProtoStream 处理器来编译您的
SerializationContextInitializer
实现。
org.infinispan.protostream.MessageMarshaller
接口已弃用,计划在以后的 ProtoStream 版本中删除。您应该忽略任何显示如何使用 MessageMarshaller
的代码示例或文档,直到完全删除为止。
2.2.1. 添加 ProtoStream 处理器
Data Grid 提供了一个 ProtoStream 处理器工件,它在编译时在编译时处理类中的 Java 注解,以生成 Protobuf 模式、marshallers 以及 SerializationContextInitializer
接口的聚合实现。
流程
将
protostream-processor
依赖项添加到带有提供的
范围的pom.xml
中。注意这个依赖项只在编译时需要,因此您应该使用
所提供的
范围或将其标记为可选。您还应确保protostream-processor
没有作为传输的依赖关系传播。<dependencyManagement> <dependencies> <dependency> <groupId>org.infinispan</groupId> <artifactId>infinispan-bom</artifactId> <version>${version.infinispan}</version> <type>pom</type> </dependency> </dependencies> </dependencyManagement> <dependencies> <dependency> <groupId>org.infinispan.protostream</groupId> <artifactId>protostream-processor</artifactId> <scope>provided</scope> </dependency> </dependencies>
Copy to clipboardCopied<dependencyManagement> <dependencies> <dependency> <groupId>org.infinispan</groupId> <artifactId>infinispan-bom</artifactId> <version>${version.infinispan}</version> <type>pom</type> </dependency> </dependencies> </dependencyManagement> <dependencies> <dependency> <groupId>org.infinispan.protostream</groupId> <artifactId>protostream-processor</artifactId> <scope>provided</scope> </dependency> </dependencies>
2.2.2. 在 Java 类中添加 ProtoStream 注解
通过在 Java 类及其成员中添加注解来声明 ProtoStream 元数据。然后,Data Grid 使用 ProtoStream 处理器从这些注解生成 Protobuf 模式和相关 marshallers。
流程
使用
@ProtoField
注解您要 marshall 的 Java 字段,可以直接在字段或 getter 或 setter 方法上。您的 Java 类中的任何非扩展字段都是临时的。例如,您有一个带有 15 个字段的 Java 类,并注解了五个字段。生成的模式仅包含这五个字段,当将类实例存储在 Data Grid 中时,只有五个字段会被处理。
-
使用
@ProtoFactory
为不可变对象注解构造器。注解的构造器必须初始化使用@ProtoField
注解的所有字段。 -
使用
@ProtoEnumValue
注解任何 Java enum 的成员。
以下 Author.java
和 Book.java
示例显示了使用 @ProtoField
和 @ProtoFactory
注解的 Java 类:
Author.java
import org.infinispan.protostream.annotations.ProtoFactory; import org.infinispan.protostream.annotations.ProtoField; public class Author { @ProtoField(1) final String name; @ProtoField(2) final String surname; @ProtoFactory Author(String name, String surname) { this.name = name; this.surname = surname; } // public Getter methods omitted for brevity }
import org.infinispan.protostream.annotations.ProtoFactory;
import org.infinispan.protostream.annotations.ProtoField;
public class Author {
@ProtoField(1)
final String name;
@ProtoField(2)
final String surname;
@ProtoFactory
Author(String name, String surname) {
this.name = name;
this.surname = surname;
}
// public Getter methods omitted for brevity
}
Copy to clipboardCopiedBook.java
import org.infinispan.protostream.annotations.ProtoFactory; import org.infinispan.protostream.annotations.ProtoField; public class Book { @ProtoField(number = 1) public final UUID id; @ProtoField(number = 2) final String title; @ProtoField(number = 3) final String description; @ProtoField(number = 4, defaultValue = "0") final int publicationYear; @ProtoField(number = 5, collectionImplementation = ArrayList.class) final List<Author> authors; @ProtoField(number = 6) public Language language; @ProtoFactory Book(UUID id, String title, String description, int publicationYear, List<Author> authors, Language language) { this.id = id; this.title = title; this.description = description; this.publicationYear = publicationYear; this.authors = authors; this.language = language; } // public Getter methods not included for brevity }
import org.infinispan.protostream.annotations.ProtoFactory;
import org.infinispan.protostream.annotations.ProtoField;
public class Book {
@ProtoField(number = 1)
public final UUID id;
@ProtoField(number = 2)
final String title;
@ProtoField(number = 3)
final String description;
@ProtoField(number = 4, defaultValue = "0")
final int publicationYear;
@ProtoField(number = 5, collectionImplementation = ArrayList.class)
final List<Author> authors;
@ProtoField(number = 6)
public Language language;
@ProtoFactory
Book(UUID id, String title, String description, int publicationYear, List<Author> authors, Language language) {
this.id = id;
this.title = title;
this.description = description;
this.publicationYear = publicationYear;
this.authors = authors;
this.language = language;
}
// public Getter methods not included for brevity
}
Copy to clipboardCopied
以下 Language.java
示例显示了一个带有 @ProtoEnumValue
注解的 Java enum,以及对应的 Protobuf 模式:
Language.java
import org.infinispan.protostream.annotations.ProtoEnumValue; public enum Language { @ProtoEnumValue(number = 0, name = "EN") ENGLISH, @ProtoEnumValue(number = 1, name = "DE") GERMAN, @ProtoEnumValue(number = 2, name = "IT") ITALIAN, @ProtoEnumValue(number = 3, name = "ES") SPANISH, @ProtoEnumValue(number = 4, name = "FR") FRENCH; }
import org.infinispan.protostream.annotations.ProtoEnumValue;
public enum Language {
@ProtoEnumValue(number = 0, name = "EN")
ENGLISH,
@ProtoEnumValue(number = 1, name = "DE")
GERMAN,
@ProtoEnumValue(number = 2, name = "IT")
ITALIAN,
@ProtoEnumValue(number = 3, name = "ES")
SPANISH,
@ProtoEnumValue(number = 4, name = "FR")
FRENCH;
}
Copy to clipboardCopiedLanguage.proto
enum Language { EN = 0; DE = 1; IT = 2; ES = 3; FR = 4; }
enum Language {
EN = 0;
DE = 1;
IT = 2;
ES = 3;
FR = 4;
}
Copy to clipboardCopied2.2.3. 创建 ProtoStream 适配器类
ProtoStream 提供了一个 @ProtoAdapter
注释,您可以使用它来编译您无法直接注解的外部第三方 Java 对象类。
流程
创建一个
适配器
类并添加@ProtoAdapter
注解,如下例所示:import java.util.UUID; import org.infinispan.protostream.annotations.ProtoAdapter; import org.infinispan.protostream.annotations.ProtoFactory; import org.infinispan.protostream.annotations.ProtoField; import org.infinispan.protostream.descriptors.Type; /** * Human readable UUID adapter for UUID marshalling */ @ProtoAdapter(UUID.class) public class UUIDAdapter { @ProtoFactory UUID create(String stringUUID) { return UUID.fromString(stringUUID); } @ProtoField(1) String getStringUUID(UUID uuid) { return uuid.toString(); } }
Copy to clipboardCopiedimport java.util.UUID; import org.infinispan.protostream.annotations.ProtoAdapter; import org.infinispan.protostream.annotations.ProtoFactory; import org.infinispan.protostream.annotations.ProtoField; import org.infinispan.protostream.descriptors.Type; /** * Human readable UUID adapter for UUID marshalling */ @ProtoAdapter(UUID.class) public class UUIDAdapter { @ProtoFactory UUID create(String stringUUID) { return UUID.fromString(stringUUID); } @ProtoField(1) String getStringUUID(UUID uuid) { return uuid.toString(); } }
2.2.4. 生成序列化上下文初始化器
添加 ProtoStream 处理器并注解 Java 类后,您可以将 @AutoProtoSchemaBuilder
注解添加到接口,以便数据仓库生成 Protobuf 模式、marshallers 以及 SerializationContextInitializer
的聚合实现。
默认情况下,生成的实现名称是注解的类名称,带有一个 "Impl" 后缀。
流程
定义一个扩展
GeneratedSchema
或其超级接口SerializationContextInitializer
的接口。注意GeneratedSchema
接口包括访问 Protobuf 模式的方法,而SerializationContextInitializer
接口只支持注册方法。-
使用
@AutoProtoSchemaBuilder
注解接口。 -
确保
includeClasses
参数包含生成的SerializationContextInitializer
实现的所有类。 -
使用
schemaFileName
参数为生成的.proto
模式指定一个名称。 -
在
target/classes
下设置一个路径,其中 schema 文件使用schemaFilePath
参数生成。 -
使用
schemaPackageName
参数为生成的.proto
模式指定软件包名称。
以下示例显示了使用 @AutoProtoSchemaBuilder
注解的 GeneratedSchema
接口:
@AutoProtoSchemaBuilder( includeClasses = { Book.class, Author.class, UUIDAdapter.class, Language.class }, schemaFileName = "library.proto", schemaFilePath = "proto/", schemaPackageName = "book_sample") interface LibraryInitializer extends GeneratedSchema { }
@AutoProtoSchemaBuilder(
includeClasses = {
Book.class,
Author.class,
UUIDAdapter.class,
Language.class
},
schemaFileName = "library.proto",
schemaFilePath = "proto/",
schemaPackageName = "book_sample")
interface LibraryInitializer extends GeneratedSchema {
}
Copy to clipboardCopied后续步骤
如果您使用嵌入式缓存,Data Grid 会自动注册您的 SerializationContextInitializer
实现。
如果使用远程缓存,您必须在 Data Grid Server 中注册 SerializationContextInitializer
实现。
2.2.5. 注册序列化上下文初始化器
对于嵌入式缓存,Data Grid 会自动使用 java.util.ServiceLoader
在注解的 SerializationContextInitializer
实现中注册序列化上下文和 marshallers。
如果您希望禁用 SerializationContextInitializer
实现的自动注册,然后手动注册它们。
如果您手动注册一个 SerializationContextInitializer
实现,它会禁用自动注册。然后,您必须手动注册所有其他实现。
流程
为
AutoProtoSchemaBuilder.service
注解设置false
值。@AutoProtoSchemaBuilder( includeClasses = SomeClass.class, ... service = false )
Copy to clipboardCopied@AutoProtoSchemaBuilder( includeClasses = SomeClass.class, ... service = false )
-
手动以编程方式或声明性地注册
SerializationContextInitializer
实现,如下例所示:
声明
<serialization> <context-initializer class="org.infinispan.example.LibraryInitializerImpl"/> <context-initializer class="org.infinispan.example.another.SCIImpl"/> </serialization>
<serialization>
<context-initializer class="org.infinispan.example.LibraryInitializerImpl"/>
<context-initializer class="org.infinispan.example.another.SCIImpl"/>
</serialization>
Copy to clipboardCopiedprogrammatic
GlobalConfigurationBuilder builder = new GlobalConfigurationBuilder(); builder.serialization() .addContextInitializers(new LibraryInitializerImpl(), new SCIImpl());
GlobalConfigurationBuilder builder = new GlobalConfigurationBuilder();
builder.serialization()
.addContextInitializers(new LibraryInitializerImpl(), new SCIImpl());
Copy to clipboardCopied2.2.6. 将 Protobuf 模式注册到 Data Grid 服务器
使用 Data Grid Server 注册 Protobuf 模式,以执行 Ickle 查询或从 application/x-protostream
转换到其他介质类型,如 application/json
。
先决条件
使用 ProtoStream 处理器生成 Protobuf 模式。
您可以在
target/<schemaFilePath>/
目录中找到生成的 Protobuf 模式。具有
CREATE
权限的用户。注意安全授权需要
CREATE
权限来添加模式。使用默认设置时,您至少需要deployer
角色。
流程
使用以下方法之一在 Data Grid 服务器中添加 Protobuf 模式:
- 在任何浏览器中打开 Data Grid Console,选择 Schema 选项卡,然后添加 Protobuf 模式。
使用带有 Data Grid 命令行界面(CLI)中的
--upload=
参数的schema
命令。schema --upload=person.proto person
Copy to clipboardCopiedschema --upload=person.proto person
使用 REST API 在
POST
请求有效负载中包含 Protobuf 模式。POST/rest/v2/schemas/<schema_name>
Copy to clipboardCopiedPOST/rest/v2/schemas/<schema_name>
使用带有 Hot Rod 客户端生成的
SerializationContextInitializer
实现来注册 Protobuf 模式,如下例所示:/** * Register generated Protobuf schema with Data Grid Server. * This requires the RemoteCacheManager to be initialized. * * @param initializer The serialization context initializer for the schema. */ private void registerSchemas(SerializationContextInitializer initializer) { // Store schemas in the '___protobuf_metadata' cache to register them. // Using ProtobufMetadataManagerConstants might require the query dependency. final RemoteCache<String, String> protoMetadataCache = remoteCacheManager.getCache(ProtobufMetadataManagerConstants.PROTOBUF_METADATA_CACHE_NAME); // Add the generated schema to the cache. protoMetadataCache.put(initializer.getProtoFileName(), initializer.getProtoFile()); // Ensure the registered Protobuf schemas do not contain errors. // Throw an exception if errors exist. String errors = protoMetadataCache.get(ProtobufMetadataManagerConstants.ERRORS_KEY_SUFFIX); if (errors != null) { throw new IllegalStateException("Some Protobuf schema files contain errors: " + errors + "\nSchema :\n" + initializer.getProtoFileName()); } }
Copy to clipboardCopied/** * Register generated Protobuf schema with Data Grid Server. * This requires the RemoteCacheManager to be initialized. * * @param initializer The serialization context initializer for the schema. */ private void registerSchemas(SerializationContextInitializer initializer) { // Store schemas in the '___protobuf_metadata' cache to register them. // Using ProtobufMetadataManagerConstants might require the query dependency. final RemoteCache<String, String> protoMetadataCache = remoteCacheManager.getCache(ProtobufMetadataManagerConstants.PROTOBUF_METADATA_CACHE_NAME); // Add the generated schema to the cache. protoMetadataCache.put(initializer.getProtoFileName(), initializer.getProtoFile()); // Ensure the registered Protobuf schemas do not contain errors. // Throw an exception if errors exist. String errors = protoMetadataCache.get(ProtobufMetadataManagerConstants.ERRORS_KEY_SUFFIX); if (errors != null) { throw new IllegalStateException("Some Protobuf schema files contain errors: " + errors + "\nSchema :\n" + initializer.getProtoFileName()); } }
添加带有
SerializationContextInitializer
实现的 JAR 文件,并将自定义类添加到$114G_HOME/server/lib
目录中。当您执行此操作时,Data Grid 服务器在启动时注册您的 Protobuf 模式。但是,您必须将存档添加到每台服务器安装中,因为 schema 不会保存在
___protobuf_metadata
缓存中,或者在集群中自动分发。注意如果您需要 Data Grid Server 执行任何
application/x-protostream
到application/x-java-object
转换,则必须执行此操作,在这种情况下,您必须为 POJO 添加任何 JAR 文件。
后续步骤
将 SerializationContextInitializer
注册到 Hot Rod 客户端,如下例所示:
ConfigurationBuilder remoteBuilder = new ConfigurationBuilder(); remoteBuilder.addServer().host(host).port(Integer.parseInt(port)); // Add your generated SerializationContextInitializer implementation. LibraryInitalizer initializer = new LibraryInitalizerImpl(); remoteBuilder.addContextInitializer(initializer);
ConfigurationBuilder remoteBuilder = new ConfigurationBuilder();
remoteBuilder.addServer().host(host).port(Integer.parseInt(port));
// Add your generated SerializationContextInitializer implementation.
LibraryInitalizer initializer = new LibraryInitalizerImpl();
remoteBuilder.addContextInitializer(initializer);
Copy to clipboardCopied2.2.7. 手动序列化上下文初始化器实现
Data Grid 强烈建议您手动实现 SerializationContextInitializer
或 GeneratedSchema
接口。
可以使用 ProtobufTagMarshaller
和 RawProtobufMarshaller
注解手动实现 SerializationContextInitializer
或 GeneratedSchema
接口。
但是,手动实施需要大量的开销,且容易出错。使用 protostream-processor
工件生成的实现更为高效且可靠的方法来配置 ProtoStream marshalling。
第 3 章 使用替代和自定义 marshaller 实现
Data Grid 建议您将基于 Protobuf 的 marshalling 与 ProtoStream marshaller 一起使用,以便您可以利用 Ickle 查询并使用 Data Grid CLI 和控制台。但是,如果需要,您可以使用替代的 marshallers 或自定义 marshaller 实现。
3.1. 允许反序列化 Java 类
出于安全考虑,Data Grid 不允许反序列化任意 Java 类。如果使用 JavaSerializationMarshaller
或 GenericJBossMarshaller
,您必须将 Java 类添加到反序列化允许列表中。
deserialization allow 列表应用到 Cache Manager,以便所有缓存可以反序列化 Java 类。
流程
- 将 Java 类添加到 Data Grid 配置或系统属性中的反序列化允许列表中。
声明
<infinispan> <cache-container> <serialization version="1.0" marshaller="org.infinispan.marshall.TestObjectStreamMarshaller"> <allow-list> <class>org.infinispan.test.data.Person</class> <regex>org.infinispan.test.data.*</regex> </allow-list> </serialization> </cache-container> </infinispan>
<infinispan>
<cache-container>
<serialization version="1.0"
marshaller="org.infinispan.marshall.TestObjectStreamMarshaller">
<allow-list>
<class>org.infinispan.test.data.Person</class>
<regex>org.infinispan.test.data.*</regex>
</allow-list>
</serialization>
</cache-container>
</infinispan>
Copy to clipboardCopied系统属性
// Specify a comma-separated list of fully qualified class names -Dinfinispan.deserialization.allowlist.classes=java.time.Instant,com.myclass.Entity // Specify a regular expression to match classes -Dinfinispan.deserialization.allowlist.regexps=.*
// Specify a comma-separated list of fully qualified class names
-Dinfinispan.deserialization.allowlist.classes=java.time.Instant,com.myclass.Entity
// Specify a regular expression to match classes
-Dinfinispan.deserialization.allowlist.regexps=.*
Copy to clipboardCopied3.2. 使用 JBoss Marshalling
JBoss Marshalling 是一个基于序列化的 marshalling 库,它是之前 Data Grid 版本里的默认 marshaller,但现已弃用。
JBoss Marshalling 已被弃用。在将应用程序从旧版本的 Data Grid 迁移应用程序时,您应该将其用作临时措施。
流程
-
在您的 classpath 中添加
infinispan-jboss-marshalling
依赖项。 -
将 Data Grid 配置为使用
GenericJBossMarshaller
。 - 将您的 Java 类添加到 deserialization allowlist 中。
声明
<serialization marshaller="org.infinispan.jboss.marshalling.commons.GenericJBossMarshaller"> <allow-list> <class>org.infinispan.concrete.SomeClass</class> <regex>org.infinispan.example.*</regex> </allow-list> </serialization>
<serialization marshaller="org.infinispan.jboss.marshalling.commons.GenericJBossMarshaller">
<allow-list>
<class>org.infinispan.concrete.SomeClass</class>
<regex>org.infinispan.example.*</regex>
</allow-list>
</serialization>
Copy to clipboardCopiedprogrammatic
GlobalConfigurationBuilder builder = new GlobalConfigurationBuilder(); builder.serialization() .marshaller(new GenericJBossMarshaller()) .allowList() .addRegexps("org.infinispan.example.", "org.infinispan.concrete.SomeClass");
GlobalConfigurationBuilder builder = new GlobalConfigurationBuilder();
builder.serialization()
.marshaller(new GenericJBossMarshaller())
.allowList()
.addRegexps("org.infinispan.example.", "org.infinispan.concrete.SomeClass");
Copy to clipboardCopied其他资源
3.3. 使用 Java 序列化
您可以通过 Data Grid 使用 Java 序列化,以 marshall 对象实现 Java Serializable
接口。
Java 序列化提供比 ProtoStream marshalling 更差的性能。只有在有严格的要求时才应使用 Java 序列化。
流程
-
将 Data Grid 配置为使用
JavaSerializationMarshaller
。 - 将您的 Java 类添加到 deserialization allowlist 中。
声明
<serialization marshaller="org.infinispan.commons.marshall.JavaSerializationMarshaller"> <allow-list> <class>org.infinispan.concrete.SomeClass</class> <regex>org.infinispan.example.*</regex> </allow-list> </serialization>
<serialization marshaller="org.infinispan.commons.marshall.JavaSerializationMarshaller">
<allow-list>
<class>org.infinispan.concrete.SomeClass</class>
<regex>org.infinispan.example.*</regex>
</allow-list>
</serialization>
Copy to clipboardCopiedprogrammatic
GlobalConfigurationBuilder builder = new GlobalConfigurationBuilder(); builder.serialization() .marshaller(new JavaSerializationMarshaller()) .allowList() .addRegexps("org.infinispan.example.", "org.infinispan.concrete.SomeClass");
GlobalConfigurationBuilder builder = new GlobalConfigurationBuilder();
builder.serialization()
.marshaller(new JavaSerializationMarshaller())
.allowList()
.addRegexps("org.infinispan.example.", "org.infinispan.concrete.SomeClass");
Copy to clipboardCopied3.4. 使用自定义 marshallers
Data Grid 提供了一个 Marshaller
接口,您可以为自定义 marshallers 实施。
自定义 marshaller 实现可以通过 initialize () 方法访问配置的访问列表,该列表在启动期间调用。
流程
-
实施
Marshaller
接口。 - 配置 Data Grid 以使用您的 marshaller。
- 将您的 Java 类添加到 deserialization allowlist 中。
声明
<serialization marshaller="org.infinispan.example.marshall.CustomMarshaller"> <allow-list> <class>org.infinispan.concrete.SomeClass</class> <regex>org.infinispan.example.*</regex> </allow-list> </serialization>
<serialization marshaller="org.infinispan.example.marshall.CustomMarshaller">
<allow-list>
<class>org.infinispan.concrete.SomeClass</class>
<regex>org.infinispan.example.*</regex>
</allow-list>
</serialization>
Copy to clipboardCopiedprogrammatic
GlobalConfigurationBuilder builder = new GlobalConfigurationBuilder(); builder.serialization() .marshaller(new org.infinispan.example.marshall.CustomMarshaller()) .allowList().addRegexp("org.infinispan.example.*");
GlobalConfigurationBuilder builder = new GlobalConfigurationBuilder();
builder.serialization()
.marshaller(new org.infinispan.example.marshall.CustomMarshaller())
.allowList().addRegexp("org.infinispan.example.*");
Copy to clipboardCopied第 4 章 数据转换
Data Grid 使用 transcoders 在由介质类型标识的不同编码之间转换数据。
4.1. hot Rod DataFormat API
通过 Hot Rod 端点对远程缓存的读写操作默认使用客户端 marshaller。热 Rod 为 Java 客户端提供 DataFormat
API,您可以使用它来执行具有不同介质类型 encodings 和/或 marshallers 的缓存操作。
键和值的不同 marshallers
您可以在运行时覆盖键和值的 marshallers。
例如,要绕过 Hot Rod 客户端中的所有序列化,并读取存储在远程缓存中的 byte[]
数组:
// Existing RemoteCache instance RemoteCache<String, Pojo> remoteCache = ... // IdentityMarshaller is a no-op marshaller DataFormat rawKeyAndValues = DataFormat.builder() .keyMarshaller(IdentityMarshaller.INSTANCE) .valueMarshaller(IdentityMarshaller.INSTANCE) .build(); // Creates a new instance of RemoteCache with the supplied DataFormat RemoteCache<byte[], byte[]> rawResultsCache = remoteCache.withDataFormat(rawKeyAndValues);
// Existing RemoteCache instance
RemoteCache<String, Pojo> remoteCache = ...
// IdentityMarshaller is a no-op marshaller
DataFormat rawKeyAndValues =
DataFormat.builder()
.keyMarshaller(IdentityMarshaller.INSTANCE)
.valueMarshaller(IdentityMarshaller.INSTANCE)
.build();
// Creates a new instance of RemoteCache with the supplied DataFormat
RemoteCache<byte[], byte[]> rawResultsCache =
remoteCache.withDataFormat(rawKeyAndValues);
Copy to clipboardCopied
对带有 keyMarshaller ()
和 keyType ()
方法的密钥使用不同的 marshallers 和数据格式可能会影响客户端智能路由机制,从而导致 Data Grid 集群中的额外网络跃点。如果性能至关重要,您应该对客户端和服务器中的密钥使用相同的编码。
读取不同编码中的数据
根据 org.infinispan.commons.dataconversion.MediaType
指定的不同编码请求并发送数据,如下所示:
// Existing remote cache using ProtostreamMarshaller RemoteCache<String, Pojo> protobufCache = ... // Request values returned as JSON // Use the UTF8StringMarshaller to convert UTF-8 to String DataFormat jsonString = DataFormat.builder() .valueType(MediaType.APPLICATION_JSON) .valueMarshaller(new UTF8StringMarshaller()) .build(); RemoteCache<byte[], byte[]> rawResultsCache = protobufCache.withDataFormat(jsonString);
// Existing remote cache using ProtostreamMarshaller
RemoteCache<String, Pojo> protobufCache = ...
// Request values returned as JSON
// Use the UTF8StringMarshaller to convert UTF-8 to String
DataFormat jsonString =
DataFormat.builder()
.valueType(MediaType.APPLICATION_JSON)
.valueMarshaller(new UTF8StringMarshaller())
.build();
RemoteCache<byte[], byte[]> rawResultsCache =
protobufCache.withDataFormat(jsonString);
Copy to clipboardCopied使用自定义值 marshallers
您可以将自定义 marshallers 用于值,如下例所示,它将值返回为 org.codehaus.jackson.JsonNode
对象。
在本例中,Data Grid 服务器处理数据转换,并在不支持指定的介质类型时抛出异常。
DataFormat jsonNode = DataFormat.builder() .valueType(MediaType.APPLICATION_JSON) .valueMarshaller(new CustomJacksonMarshaller() .build(); RemoteCache<String, JsonNode> jsonNodeCache = remoteCache.withDataFormat(jsonNode);
DataFormat jsonNode =
DataFormat.builder()
.valueType(MediaType.APPLICATION_JSON)
.valueMarshaller(new CustomJacksonMarshaller()
.build();
RemoteCache<String, JsonNode> jsonNodeCache =
remoteCache.withDataFormat(jsonNode);
Copy to clipboardCopied将值返回为 XML
以下代码片段返回值为 XML:
Object xmlValue = remoteCache .withDataFormat(DataFormat.builder() .valueType(MediaType.APPLICATION_XML) .valueMarshaller(new UTF8StringMarshaller()) .build()) .get(key);
Object xmlValue = remoteCache
.withDataFormat(DataFormat.builder()
.valueType(MediaType.APPLICATION_XML)
.valueMarshaller(new UTF8StringMarshaller())
.build())
.get(key);
Copy to clipboardCopied
例如,前面的 get (key)
调用返回值,例如:
<?xml version="1.0" ?><string>Hello!</string>
<?xml version="1.0" ?><string>Hello!</string>
Copy to clipboardCopied4.2. 使用嵌入式缓存根据需要转换数据
嵌入式缓存具有 application/x-java-object
的默认请求编码,以及一个与您为缓存配置的介质类型对应的存储编码。这意味着,Data Grid marshalls 从应用程序到缓存的存储编码,然后返回 POJOs 返回到应用程序。在一些复杂的场景中,您可以使用 AdvancedCache
API 将默认转换从 POJO 更改为其他编码。
以下示例使用 withMediaType ()
方法根据需要以 application/json
返回值。
带有 MediaType 的高级缓存
DefaultCacheManager cacheManager = new DefaultCacheManager(); // Encode keys and values as Protobuf ConfigurationBuilder cfg = new ConfigurationBuilder(); cfg.encoding().key().mediaType("application/x-protostream"); cfg.encoding().value().mediaType("application/x-protostream"); cacheManager.defineConfiguration("mycache", cfg.build()); Cache<Integer, Person> cache = cacheManager.getCache("mycache"); cache.put(1, new Person("John","Doe")); // Use Protobuf for keys and JSON for values Cache<Integer, byte[]> jsonValuesCache = (Cache<Integer, byte[]>) cache.getAdvancedCache().withMediaType("application/x-protostream", "application/json"); byte[] json = jsonValuesCache.get(1);
DefaultCacheManager cacheManager = new DefaultCacheManager();
// Encode keys and values as Protobuf
ConfigurationBuilder cfg = new ConfigurationBuilder();
cfg.encoding().key().mediaType("application/x-protostream");
cfg.encoding().value().mediaType("application/x-protostream");
cacheManager.defineConfiguration("mycache", cfg.build());
Cache<Integer, Person> cache = cacheManager.getCache("mycache");
cache.put(1, new Person("John","Doe"));
// Use Protobuf for keys and JSON for values
Cache<Integer, byte[]> jsonValuesCache = (Cache<Integer, byte[]>) cache.getAdvancedCache().withMediaType("application/x-protostream", "application/json");
byte[] json = jsonValuesCache.get(1);
Copy to clipboardCopied以 JSON 格式返回的值
{ "_type":"org.infinispan.sample.Person", "name":"John", "surname":"Doe" }
{
"_type":"org.infinispan.sample.Person",
"name":"John",
"surname":"Doe"
}
Copy to clipboardCopied