You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在ProtoStream 4.4.3(Java8)中编组?泛型与ZonedDateTime问题

问题解决步骤

一、解决ZonedDateTime无参构造错误

Java 8的ZonedDateTime没有公共无参构造函数,Protostream无法直接实例化它,可通过以下两种方式处理:

方案1:引入JDK8时间类型支持模块

如果使用Maven,添加对应依赖:

<dependency>
    <groupId>org.infinispan.protostream</groupId>
    <artifactId>protostream-jdk8</artifactId>
    <version>你的Protostream版本</version>
</dependency>

然后在ProtoInitializer相关类中注册JDK8时间编解码器:

public class ProtoSchemaInitializer implements GeneratedSchema {
    @Override
    public void registerSchema(SerializationContext serCtx) {
        // 注册JDK8时间类型编解码器
        Jdk8TimeMarshaller.register(serCtx);
        // 注册生成的proto文件
        serCtx.registerProtoFiles(FileDescriptorSource.fromResources("proto/abc.proto"));
    }

    @Override
    public void registerMarshallers(SerializationContext serCtx) {
        Jdk8TimeMarshaller.register(serCtx);
    }
}

方案2:自定义ZonedDateTime的Marshaller

若不想引入额外模块,自行实现编解码器:

public class ZonedDateTimeMarshaller implements Marshaller<ZonedDateTime> {
    @Override
    public Class<? extends ZonedDateTime> getJavaClass() {
        return ZonedDateTime.class;
    }

    @Override
    public String getTypeName() {
        return "pkg_abc.ZonedDateTime";
    }

    @Override
    public void writeTo(ProtoStreamWriter writer, ZonedDateTime zonedDateTime) throws IOException {
        writer.writeString("value", zonedDateTime.toString());
    }

    @Override
    public ZonedDateTime readFrom(ProtoStreamReader reader) throws IOException {
        return ZonedDateTime.parse(reader.readString("value"));
    }
}

同时在proto schema中定义对应消息类型:

message ZonedDateTime {
    string value = 1;
}

最后在初始化类中注册该Marshaller。

二、解决通配符泛型List<? extends Account>错误

Protostream不支持通配符类型,需修改集合类型并处理多态逻辑:

  1. 修改P类的集合字段类型
    将List<? extends Account>改为List<Account>:
class P {
    @ProtoField(number = 1, collectionImplementation = ArrayList.class)
    List<Account> accounts;

    @ProtoField(number = 2)
    ZonedDateTime fromDate;

    @ProtoFactory
    public P(List<Account> accounts, ZonedDateTime fromDate) {
        this.accounts = accounts;
        this.fromDate = fromDate;
    }
}
  1. 在父类Account上声明多态子类
    给Account类添加@ProtoInclude注解,指定所有子类:
@ProtoInclude(value = 1, type = SavingAccount.class)
@ProtoInclude(value = 2, type = ChequingAccount.class)
public abstract class Account {
    // 父类字段需添加@ProtoField注解(如有)
}
  1. 完善子类的注解与构造
    子类需添加@ProtoMessage注解,同时提供无参构造(Protostream要求):
@ProtoMessage(name = "SavingAccount")
public class SavingAccount extends Account {
    @ProtoField(number = 1)
    private String name_sa;

    public SavingAccount() {}

    public SavingAccount(String name_sa) {
        this.name_sa = name_sa;
    }

    // getter、setter方法
    public String getName_sa() { return name_sa; }
    public void setName_sa(String name_sa) { this.name_sa = name_sa; }
}
@ProtoMessage(name = "ChequingAccount")
public class ChequingAccount extends Account {
    @ProtoField(number = 1)
    private String holder_ca;

    public ChequingAccount() {}

    public ChequingAccount(String holder_ca) {
        this.holder_ca = holder_ca;
    }

    // getter、setter方法
    public String getHolder_ca() { return holder_ca; }
    public void setHolder_ca(String holder_ca) { this.holder_ca = holder_ca; }
}

三、修正ProtoInitializer的语法错误

原代码中Public需改为小写public:

@AutoProtoBuilder(
    basePackages = "com.domain",
    schemaFileName = "abc.proto",
    schemaFilePath = "proto/",
    schemaPackageName = "pkg_abc"
)
public interface ProtoInitializer extends GeneratedSchema {
}

最终生成的Proto Schema

完成上述修改后,生成的abc.proto示例如下:

package pkg_abc;

message Account {
    oneof subtype {
        SavingAccount saving_account = 1;
        ChequingAccount chequing_account = 2;
    }
}

message SavingAccount {
    string name_sa = 1;
}

message ChequingAccount {
    string holder_ca = 1;
}

message ZonedDateTime {
    string value = 1;
}

message P {
    repeated Account accounts = 1;
    ZonedDateTime from_date = 2;
}

内容的提问来源于stack exchange,提问作者user1912935

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 05:12:07