请注意:虽然这个问题特别提到了Dropwizard,但我相信任何有Jersey / JAX-RS经验的人应该能够回答这个问题,就像我想象的Dropwizard只是遵循Jersey / JAX-RS惯例。
我有一个Dropwizard服务,可以用JSON进行红色/写入并且工作得非常好。
我现在想把它切换到读/写二进制数据(以最小化网络带宽)。我看到有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
的{{1}}类型的元素。它返回与提供的int
匹配的Fizz
响应实体。
我想通过Google Protocol Buffers将其从JSON切换为二进制。
根据Dropwizard-Protobuf文档,这就像添加到我的id
方法一样简单:
FizzService#run(...)
问题是目前我的整个应用程序都连接到JSON的序列化/反序列化。我的environment.jersey().register(new ProtocolBufferMessageBodyProvider())
类上的@JsonProperty
注释对Dropwizard有意义。 Fizz
上的@Produces(MediaType.APPLICATION_JSON)
注释也起着至关重要的作用。我担心让我的Dropwizard应用程序读/写protobuf生成的二进制文件并不像文档中发布的1-liner一样简单。
我没跟这个图书馆结婚。如果有人在Dropwizard应用程序中设置REST端点以接受/接收protobuf生成的二进制文件的经验,我所关心的只是一个有效的解决方案。想法?
答案 0 :(得分:5)
你是对的,它不像一个班轮那么容易。您需要让protobuf生成代码才能正常工作。查看Protocol Buffers Documentation。首先需要一个使用protobuf编译器编译的proto文件,它会为您生成代码。生成的代码就是您用来构建域/模型对象的代码。 Dropwizard的protobuf提供程序可以处理这个编译过的代码。无论您是否使用Dropwizard提供程序,您仍然需要使用生成的代码。请参阅上面链接中的“我如何开始”部分。
获得生成的代码之后,在资源方法中,生成的类/类型是您需要返回的内容,供提供程序能够序列化它。您还需要在资源方法或资源类上使用@Produces("application/x-protobuf")
或@Produces(ProtocolBufferMediaType.APPLICATION_PROTOBUF)
,因此Jersey知道如何查找媒体类型的提供程序。
您可以同时支持application/json
和application/x-protobuf
,因为您可以在@Produces
中拥有更多的媒体类型。只需使用语法@Produces({ .. , .. })
。
但并非如此。由于您需要返回两种不同的类型,即简单的JJ POJO或Protobuf的生成类型,您需要检查资源方法中的标题
@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
标头,这都是将被发送出去的类型。例如Accept: application/json
或Accept: application/x-protobuf
另见: