欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

使用java原生url连接传输protobuf

程序员文章站 2022-05-19 18:01:28
...

protobuf已经出来好多年了,原谅我最近才了解到google这个高性能的用于传输的格式。

 

从各方面来看,它无论从序列化的性能还是从序列化的压缩比都是优于当前各种传输格式的。如json、xml、hessian,java原生的Serializable。具体对比结果参见:http://agapple.iteye.com/blog/859052

 

网上也看了些资料,并有所了解,看了下,这玩意儿性能上来说真的没什么可说,但初始化和使用的时候感觉不是特别方便。而且网上的例子多数都是序列化过程,没有很多关于演示网络传输的demo,于是自己简单写了一个,将完整的例子摆在这里。

 

先定义一个Person.proto

 

option java_package = "com.example.protobuf";
option java_outer_classname = "PersonProbuf";

message Person {
  required string name = 1;
  required int32 id = 2;
  optional string email = 3;
  repeated PhoneNumber phone = 4;

  enum PhoneType {
    MOBILE = 0;
    HOME = 1;
    WORK = 2;
  }

  message PhoneNumber {
    required string number = 1;
    optional PhoneType type = 2 [default = HOME];
  }
}

 使用protoc生成对应的PersonProtobuf类

 

 

protoc.exe Person.proto --java_out=.

 

 

请求客户端代码如下:

 

PersonProbuf.Person.Builder personRequest = PersonProbuf.Person.newBuilder();
personRequest.setId(1);
personRequest.setName("jesse");
personRequest.setEmail("xx@xx.com");
        personRequest.addPhone(PersonProbuf.Person.PhoneNumber.newBuilder().setNumber("1234567890").setType(PersonProbuf.Person.PhoneType.HOME));

//使用java原生URL连接代码生成请求并获得返回值打印        
URL url = new URL("http://localhost:90/protobuf.jsp");
URLConnection connection = url.openConnection();
connection.setDoOutput(true);
personRequest.build().writeTo(connection.getOutputStream());
        
PersonProbuf.Person personResponse = PersonProbuf.Person.parseFrom(connection.getInputStream());
System.out.println(personResponse.getId());
System.out.println(personResponse.getName());
System.out.println(personResponse.getEmail());
System.out.println(personResponse.getPhone(0));
System.out.println(personResponse.getPhone(1));

  

服务端protobuf.jsp代码如下:

 

<%@ page pageEncoding="UTF-8"%>
<%@page import="com.example.protobuf.PersonProbuf"%>
<%
PersonProbuf.Person person = PersonProbuf.Person.parseFrom(request.getInputStream());
System.out.println(person.getId());
System.out.println(person.getName());
System.out.println(person.getEmail());
System.out.println(person.getPhone(0));
PersonProbuf.Person.Builder personBuilder = person.newBuilder(person);
personBuilder.setId(2);
personBuilder.setName("tiger");
personBuilder.setEmail("yy@yy.com");
personBuilder.addPhone(PersonProbuf.Person.PhoneNumber.newBuilder().setNumber("0987654321").setType(PersonProbuf.Person.PhoneType.HOME));
personBuilder.build().writeTo(response.getOutputStream());
%>

 

执行客户端代码后,服务端/客户端输出:

------服务端输出------
1
jesse
xx@xx.com
number: "1234567890"
type: HOME

------客户端输出------
2
tiger
yy@yy.com
number: "1234567890"
type: HOME

number: "0987654321"
type: MOBILE

 

 

所以protobuf只是一种序列化的格式,并不是传输协议,需要传输的,只要使用输入输出流,就可以做任何保存,传输的操作。

 

另外百度写了个jprotobuf开源,使用起来挺方便,只要使用注解放在javabean上就可以了

github:https://github.com/jhunters/jprotobuf

不过这个开源工具对集合没有适合的注解,而且也没有说明和其他语言传输的时候,如何保证一致性,所以需要使用的人考虑清楚,需要慎用。

相关标签: protobuf