从Infinispan 7升级至10.1.3:UUID作为缓存键/字段的序列化处理
解决Infinispan 10.1.3中Protostream处理UUID的问题
刚好我之前处理过类似的Infinispan升级问题,给你一步步拆解解决方法——不管是把UUID作为缓存键,还是作为实体类的字段,核心都是让Protostream能识别并正确序列化/反序列化UUID:
1. 给UUID自定义Protostream转换器
因为Protobuf本身不支持UUID类型,我们可以把它转成String来存储。这里有两种方式,推荐用注解适配器,更贴合你想用注解处理器的需求:
方式一:注解适配器(推荐适配注解处理器)
写一个UUIDAdapter类,用@ProtoAdapter标记,告诉Protostream如何把UUID和String互相转换:
import org.infinispan.protostream.annotations.ProtoAdapter; import org.infinispan.protostream.annotations.ProtoFactory; import org.infinispan.protostream.annotations.ProtoField; import java.util.UUID; @ProtoAdapter(UUID.class) public class UUIDAdapter { // 反序列化:从String生成UUID @ProtoFactory public UUID create(String uuidStr) { return UUID.fromString(uuidStr); } // 序列化:把UUID转成String @ProtoField(number = 1, type = org.infinispan.protostream.annotations.ProtoType.STRING) public String getValue(UUID uuid) { return uuid.toString(); } }
方式二:自定义Marshaller类
如果不想用注解,也可以直接实现Marshaller接口:
import org.infinispan.protostream.Marshaller; import org.infinispan.protostream.ProtobufTagMarshaller; import java.io.IOException; import java.util.UUID; public class UUIDMarshaller implements Marshaller<UUID> { @Override public UUID readFrom(ProtobufTagMarshaller.Input input) throws IOException { return UUID.fromString(input.readString()); } @Override public void writeTo(ProtobufTagMarshaller.Output output, UUID uuid) throws IOException { output.writeString(uuid.toString()); } @Override public Class<? extends UUID> getJavaClass() { return UUID.class; } @Override public String getTypeName() { return "your.package.UUID"; // 自定义proto类型名即可 } }
2. 注册转换器到Protostream上下文
不管用哪种方式,都需要把转换器注册到Infinispan的序列化上下文中,这样框架才能识别UUID:
import org.infinispan.manager.EmbeddedCacheManager; import org.infinispan.protostream.SerializationContext; import org.infinispan.protostream.marshaller.ProtoStreamMarshaller; import org.infinispan.configuration.cache.ConfigurationBuilder; import org.infinispan.manager.DefaultCacheManager; public class CacheInitializer { public static void main(String[] args) { EmbeddedCacheManager manager = new DefaultCacheManager(); // 获取Protostream序列化上下文 SerializationContext ctx = ProtoStreamMarshaller.getSerializationContext(manager); // 注册UUID适配器(注解方式) ctx.registerAnnotatedClass(UUIDAdapter.class); // 如果用自定义Marshaller,就注册这个实例 // ctx.registerMarshaller(new UUIDMarshaller()); // 注册你的实体类(比如Bar) ctx.registerAnnotatedClass(Bar.class); // 配置缓存使用Protostream作为序列化方式 ConfigurationBuilder configBuilder = new ConfigurationBuilder(); configBuilder.encoding() .key().mediaType("application/x-protostream") .value().mediaType("application/x-protostream"); // 定义需要的缓存 manager.defineConfiguration("t1", configBuilder.build()); manager.defineConfiguration("t2", configBuilder.build()); } }
3. 处理实体类中的UUID字段(比如Bar类)
现在你的Bar类可以直接用UUID字段了,注意必须提供公共无参构造方法——这是注解处理器的要求,也是你之前报错的原因之一:
import org.infinispan.protostream.annotations.ProtoDoc; import org.infinispan.protostream.annotations.ProtoField; import java.util.UUID; @ProtoDoc("包含UUID字段的实体类Bar") public class Bar { private UUID uuidField; private String otherField; // 必须要有无参构造,注解处理器要求 public Bar() {} public Bar(UUID uuidField, String otherField) { this.uuidField = uuidField; this.otherField = otherField; } @ProtoField(number = 1) // 字段序号唯一即可 public UUID getUuidField() { return uuidField; } public void setUuidField(UUID uuidField) { this.uuidField = uuidField; } @ProtoField(number = 2) public String getOtherField() { return otherField; } public void setOtherField(String otherField) { this.otherField = otherField; } }
4. 把UUID用作缓存键
完成上面的配置后,你就可以像原来一样直接用UUID作为缓存键了:
Map<UUID, Foo> testUUIDAsKey = manager.getCache("t1"); testUUIDAsKey.put(UUID.randomUUID(), new Foo("测试值")); // 读取操作也完全正常 Foo targetFoo = testUUIDAsKey.get(targetUuid);
额外注意事项
- 确保缓存的编码配置使用
application/x-protostream,这样键和值都会用Protostream序列化。 - 如果用Maven/Gradle构建,要正确配置Protostream注解处理器,比如Maven中添加:
<plugin> <groupId>org.infinispan.protostream</groupId> <artifactId>protostream-processor</artifactId> <version>4.3.1.Final</version> <!-- 和Infinispan 10.1.3对应版本一致 --> <executions> <execution> <goals> <goal>process</goal> </goals> </execution> </executions> </plugin>
内容的提问来源于stack exchange,提问作者iXô
相关产品推荐
相关产品推荐

