我正在尝试找到一种异步方式来立即返回客户端请求的响应。
我需要的只是记录请求数据,调用新线程来请求在其他服务器上进行昂贵的操作(一些后端操作) 并且无需等待他们的回复,立即向客户返回200状态响应。
此刻我正在尝试使用CompletableFuture,但我遗漏了一些东西。
package com.example.controller;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.core.Logger;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.util.concurrent.CompletableFuture;
@Path("/class")
public class AsynchronousResponse {
private static final Logger LOGGER = (Logger) LogManager.getLogger(AsynchronousResponse.class.getName());
private static final int HTTP_STATUS_OK = 200;
private static final String EMPTY_CONTENT = "";
@Context
private HttpServletRequest httpRequest;
@Path("/method")
@GET
@Consumes(MediaType.APPLICATION_JSON)
public Response asyncResponseSupply() {
LOGGER.info(httpRequest.getSession().getId() + " : New session received");
CompletableFuture.supplyAsync(this::veryExpensiveOperations);
LOGGER.info(httpRequest.getSession().getId() + " : Returning empty response... ");
return Response.status(HTTP_STATUS_OK).entity(EMPTY_CONTENT).build();
}
// need to do some operations on data from httpRequest
private String veryExpensiveOperations() {
LOGGER.info(httpRequest.toString());
LOGGER.info("Start very expensive operations");
try {
Thread.sleep(3000);
LOGGER.info("Finished");
return "DONE";
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
e.printStackTrace();
LOGGER.error("Error: " + e.getMessage());
return "ERROR";
}
}
}
总而言之,我得到了立即响应,但是VeryExpensiveOperations()方法似乎失去了httpRequest值,这对我来说太糟糕了因为我需要使用来自客户端请求的值调用其他web服务。谢谢你的帮助!
对于我的应用我正在使用Jetty ver。 9.2.18.v20160721
答案 0 :(得分:3)
完成对servlet的调度后,将提交响应并回收请求和响应对象。
要处理servlet规范,必须使用AsyncContext
(通过HttpServletRequest.startAsync()
调用获得)让容器知道请求/响应尚未完成,并且处理它是发生在非调度线程中(如CompletableFuture.supplyAsync()
调用)
至于如何混合JAX-RS和AsyncContext
,我不知道。我甚至不知道JAX-RS是否已经更新以支持AsyncContext
。
答案 1 :(得分:1)
感谢Joakim的回答(我不能赞成它,因为我在这里很新,我没有足够的声誉)。根据您对gem install rails
的了解,我找到了一种快速回复的方法。更改后的代码(适用于runAsync和supplyAsync):
AsyncContext