我有一个对象是' Level'对象和我测试用Spring Boot Rest Controller以两种方式传输它们:
使用JSON,在Rest Controller中我使用类似的东西:
@RequestMapping(value = "/api/v1/layers/{layername}", method = RequestMethod.GET, produces = "application/json")
public @ResponseBody List<Level> query(@PathVariable String layername,
@RequestParam("northEastLat") Float northEastLat,
@RequestParam("northEastLng") Float northEastLng,
@RequestParam("northWestLat") Float northWestLat,
@RequestParam("northWestLng") Float northWestLng,
@RequestParam("southEastLat") Float southEastLat,
@RequestParam("southEastLng") Float southEastLng,
@RequestParam("southWestLat") Float southWestLat,
@RequestParam("southWestLng") Float southWestLng
) {
List<Level> poligons=levelService.obtainLevels(layername,southWestLng,southWestLat,northWestLng,northWestLat,northEastLng,northEastLat,southEastLng,southEastLat);
int i=1;
for (Level p : poligons) {
System.out.println("poligon" + i++ + " is:" + p.toString());
}
return poligons;
}
使用Protostuff Protobuf格式,我使用类似的东西:
@RequestMapping(value = "/api/v1/layers/{layername}", method = RequestMethod.GET,produces = "text/plain")
public String query(@PathVariable String layername,
@RequestParam("northEastLat") Float northEastLat,
@RequestParam("northEastLng") Float northEastLng,
@RequestParam("northWestLat") Float northWestLat,
@RequestParam("northWestLng") Float northWestLng,
@RequestParam("southEastLat") Float southEastLat,
@RequestParam("southEastLng") Float southEastLng,
@RequestParam("southWestLat") Float southWestLat,
@RequestParam("southWestLng") Float southWestLng
) {
List<Level> poligons=levelService.obtainLevels(layername,southWestLng,southWestLat,northWestLng,northWestLat,northEastLng,northEastLat,southEastLng,southEastLat);
LevelList list = new LevelList(poligons);
byte[] bytes;
int i=1;
for (Level p : poligons) {
System.out.println("poligon" + i++ + " is:" + p.toString());
}
Schema<LevelList> schema = RuntimeSchema.getSchema(LevelList.class);
LinkedBuffer buffer = LinkedBuffer.allocate();
try
{
bytes = ProtostuffIOUtil.toByteArray(list, schema, buffer);
}
finally
{
buffer.clear();
}
return new String(bytes);
}
Level对象格式为: [{&#34; wkb_geometry&#34;:&#34; {&#34;类型&#34;:&#34;多边形&#34;&#34;坐标&#34;:[[[24.446822,45.34997] [24.706508,45.352485]]]}&#34;&#34; ID&#34; 199&#34;电平&#34;:&#34; 3&#34;&#34;类型&#34 ;日期null}
Level对象是:
@Entity(name = "Level")
@Table(name="Level2G")
@SecondaryTables({
@SecondaryTable(name="Level3G"),
@SecondaryTable(name="Level4G")
})
public class Level implements Serializable {
private static final long serialVersionUID = 1L;
// @Column(name = "wkb_geometry",columnDefinition="Geometry")
//@Type(type = "org.hibernate.spatial.GeometryType")
@Column(name="wkb_geometry")
private /*Geometry */ String wkb_geometry;
@Id
@Column(name="id")
private Integer id;
@Column(name="level")
private String level;
@Transient
private String type;
public Level() {
}
public Level(String wkb_geometry, Integer id, String level) {
this.wkb_geometry = wkb_geometry;
this.id = id;
this.level = level;
this.type = "Feature";
}
public Level(String wkb_geometry, Integer id, String level, String type) {
this.wkb_geometry = wkb_geometry;
this.id = id;
this.level = level;
this.type = type;
}
public Object getWkb_geometry() {
return wkb_geometry;
}
public void setWkb_geometry(String wkb_geometry) {
this.wkb_geometry = wkb_geometry;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getLevel() {
return level;
}
public void setLevel(String level) {
this.level = level;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
@Override
public String toString() {
return "Level{" +
"wkb_geometry=" + wkb_geometry +
", id=" + id +
", level='" + level + '\'' +
", type='" + type + '\'' +
'}';
}
}
LevelList对象只是Level对象列表
问题是,使用Protostuff,与JSON(3.7kb)相比,我获得了更大的有效载荷(26 kb)。为什么呢?
对于第二个选项,我也尝试设置&#34; application / octet-stream&#34;直接返回字节但仍然是相同的结果。我还比较了JSON和protobuf的速度; protobuf具有更好的性能,即使有更大的有效载荷。知道为什么吗?
答案 0 :(得分:1)
Protostuff和Protobuf不是一回事。 Protostuff是一个包装库,可以使用许多不同的序列化格式。它还支持您似乎正在使用的运行时模式生成。该运行时架构需要发送额外的元数据以及消息,以告知接收者消息的架构。我猜你所看到的大型消息主要来自这个运行时架构数据。
使用标准的Protobuf,架构不会随消息一起发送,因为假设发件人和收件人已经就编译到两个程序中的.proto
文件提供的架构达成一致。如果您使用带有标准.proto
文件的Protobuf,您会发现它生成的消息比JSON小得多。
答案 1 :(得分:0)
您的测试中至少有一个问题。
从字节数组到String的转换无效:
bytes = ProtostuffIOUtil.toByteArray(list, schema, buffer);
return new String(bytes);
String的构造函数将尝试将字节数组解析为UTF-8字符串(最可能;取决于您的语言环境设置),但根据定义给定的数据不是有效的UTF-8字符串。
如果您想进行更好的尺寸比较,您应该以下列形式编写测试:
LevelList source = testData();
byte[] jsonData = generateJson(source);
byte[] protobufData = generateProtobuf(source);
System.out.println("JSON=" + jsonData.size() + " Protobuf=" + protobufData.size());
这里的要点是让你的测试可以重现,以便其他人可以重复它。