Dropwizard 支持多种序列化格式

Dropwizard support for multiple serialization formats

在 RESTful API 中看到可以支持多种序列化格式的端点非常典型:

// Sends back "fizz" resource that has an id=34 as a JSON object
http://api.example.com/v2/fizz/34.json

// Sends back "fizz" resource that has an id=34 as an XML object
http://api.example.com/v2/fizz/34.xml

// Sends back "fizz" resource that has an id=34 as a binary object,
// say, using Google Protocol Buffers
http://api.example.com/v2/fizz/34.bin

我正在设计一个 Dropwizard 服务,并试图弄清楚如何实现多种格式支持,但是这方面的文档很少。有什么想法吗?

一般来说,对不同格式配置的支持只需在 @Produces@Consumes 注释中以声明方式完成。当客户端发送数据时,Content-Type请求header应该设置为发送数据的实际类型。

例如,如果客户端正在发送JSON数据,那么客户端应该设置请求headerContent-Type: application/json。 Jersey 将寻找方法或 class 与 @Consume("application/json")。如果找到它,则表示该应用已配置为支持媒体类型 application/json。如果不支持,则客户端将收到回复,说明不支持媒体类型。

同理当客户端请求数据时,应该设置Accept: application/json请求header。泽西岛将寻找 @Produces("application/json")。如果它无法为端点找到它,那么客户端将收到一条消息,说明它不是可接受的类型。

因此我们可以为同一端点支持不同的媒体类型。你可以像

这样声明方法
@Produces({"application/json", "application/xml", "application/x-protobuf"})
public Response getFoo() {
    return Response.ok(new Foo());
} 

你需要关心的事情是 如果 每个媒体类型都有一个 MessageBodyWriter 可以处理 [=23] 的序列化=] 类型。在 JAX-RS Entity Providers.

查看更多

或者,如果 application/jsonapplication/xmlapplication/x-protobuf 媒体类型需要不同的域类型进行序列化,您可以使用不同的方法来处理不同的类型。例如,application/jsonapplication/xml,你通常可以使用相同的 Foo 域 object,所以你可以只做

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

但是对于Protobuf,它需要Protobuf编译classes。因此,您将 return 生成的类型代替 Foo 域 object。

@Produces("application/x-protobuf")
public Response getFooProtobuf() {
    return Response.ok(new ProtobufFoo());
}

至于您在 URL 中使用 .xml.json 扩展名,客户通常不会这样说它想要什么类型。通常将 Accept 请求 header 设置为您的服务器支持的类型之一,如上所述。

但是 支持 URL 类型扩展,但它通常适用于无法设置 header 的客户s,例如浏览器。但是您需要使用 UriConnegFilter 配置这些媒体类型映射。例如

Map<String, MediaType> map = new HashMap<>();
map.put("xml", MediaType.APPLICATION_XML_TYPE);
map.put("json", MediaType.APPLICATION_JSON_TYPE);
map.put("bin", ProtocolBufferMediaType.APPLICATION_PROTOBUF_TYPE);
env.jersey().property(ServerProperties.MEDIA_TYPE_MAPPINGS, map);

另请参阅: