Dropwizard和协议缓冲区示例

sme*_*eeb 3 jax-rs jersey protocol-buffers binary-serialization dropwizard

请注意:尽管这个问题特别提到了Dropwizard,但我相信任何具有Jersey / JAX-RS经验的人都应该能够回答这个问题,因为我认为Dropwizard只是遵循了Jersey / JAX-RS的惯例。


我有一个Dropwizard服务,该服务以JSON 进行改写 /编写,并且效果很好。

我现在想将其切换为读/写二进制数据(以最小化网络带宽)。我看到有Dropwizard-Protobuf库,但是我对在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)
    }
}
Run Code Online (Sandbox Code Playgroud)

如您所见,GET /fizz端点期望JSON请求实体包含一个名为idtype 的元素int。它返回Fizz与提供的相匹配的响应实体id

我想通过Google Protocol Buffers将其从JSON切换为二进制。

根据Dropwizard-Protobuf文档,这就像将其添加到我的FizzService#run(...)方法中一样简单:

environment.jersey().register(new ProtocolBufferMessageBodyProvider())
Run Code Online (Sandbox Code Playgroud)

问题是,当前我的整个应用程序都已连接到JSON /从JSON反序列化。@JsonPropertyFizz班上的注释对Dropwizard有意义。上的@Produces(MediaType.APPLICATION_JSON)注释FizzResource也起着关键作用。我担心让我的Dropwizard应用程序读/写protobuf生成的二进制文件并不像文档中发布的1-liner那样容易。

我没有嫁给这个图书馆。如果任何人有任何在Dropwizard应用程序中设置REST端点以接受/接收由protobuf生成的二进制文件的经验,我所关心的就是一个有效,有效的解决方案。有想法吗?

Pau*_*tha 6

没错,这并不像一支班轮那么容易。您需要使protobuf生成代码才能正常工作。查看协议缓冲区文档。首先,您需要具有一个protobuf编译器编译的proto文件,该文件会为您生成代码。此生成的代码是用于构建域/模型对象的代码。Dropwizard的protobuf提供程序可以处理此编译代码。无论您是否使用Dropwizard提供程序,您都仍然需要使用生成的代码。请参阅以上链接中的“如何开始”部分。

获得生成的代码之后,然后在您的资源方法中,将需要返回生成的类/类型,以使提供程序能够对其进行序列化。您还需要在资源方法或资源类上使用@Produces("application/x-protobuf")@Produces(ProtocolBufferMediaType.APPLICATION_PROTOBUF)在其上,因此Jersey知道如何找到媒体类型的提供程序。

您可以同时支持application/jsonapplication/x-protobuf,因为您可以在中添加多种媒体类型@Produces。只需使用语法@Produces({ .. , .. })

那还不是全部。由于您将需要返回两种不同的类型,即用于JSON的简单POJO或用于Protobuf的生成的类型,因此您将需要在resource方法中检查标头

@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());
    }
}
Run Code Online (Sandbox Code Playgroud)

或者您可以有两种不同的方法,每种类型一种

@Produces("application/json")
public Response getFooJson() {
    return Response.ok(new Foo());
}

@Produces("application/x-protobuf")
public Response getFooProto() {
    return Response.ok(new ProtoBufFoo());
}
Run Code Online (Sandbox Code Playgroud)

客户端发送的任何内容作为其Accept标头,即要发送的类型。例如Accept: application/jsonAccept: application/x-protobuf

也可以看看: