给定秒数后中断HTTP请求

时间:2019-04-10 09:34:02

标签: java swagger

我为我的API使用Java 1.8,dropwizard 1.3.5和大张旗鼓的变化1.0.13。

我有一个方法,它需要一个HTTP请求,延迟20秒,然后返回200状态码响应:

public ResponseContext delayBy20Seconds(RequestContext context) {
    ResponseContext response = new ResponseContext().contentType(MediaType.APPLICATION_JSON_TYPE);

    Thread.sleep(20000);

    response.status(Response.Status.OK);
    return response;
}

说,如果操作(在这种情况下需要20秒)超过15秒,我想返回400状态代码。我将如何实现?

2 个答案:

答案 0 :(得分:4)

您可以使用Google Guava库中的TimeLimiter之类的东西。这允许您将可调用对象包装在可以使用超时调用的操作中。如果可调用对象未及时完成操作,它将抛出一个TimeoutException,您可以捕获并返回400响应。

例如:

TimeLimiter timeLimiter = new SimpleTimeLimiter();
try {
  String result = timeLimiter.callWithTimeout(
                () -> doSomeHeavyWeightOperation(), 15, TimeUnit.SECONDS);
} catch (TimeoutException e) {
  // return 400
}

答案 1 :(得分:4)

一种无需其他库即可完成此操作的方法是使用java.util.concurrent软件包。取消此类长期运行任务的最可靠方法是在单独的线程中运行它。

import java.util.concurrent.*;

...

private ExecutorService exec = Executors.newSingleThreadExecutor();
public ResponseContext delayBy20Seconds(RequestContext context) {
    Callable<ResponseContext> task = new Callable<ResponseContext>() {
        @Override
        public ResponseContext call() throws Exception {
            Thread.sleep(20000);
            return new ResponseContext().contentType(MediaType.APPLICATION_JSON_TYPE);
        }
    };
    List<Callable<ResponseContext>> tasks = new ArrayList<>();
    tasks.add(task);
    List<Future<ResponseContext>> done = exec.invokeAll(tasks, 15, TimeUnit.SECONDS);
    Future<ResponseContext> task1 = done.get(0);
    if (task1.isCancelled()) {
        return some Error Response;
    }
    return task1.get();
}

您的ExecutorService应该不是静态的,因为您不想为此特定用途在线程之间共享它。

Callable<ResponseContext>实现是完成长时间运行任务的工作的地方。正如在exec.invokeAll调用中显而易见的那样,我们告诉我们我们愿意等待多少。返回的期货列表将始终包含与任务列表一样多的元素,因此无需检查其是否为空。我们只需要检查任务是否完成即可。