【问题标题】:Java Rest API Calling another Rest without waiting for the response - in JAX-RSJava Rest API 在不等待响应的情况下调用另一个 Rest - 在 JAX-RS 中
【发布时间】:2018-03-09 12:36:55
【问题描述】:

我有一个案例要在我的项目中实施。下面是一个必须实施的示例休息服务

    @GET
    @Path("/test/{id}")
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
    public String getData(@PathParam("id") String id) {
        //Some processing to get value of String
        String result = doSomeProcessing();

        //I want to return this result to GUI and call one more rest api  
        // and end this process without waiting for response from second 
        //call

       new Thread(){
       //call second rest api
       }.start();

       return result;      

    }

这是使用新线程调用第二个休息 API 并返回结果而不等待第二个休息 API 响应的好方法吗? 我也研究了异步休息调用,但它并不完全符合我的要求。请指教。提前致谢

【问题讨论】:

  • 所以客户端不需要第二次API调用的结果?
  • 是的,客户端不需要第二次 API 调用的结果

标签: java rest web-services jax-rs


【解决方案1】:

避免直接启动Threads。请考虑使用ExecutorService,如下所示:

@Singleton
@Path("foo")
public class FooResource {

    private ExecutorService executor;

    @PostConstruct
    public void onCreate() {

        // Creates a thread pool that reuses a fixed number 
        // of threads operating off a shared unbounded queue
        this.executor = Executors.newFixedThreadPool​(10);
    }

    @GET
    public Response getFoo() {

        String result = doSomeProcessing();

        // Submits a Runnable task for execution
        executor.submit(new LongRunningTask());

        return Response.ok(result).build();
    }

    @PreDestroy
    public void onDestroy() {

        // Initiates an orderly shutdown in which previously submitted 
        // tasks are executed, but no new tasks will be accepted.
        this.executor.shutdownNow();
    }
}
public class LongRunningTask implements Runnable {

    @Override
    public void run() {

        try {
            // Simulate a long running task
            // Don't do it in a real application
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

探索Executors API,详细了解如何创建ExecutorService 实例。


在 Java SE 和 Servlet 容器中,您可以使用 ExecutorService 来执行长时间运行的任务。在 Java EE 容器中,您应该改用 ManagedExecutorService

@Resource
ManagedExecutorService executor;

一旦它是由容器管理的资源,您就不需要手动实例化和处置它。

【讨论】:

    【解决方案2】:

    我不确定“调用第二个 REST API”到底是什么意思,所以我假设您正在向另一个外部 API 发送 HTTP 请求,即“第二个 REST API”。

    您可以使用Apache HC 发送请求并跳过等待响应。请参阅其易于使用的fluent APIAsync.execute 是应该在您的情况下使用的那个。 Async 类使用底层的线程池来处理后台请求。

    我应该提到我没有使用任何其他 HTTP 客户端库。可能还有其他选择具有几乎相同的功能。

    旁注我强烈建议ExecutorService,尤其是。 ThreadPoolExecutor 而不是创建新线程。它可以更好地控制线程的生命周期并有效地管理系统资源。 ExecutorService 有处理火灾和忘记场景的方法 (submit)。但是,只有当您的“第二个 REST API”调用实际上是在您的应用程序的另一个方法中实现并且位于同一个 JRE 中时,这才有意义。

    【讨论】:

      【解决方案3】:

      我会说是也不是;异步调用另一个服务并没有什么“错误”(例如:一个度量子系统来注册对该服务的调用)。但是,我不会直接在 getData 方法中创建线程,我会使用另一个(注入的)对象来隐藏实现细节(例如:只是调用某种 myOtherService.submit(something)。这样你就可以轻松地从同步的东西切换, 异步,甚至根据自己的喜好更改异步方法。

      至于实际的实现,我不会创建线程,而是将可调用对象提交给执行程序服务,这样您就可以节省创建实际系统线程的开销,或者您甚至可以让一个或多个线程在阻塞队列上等待,而只是将作业放入该队列中以供线程拾取。

      【讨论】:

        猜你喜欢
        • 2016-12-18
        • 2018-12-17
        • 2017-11-12
        • 1970-01-01
        • 2018-08-04
        • 1970-01-01
        • 2015-04-25
        • 1970-01-01
        相关资源
        最近更新 更多