当前位置:  开发笔记 > 编程语言 > 正文

如何在JAVA中创建异步HTTP请求?

如何解决《如何在JAVA中创建异步HTTP请求?》经验,为你挑选了5个好方法。

我对Java很新,所以对某些人来说这似乎是显而易见的.我在ActionScript上做了很多工作,这是基于事件的,我很喜欢.我最近尝试编写了一小部分执行POST请求的Java代码,但我遇到了一个问题,即它是一个同步请求,因此代码执行会等待请求完成,超时或出现错误.

如何创建异步请求,代码继续执行,并在HTTP请求完成时调用回调?我瞥了一眼线程,但我认为这太过分了.



1> BalusC..:

Java确实比ActionScript更低级别.这就像比较苹果和橘子.虽然ActionScript在"引擎盖下"透明地处理它,但在Java中,您需要自己管理异步处理(线程).

幸运的是,在Java中,有一种java.util.concurrentAPI可以很好地完成这项工作.

你的问题基本上可以解决如下:

// Have one (or more) threads ready to do the async tasks. Do this during startup of your app.
ExecutorService executor = Executors.newFixedThreadPool(1); 

// Fire a request.
Future response = executor.submit(new Request(new URL("http://google.com")));

// Do your other tasks here (will be processed immediately, current thread won't block).
// ...

// Get the response (here the current thread will block until response is returned).
InputStream body = response.get().getBody();
// ...

// Shutdown the threads during shutdown of your app.
executor.shutdown();

其中RequestResponse如下所示:

public class Request implements Callable {
    private URL url;

    public Request(URL url) {
        this.url = url;
    }

    @Override
    public Response call() throws Exception {
        return new Response(url.openStream());
    }
}

public class Response {
    private InputStream body;

    public Response(InputStream body) {
        this.body = body;
    }

    public InputStream getBody() {
        return body;
    }
}

也可以看看:

课程:并发 - 一个java.util.concurrent教程.


请注意,这个答案实际上并不是异步IO - 这就是ActionScript的作用.这个答案只是使用不同的线程来运行HTTP请求.如果您做任何认真的工作,这种方法会产生明显的性能影响.
当有人想要"异步请求"时,了解线程模型很重要.此示例创建一个线程池,并在工作线程上同步处理每个请求.这可能不是所期望的效果,因为在请求/响应过程中保持线程很重.
ActionScript或Node根本不是多线程的,但是它们提供了异步IO。该答案使用线程和阻塞操作,因此尽管有更好的方法,但所有愚蠢的IO工作仍需要在您的过程中完成。环顾四周,下面有更好的答案。

2> Psyx..:

如果您处于JEE7环境中,那么您必须有一个不错的JAXRS实现,这将允许您使用其客户端API轻松地发出异步HTTP请求.

这看起来像这样:

public class Main {

    public static Future getAsyncHttp(final String url) {
        return ClientBuilder.newClient().target(url).request().async().get();
    }

    public static void main(String ...args) throws InterruptedException, ExecutionException {
        Future response = getAsyncHttp("http://www.nofrag.com");
        while (!response.isDone()) {
            System.out.println("Still waiting...");
            Thread.sleep(10);
        }
        System.out.println(response.get().readEntity(String.class));
    }
}

当然,这只是使用期货.如果你可以使用更多的库,你可以看看RxJava,代码看起来像:

public static void main(String... args) {
    final String url = "http://www.nofrag.com";
    rx.Observable.from(ClientBuilder.newClient().target(url).request().async().get(String.class), Schedulers
            .newThread())
            .subscribe(
                    next -> System.out.println(next),
                    error -> System.err.println(error),
                    () -> System.out.println("Stream ended.")
            );
    System.out.println("Async proof");
}

最后但并非最不重要的是,如果你想重用你的异步调用,你可能想看看Hystrix,除了一个非常酷的其他东西之外,它还允许你写这样的东西:

例如:

public class AsyncGetCommand extends HystrixCommand {

    private final String url;

    public AsyncGetCommand(final String url) {
        super(Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("HTTP"))
                .andCommandPropertiesDefaults(HystrixCommandProperties.Setter()
                        .withExecutionIsolationThreadTimeoutInMilliseconds(5000)));
        this.url = url;
    }

    @Override
    protected String run() throws Exception {
        return ClientBuilder.newClient().target(url).request().get(String.class);
    }

 }

调用此命令将如下所示:

public static void main(String ...args) {
    new AsyncGetCommand("http://www.nofrag.com").observe().subscribe(
            next -> System.out.println(next),
            error -> System.err.println(error),
            () -> System.out.println("Stream ended.")
    );
    System.out.println("Async proof");
}

PS:我知道线程已经过时了,但是在没有提到Rx/Hystrix方式的情况下,没有人提到这个问题.



3> kschneid..:

您可能还想查看Async Http Client.



4> ericsoco..:

基于此SO线程上的Apache HTTP组件链接,我遇到了HTTP组件的Fluent外观API. 这里的一个例子展示了如何设置异步HTTP请求的队列(并获得完成/失败/取消的通知).就我而言,我不需要一个队列,一次只需要一个异步请求.

这是我结束的地方(也使用HTTP Components中的URIBuilder,例如这里).

import java.net.URI;
import java.net.URISyntaxException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import org.apache.http.client.fluent.Async;
import org.apache.http.client.fluent.Content;
import org.apache.http.client.fluent.Request;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.concurrent.FutureCallback;

//...

URIBuilder builder = new URIBuilder();
builder.setScheme("http").setHost("myhost.com").setPath("/folder")
    .setParameter("query0", "val0")
    .setParameter("query1", "val1")
    ...;
URI requestURL = null;
try {
    requestURL = builder.build();
} catch (URISyntaxException use) {}

ExecutorService threadpool = Executors.newFixedThreadPool(2);
Async async = Async.newInstance().use(threadpool);
final Request request = Request.Get(requestURL);

Future future = async.execute(request, new FutureCallback() {
    public void failed (final Exception e) {
        System.out.println(e.getMessage() +": "+ request);
    }
    public void completed (final Content content) {
        System.out.println("Request completed: "+ request);
        System.out.println("Response:\n"+ content.asString());
    }

    public void cancelled () {}
});



5> Paul Rubel..:

您可能想看一下这个问题:Java中的异步IO?

看起来你最好的选择,如果你不想自己争论线程是一个框架.上一篇文章提到了Grizzly,https://grizzly.dev.java.net/和Netty,http: //www.jboss.org/netty/ .

来自netty文档:

Netty项目旨在提供异步事件驱动的网络应用程序框架和工具,以便快速开发可维护的高性能和高可伸缩性协议服务器和客户端.

推荐阅读
大大炮
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有