java - 使用 Jersey 在运行时决定同步或异步响应

标签 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 请求。在这两种情况下,资源端点的 URL (http://server/resource) 必须相同。这可能吗?

当然,如您在上面的示例中所见,可以通过简单地调用 AsyncResponse.resume(...) 以异步方式伪造同步版本。但是,我会避免创建异步响应的开销。

最佳答案

退一步

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

引用关于 Asynchronous Server API 的 Jersey 文档:

Note that the use of server-side asynchronous processing model will not improve the request processing time perceived by the client. It will however increase the throughput of the server, by releasing the initial request processing thread back to the I/O container while the request may still be waiting in a queue for processing or the processing may still be running on another dedicated thread. The released I/O container thread can be used to accept and process new incoming request connections.

下面描述的方法不会给您的客户带来任何好处。

使用自定义 header

您可以为同步和异步方法使用不同的 URL,并创建一个 pre-matching filter ,在请求匹配开始之前执行。

为此,实现 ContainerRequestFilter , 注释为 @PreMatching并根据您的条件( header 、参数等)更改请求的 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 header ,如下所示:

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()返回带有请求 header 的可变映射。

关于java - 使用 Jersey 在运行时决定同步或异步响应,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33651968/

相关文章:

java - 图论 : Find the Jordan center?

java - 在没有默认构造函数的内部类时使用 Jackson 解码 JSON

java - 如何编写读取 MongoDB 数据库的 Maven Java Azure 函数?

api - 用于插入/更新文档的 Couchbase REST API

java - 每隔几秒更新一次 android studio 中的 gps 位置

java - 如何将 String 从 Servlet 传输到 JSP?

node.js - 使用Postman时如何解决nodejs中的CORS错误?

java - 创建@Service bean的对象,可能吗?

node.js - 如何使用 async.parallelLimit 来最大化(并行)运行进程的数量?

javascript - 对 Javascript 中的轻量级开源 AJAX 库的建议