94 votes

Comment voulez-vous créer une requête HTTP asynchrone en JAVA?

Je suis assez nouveau à Java, ce qui peut paraître évident pour certains. J'ai beaucoup travaillé avec ActionScript, ce qui est beaucoup basée sur les événements et j'adore ça. Récemment, j'ai essayé d'écrire un petit peu de code Java qui fait une requête POST, mais j'ai été confronté avec le problème qu'il est synchrone demande, de sorte que l'exécution de code attend de la demande est complète, le temps, ou présente une erreur.

Comment puis-je créer une requête asynchrone, où le code continue l'exécution et une fonction de callback est appelé lorsque la requête HTTP est terminée? J'ai jeté un coup d'oeil au fils, mais je pense que c'est exagéré.

47voto

BalusC Points 498232

Java est en effet plus bas niveau que ActionScript. C'est comme comparer des pommes avec des oranges. Tout en ActionScript gère tout cela de manière transparente "sous le capot", en Java, vous devez gérer le traitement asynchrone (threading) de vous-même.

Heureusement, en Java il y a l' java.util.concurrent API qui peut faire de bien belle manière.

Votre problème peut être résolu comme suit:

// 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> 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();

Request et Response se présenter comme suit:

public class Request implements Callable<Response> {
    private URL url;

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

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

et

public class Response {
    private InputStream body;

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

    public InputStream getBody() {
        return body;
    }
}

Voir aussi:

26voto

kschneid Points 3823

Vous pouvez également regarder Asynchrone Client Http.

15voto

ericsoco Points 1948

Basé sur un lien pour Apache HTTP Composants sur ce fil, je suis tombé sur la fluidité de la façade de l'API HTTP de Composants. Un exemple montre comment configurer une file d'attente de l'asynchrone des requêtes HTTP (et être averti de leur achèvement/échec/annulation). Dans mon cas, je n'ai pas besoin d'une file d'attente, une seule demande asynchrone à un moment.

Voici où j'ai fini (également à l'aide de URIBuilder de HTTP Composants, exemple ici).

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<Content> future = async.execute(request, new FutureCallback<Content>() {
    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 () {}
});

6voto

Paul Rubel Points 13132

Vous pouvez prendre un coup d'oeil à cette question: http://stackoverflow.com/questions/592303/asynchronous-io-in-java

Il ressemble à votre meilleur pari, si vous ne voulez pas de se disputer le fils vous-même est un cadre. Le post précédent mentionne Grizzly, https://grizzly.dev.java.net/, et Netty, http://www.jboss.org/netty/.

À partir de la netty docs:

Le Netty projet est un effort pour offrir un événement asynchrone piloté par le réseau de l'application du cadre et des outils pour le développement rapide de facile à maintenir de hautes performances et une évolutivité élevée protocole des serveurs et des clients.

2voto

danbrough Points 866

Apache HttpComponents ont également un async client http désormais trop:

/**
    <dependency>
      <groupId>org.apache.httpcomponents</groupId>
      <artifactId>httpasyncclient</artifactId>
      <version>4.0-beta4</version>
    </dependency>
**/

import java.io.IOException;
import java.nio.CharBuffer;
import java.util.concurrent.Future;

import org.apache.http.HttpResponse;
import org.apache.http.impl.nio.client.CloseableHttpAsyncClient;
import org.apache.http.impl.nio.client.HttpAsyncClients;
import org.apache.http.nio.IOControl;
import org.apache.http.nio.client.methods.AsyncCharConsumer;
import org.apache.http.nio.client.methods.HttpAsyncMethods;
import org.apache.http.protocol.HttpContext;

public class HttpTest {

  public static void main(final String[] args) throws Exception {

    final CloseableHttpAsyncClient httpclient = HttpAsyncClients
        .createDefault();
    httpclient.start();
    try {
      final Future<Boolean> future = httpclient.execute(
          HttpAsyncMethods.createGet("http://www.google.com/"),
          new MyResponseConsumer(), null);
      final Boolean result = future.get();
      if (result != null && result.booleanValue()) {
        System.out.println("Request successfully executed");
      } else {
        System.out.println("Request failed");
      }
      System.out.println("Shutting down");
    } finally {
      httpclient.close();
    }
    System.out.println("Done");
  }

  static class MyResponseConsumer extends AsyncCharConsumer<Boolean> {

    @Override
    protected void onResponseReceived(final HttpResponse response) {
    }

    @Override
    protected void onCharReceived(final CharBuffer buf, final IOControl ioctrl)
        throws IOException {
      while (buf.hasRemaining()) {
        System.out.print(buf.get());
      }
    }

    @Override
    protected void releaseResources() {
    }

    @Override
    protected Boolean buildResult(final HttpContext context) {
      return Boolean.TRUE;
    }
  }
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X