使用Jersey

时间:2015-11-11 13:49:48

标签: java rest asynchronous jersey

是否可以在运行时决定是否应同步或异步处理对资源端点的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(...)即可以异步方式伪造同步版本。但是,我会避免创建异步响应的开销。

2 个答案:

答案 0 :(得分:5)

退一步

JAX-RS异步服务器API 是关于容器如何管理请求的全部内容。但它仍将保留请求,不会影响客户体验

引用有关Asynchronous Server 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");
}

根据documentationContainerRequestContext#getHeaders()会返回带有请求标头的可变地图。

答案 1 :(得分:0)

您可以使用自定义MediaType ...例如,您可以在简单的get方法上放置@Produces(“simple”),在异步get方法上放置@Produces(“asynch”)。在您的客户端中,您可以根据需要将呼叫的接受标头设置为“简单”或“异步”。