我在客户端 - 服务器架构中使用协议缓冲区作为有线数据格式。域对象(java bean)将经历以下生命周期。
"Protocol Buffers and O-O Design"部分建议将生成的类包装在适当的域模型中。
我想找出最好的搭档。
例如我有一个简单的原型定义。
package customer;
option java_package = "com.example";
option java_outer_classname = "CustomerProtos";
message Customer {
required string name = 1;
optional string address = 2;
}
这就是域模型的定义方式。如您所见,数据完全存储在proto builder对象中。
package com.example;
public class CustomerModel
{
private CustomerProtos.Customer.Builder builder = CustomerProtos.Customer.newBuilder();
public String getName()
{
return builder.getName();
}
public void setName(String name)
{
builder.setName(name);
}
public String getAddress()
{
return builder.getAddress();
}
public void setAddress(String address)
{
builder.setAddress(address);
}
public byte[] serialize()
{
return builder.build().toByteArray();
}
}
这是一个好习惯吗?因为这些对象用于生命周期的所有阶段,但我们在客户端 - 服务器传输阶段只需要protocolbuf格式。
当原型定义复杂且嵌套时,访问proto builder类getter / setter方法时是否存在性能问题?
答案 0 :(得分:9)
我没有使用协议缓冲区的经验,但我不建议实现针对特定序列化/传输框架量身定制的域对象。你可能会后悔。
软件应用程序的域对象和逻辑应尽可能独立于特定的实现问题(在您的情况下是序列化/传输),因为您希望您的域易于理解并且将来可重用/可维护。
如果要独立于序列化/传输定义域对象,则有两个选项:
选项1的缺点是您的域被定义了两次(这对于修改是不可取的)和信息的复制(这会产生容易出错且不可维护的代码)。
选项2的缺点是你丢失schema evolution(虽然ProtoStuff显然是supports it)并且完整的(可能很大的)对象图被序列化和传输。虽然您可以在序列化/传输之前修剪对象图(手动或使用JGT)。
答案 1 :(得分:2)
我们制作了protobuf-converter来解决将您的域模型对象转换为Google Protobuf消息的问题,反之亦然。
如何使用
必须转换为protobuf消息的域模型类必须满足条件:
E.g:
@ProtoClass(ProtobufUser.class)
public class User {
@ProtoField
private String name;
@ProtoField
private String password;
// getters and setters for 'name' and 'password' fields
...
}
将用户实例转换为相关的protobuf消息的代码:
User userDomain = new User();
...
ProtobufUser userProto = Converter.create().toProtobuf(ProtobufUser.class, userDomain);
反向转换代码:
User userDomain = Converter.create().toDomain(User.class, userProto);
对象列表的转换类似于单个对象转换。