Dropwizard 和 Protocol Buffers 的例子
Dropwizard and Protocol Buffers by example
请注意:虽然这个问题特别提到了Dropwizard,但我相信有Jersey/JAX-RS经验的人应该能够回答这个问题,正如我想象的那样,Dropwizard 只是在幕后遵循 Jersey/JAX-RS 约定。
我有一个 Dropwizard 服务,reds/writes 在 JSON 中运行得很好。
我现在想将其切换为 read/write 二进制数据(以最小化网络带宽)。我看到有 Dropwizard-Protobuf lib 但我对在 Dropwizard 中实现二进制序列化有一些担忧。
首先,这是我当前(JSON 中心)代码中的重要内容:
// Groovy pseudo-code
// Domain entity/POJO
@JsonIgnoreProperties(ignoreUnknown = true)
@JsonInclude(JsonInclude.Include.NON_NULL)
class Fizz {
@JsonProperty
String name
@JsonProperty
boolean isBuzz
}
// The Dropwizard app entry point
class FizzService extends Application<FizzConfiguration> {
@Override
void run(FizzConfiguration fizzCfg, Environment env) throws Exception {
// ... lots of stuff
env.jersey().register(new FizzService())
}
}
// JAX-RS resource with a sample GET endpoint
@Path(value = "/fizz")
@Produces(MediaType.APPLICATION_JSON)
class FizzResource {
@GET
@Path("/{id}")
Fizz getFizzById(@PathParam("id") int id) {
// Look up a 'Fizz' in a DB and return it.
lookupFizzinDB(id)
}
}
因此,如您所见,GET /fizz
端点需要一个 JSON 请求实体,其中包含一个名为 id
且类型为 int
的元素。它 returns 与提供的 id
.
相匹配的 Fizz
响应实体
我想通过 Google Protocol Buffers.
将其从 JSON 切换为二进制
根据 Dropwizard-Protobuf 文档,这就像将其添加到我的 FizzService#run(...)
方法一样简单:
environment.jersey().register(new ProtocolBufferMessageBodyProvider())
问题是目前我的整个应用程序连接到 serialize/deserialize to/from JSON。我的 Fizz
class 上的 @JsonProperty
注释对 Dropwizard 有意义。 FizzResource
上的 @Produces(MediaType.APPLICATION_JSON)
注释也起着关键作用。我担心制作我的 Dropwizard 应用程序 read/write protobuf 生成的二进制文件不像文档中发布的 1-liner 那样容易。
我没有和这个图书馆结婚。如果有人有任何在 Dropwizard 应用程序中将 REST 端点设置为 accept/receive protobuf 生成的二进制文件的经验,我所关心的只是一个有效的、高效的解决方案。想法?
你说得对,它不像单线那么容易。您需要让 protobuf 生成代码才能工作。查看 Protocol Buffers Documentation。您首先需要有一个使用 protobuf 编译器编译的 proto 文件,它会为您生成代码。此生成的代码是您用来构建 domain/model objects 的代码。来自 Dropwizard 的 protobuf 提供程序使用此编译代码。无论您是否使用 Dropwizard 提供程序,您仍然需要使用生成的代码。见上文link."How do I start"部分。
生成代码后,在您的资源方法中,生成的 class/type 是您需要 return 以便提供程序能够对其进行序列化的内容。您还需要在资源方法或资源 class 上设置 @Produces("application/x-protobuf")
或 @Produces(ProtocolBufferMediaType.APPLICATION_PROTOBUF)
,以便 Jersey 知道如何找到媒体类型的提供者。
您可以同时支持 application/json
和 application/x-protobuf
,因为您可以在 @Produces
中拥有不止一种媒体类型。只需使用语法 @Produces({ .. , .. })
.
但这还不是全部。由于您将需要 return 两种不同的类型,即 JSON 的简单 POJO 或 Protobuf 的生成类型,您将需要检查资源方法中的 header
@Produces({"application/json", "application/x-protobuf"})
public Response getFoo(@Context HttpHeaders headers) {
List<MediaType> accepts = headers.getAcceptableMediaTypes();
if (accepts.contains(MediaType.APPLICATION_JSON_TYPE) {
return Response.ok(new Foo());
} else if (accepts.contains(ProtocolBufferMediaType.APPLICATION_PROTOBUF_TYPE) {
return Reponse.ok(new ProtoBufFoo());
} else {
// default
return Response.ok(new Foo());
}
}
或者你可以有两种不同的方法,每种方法一种
@Produces("application/json")
public Response getFooJson() {
return Response.ok(new Foo());
}
@Produces("application/x-protobuf")
public Response getFooProto() {
return Response.ok(new ProtoBufFoo());
}
无论客户端发送什么作为它的Accept
header,这就是将被发送出去的类型。例如 Accept: application/json
或 Accept: application/x-protobuf
另请参阅:
请注意:虽然这个问题特别提到了Dropwizard,但我相信有Jersey/JAX-RS经验的人应该能够回答这个问题,正如我想象的那样,Dropwizard 只是在幕后遵循 Jersey/JAX-RS 约定。
我有一个 Dropwizard 服务,reds/writes 在 JSON 中运行得很好。
我现在想将其切换为 read/write 二进制数据(以最小化网络带宽)。我看到有 Dropwizard-Protobuf lib 但我对在 Dropwizard 中实现二进制序列化有一些担忧。
首先,这是我当前(JSON 中心)代码中的重要内容:
// Groovy pseudo-code
// Domain entity/POJO
@JsonIgnoreProperties(ignoreUnknown = true)
@JsonInclude(JsonInclude.Include.NON_NULL)
class Fizz {
@JsonProperty
String name
@JsonProperty
boolean isBuzz
}
// The Dropwizard app entry point
class FizzService extends Application<FizzConfiguration> {
@Override
void run(FizzConfiguration fizzCfg, Environment env) throws Exception {
// ... lots of stuff
env.jersey().register(new FizzService())
}
}
// JAX-RS resource with a sample GET endpoint
@Path(value = "/fizz")
@Produces(MediaType.APPLICATION_JSON)
class FizzResource {
@GET
@Path("/{id}")
Fizz getFizzById(@PathParam("id") int id) {
// Look up a 'Fizz' in a DB and return it.
lookupFizzinDB(id)
}
}
因此,如您所见,GET /fizz
端点需要一个 JSON 请求实体,其中包含一个名为 id
且类型为 int
的元素。它 returns 与提供的 id
.
Fizz
响应实体
我想通过 Google Protocol Buffers.
将其从 JSON 切换为二进制根据 Dropwizard-Protobuf 文档,这就像将其添加到我的 FizzService#run(...)
方法一样简单:
environment.jersey().register(new ProtocolBufferMessageBodyProvider())
问题是目前我的整个应用程序连接到 serialize/deserialize to/from JSON。我的 Fizz
class 上的 @JsonProperty
注释对 Dropwizard 有意义。 FizzResource
上的 @Produces(MediaType.APPLICATION_JSON)
注释也起着关键作用。我担心制作我的 Dropwizard 应用程序 read/write protobuf 生成的二进制文件不像文档中发布的 1-liner 那样容易。
我没有和这个图书馆结婚。如果有人有任何在 Dropwizard 应用程序中将 REST 端点设置为 accept/receive protobuf 生成的二进制文件的经验,我所关心的只是一个有效的、高效的解决方案。想法?
你说得对,它不像单线那么容易。您需要让 protobuf 生成代码才能工作。查看 Protocol Buffers Documentation。您首先需要有一个使用 protobuf 编译器编译的 proto 文件,它会为您生成代码。此生成的代码是您用来构建 domain/model objects 的代码。来自 Dropwizard 的 protobuf 提供程序使用此编译代码。无论您是否使用 Dropwizard 提供程序,您仍然需要使用生成的代码。见上文link."How do I start"部分。
生成代码后,在您的资源方法中,生成的 class/type 是您需要 return 以便提供程序能够对其进行序列化的内容。您还需要在资源方法或资源 class 上设置 @Produces("application/x-protobuf")
或 @Produces(ProtocolBufferMediaType.APPLICATION_PROTOBUF)
,以便 Jersey 知道如何找到媒体类型的提供者。
您可以同时支持 application/json
和 application/x-protobuf
,因为您可以在 @Produces
中拥有不止一种媒体类型。只需使用语法 @Produces({ .. , .. })
.
但这还不是全部。由于您将需要 return 两种不同的类型,即 JSON 的简单 POJO 或 Protobuf 的生成类型,您将需要检查资源方法中的 header
@Produces({"application/json", "application/x-protobuf"})
public Response getFoo(@Context HttpHeaders headers) {
List<MediaType> accepts = headers.getAcceptableMediaTypes();
if (accepts.contains(MediaType.APPLICATION_JSON_TYPE) {
return Response.ok(new Foo());
} else if (accepts.contains(ProtocolBufferMediaType.APPLICATION_PROTOBUF_TYPE) {
return Reponse.ok(new ProtoBufFoo());
} else {
// default
return Response.ok(new Foo());
}
}
或者你可以有两种不同的方法,每种方法一种
@Produces("application/json")
public Response getFooJson() {
return Response.ok(new Foo());
}
@Produces("application/x-protobuf")
public Response getFooProto() {
return Response.ok(new ProtoBufFoo());
}
无论客户端发送什么作为它的Accept
header,这就是将被发送出去的类型。例如 Accept: application/json
或 Accept: application/x-protobuf
另请参阅: