当前位置: 首页 > 知识库问答 >
问题:

协议缓冲区和OO设计

蔺霄
2023-03-14

我在客户机-服务器体系结构中使用协议缓冲区作为有线数据格式。域对象(JavaBeans)将经历以下生命周期。

  1. 用于客户端业务逻辑
  2. 转换为协议格式
  3. 传送到服务器
  4. 转换回域对象
  5. 用于服务器端业务逻辑

“协议缓冲器和O-O设计”部分在协议留档中建议在适当的域模型内包装生成的类。

我想找出最好的办法。

例如,我有一个简单的原型定义。

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();
    }

}

这是一个好的实践吗?因为这些对象在生命周期的所有阶段都被使用,但是我们只在客户机-服务器传输阶段需要协议格式。

当访问proto Builder类getter/setter方法时,特别是当proto定义复杂且嵌套时,是否存在任何性能问题?

共有2个答案

慕光赫
2023-03-14

我们制作了一个protobuf转换器来解决将域模型对象转换为Google protobuf消息的问题,反之亦然。

如何使用它:

必须转换为protobuf消息的域模型类必须满足以下条件:

  • 类必须由@ProtoClass注释标记,该注释包含对相关protobuf消息类的引用

例如:

@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);

对象列表的转换类似于单个对象的转换。

鲁旭
2023-03-14

我没有协议缓冲区方面的经验,但我不建议实现为特定序列化/传输html" target="_blank">框架定制的域对象。你将来可能会后悔。

软件应用程序的域对象和逻辑应该尽可能独立于特定的实现问题(在您的情况下是序列化/传输),因为您希望您的域易于理解,并且将来可以重用/维护。

如果您想定义独立于序列化/传输的域对象,您有两个选项:

  1. 在序列化/传输之前,将信息复制到特定对象的协议缓冲区,并将其发送到服务器。在那里,您必须将信息复制回域对象
  2. 使用非协议序列化库,如Kryo或ProtoStuff,将域对象直接传输到服务器

选项1的缺点是域被定义了两次(这在修改方面是不可取的)和信息复制(这会产生容易出错且不可维护的代码)。

选项2的缺点是失去了模式演化(尽管ProtoStuff显然支持它),完整(可能较大)的对象图被序列化和传输。尽管可以在序列化/传输之前(手动或使用JGT)修剪对象图。

 类似资料:
  • 问题内容: 我正在使用gSoap将旧式C 系统重构为SOA。我们遇到了一些性能问题(非常大的XML),因此我的领导要我看一下协议缓冲区。我做到了,它看起来非常酷(我们需要C 和Java支持)。但是协议缓冲区是仅用于序列化的解决方案,现在我需要将其发送到Java前端。从C ++和Java角度来看,我应该使用什么来通过HTTP(只是内部网络)发送那些序列化的内容? PS。另一个人试图加速我们的gSoa

  • 请注意:虽然这个问题特别提到了Dropwizard,但我相信任何有泽西/JAX-RS经验的人都应该能够回答这个问题,因为我可以想象Dropwizard只是在幕后遵循泽西/JAX-RS约定。 我有一个Dropwizard服务,它用JSON编写,工作非常出色。 现在我想将其切换为读/写二进制数据(以最小化网络带宽)。我看到了Dropwizard Protobuf库,但我对在Dropwizard中实现二

  • 我试着按照你的指示去做https://github.com/golang/protobuf和https://github.com/google/protobuf/releases安装协议缓冲区。在我将bin路径从下载文件夹添加到之后,我试图运行,但它显示 有没有办法判断我是否正确安装了protobuf? 谢谢

  • 两者都是序列化库,由谷歌开发人员开发。他们之间有什么大的区别吗?将使用协议缓冲区的代码转换为使用FlatBuffers需要大量工作吗?

  • 我们接近100人。proto文件,其中每个文件可以定义大约10个IDL结构(如服务或消息)。 有没有一种方法可以可视化它们,包括引用(从一个文件到另一个文件)。例如类似于UML类图。 可能有可配置的可视化Java /C。 引用自https://developers.google.com/protocol-buffers/docs/overview 协议缓冲区现在是谷歌的通用数据语言——在撰写本文时

  • 试图使用Ionic 4中的协议缓冲区进行编码 我已经下载了协议并用它来生成一堆_pb.js文件,每个. proto文件一个。很好。 首先关注原型示例。这是示例代码: 我做了一些更改以匹配我的文件。更改proto文件的名称。但是我的proto文件中没有包名称。所以我只是使用了消息名称。首先这是我的. proto文件的开头: 下面是我修改后的代码: 这似乎不起作用。我的控制台显示: 我相信我已经成功地