是否可以在运行时决定是否应同步或异步处理对资源端点的Jersey REST请求?我们举一个简单的例子。
同步版本:
@Path("resource")
public class Resource {
@GET
@Produces({MediaType.TEXT_PLAIN})
public Response get() {
return Response.ok("Hello there!").build();
}
}
异步版本:
@Path("resource")
public class Resource {
@GET
@Produces({MediaType.TEXT_PLAIN})
public void get(@Suspended final AsyncResponse r) {
r.resume(Response.ok("Hello there!").build()); // usually called somewhere from another thread
}
}
根据某些参数,我想在运行时决定是应该同步还是异步处理GET请求。在两种情况下,资源端点(http://server/resource
)的URL必须相同。这可能吗?
当然,正如您在上面的示例中所看到的,只需调用AsyncResponse.resume(...)
即可以异步方式伪造同步版本。但是,我会避免创建异步响应的开销。
答案 0 :(得分:5)
JAX-RS异步服务器API 是关于容器如何管理请求的全部内容。但它仍将保留请求,不会影响客户体验。
的Jersey文档注意使用服务器端异步处理模型会 不会改善客户端感知的请求处理时间。它 然而,通过释放,将增加服务器的吞吐量 初始请求处理线程时返回I / O容器 请求可能仍在队列中等待处理或 处理可能仍在另一个专用线程上运行。该 发布的I / O容器线程可用于接受和处理新的 传入请求连接。
下面描述的方法不会给您的客户带来任何好处。
您可以为同步和异步方法使用不同的URL,并创建一个pre-matching filter,它在请求匹配开始之前执行。
要执行此操作,请实施ContainerRequestFilter
,使用@PreMatching
对其进行注释,并根据您的条件(标题,参数等)更改请求的URI:
@Provider
@PreMatching
public class PreMatchingFilter implements ContainerRequestFilter {
@Override
public void filter(ContainerRequestContext requestContext) throws IOException {
if (requestContext.getHeaders().get("X-Use-Async") != null) {
requestContext.setRequestUri(yourNewURI);
}
}
}
查看ContainerRequestContext
API。
我还没有测试过以下解决方案,但它应该可行。您可以为同步和异步方法保留相同的URL,只接受每种方法的不同内容类型。
例如:
@Consumes("application/vnd.example.sync+text")
@Consumes("application/vnd.example.async+text")
并根据您的条件使用PreMatchingFilter
更改Content-Type
标题,如下所示:
if (useSync) {
requestContext.getHeaders().putSingle(
HttpHeaders.CONTENT_TYPE, "application/vnd.example.sync+text");
} else {
requestContext.getHeaders().putSingle(
HttpHeaders.CONTENT_TYPE, "application/vnd.example.async+text");
}
根据documentation,ContainerRequestContext#getHeaders()
会返回带有请求标头的可变地图。
答案 1 :(得分:0)
您可以使用自定义MediaType ...例如,您可以在简单的get方法上放置@Produces(“simple”),在异步get方法上放置@Produces(“asynch”)。在您的客户端中,您可以根据需要将呼叫的接受标头设置为“简单”或“异步”。