Ich bin ziemlich neu in Java, daher scheint dies einigen offensichtlich zu sein. Ich habe viel mit ActionScript gearbeitet, das sehr ereignisbasiert ist, und das finde ich toll. Ich habe kürzlich versucht, ein kleines Stück Java-Code zu schreiben, der eine POST-Anforderung ausführt, aber ich hatte das Problem, dass es sich um eine synchrone Anforderung handelt. Daher wartet die Codeausführung darauf, dass die Anforderung abgeschlossen wird, eine Zeitüberschreitung auftritt oder ein Fehler auftritt.
Wie kann ich eine asynchrone Anforderung erstellen, bei der der Code die Ausführung fortsetzt und ein Rückruf aufgerufen wird, wenn die HTTP-Anforderung abgeschlossen ist? Ich habe einen Blick auf Fäden geworfen, aber ich denke, es ist übertrieben.
quelle
Antworten:
Beachten Sie, dass java11 jetzt einen neuen HTTP-API- HttpClient bietet , der den vollständig asynchronen Betrieb unter Verwendung von CompletableFuture von Java unterstützt .
Es unterstützt auch eine synchrone Version mit Aufrufen wie send (synchron) und sendAsync (asynchron).
Beispiel einer asynchronen Anfrage (aus dem Apidoc):
HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("https://example.com/")) .timeout(Duration.ofMinutes(2)) .header("Content-Type", "application/json") .POST(BodyPublishers.ofFile(Paths.get("file.json"))) .build(); client.sendAsync(request, BodyHandlers.ofString()) .thenApply(HttpResponse::body) .thenAccept(System.out::println);
quelle
Wenn Sie sich in einer JEE7-Umgebung befinden, muss eine anständige Implementierung von JAXRS vorhanden sein, mit der Sie mithilfe der Client-API problemlos asynchrone HTTP-Anforderungen stellen können.
Das würde so aussehen:
public class Main { public static Future<Response> getAsyncHttp(final String url) { return ClientBuilder.newClient().target(url).request().async().get(); } public static void main(String ...args) throws InterruptedException, ExecutionException { Future<Response> 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)); } }
Natürlich werden hier nur Futures verwendet. Wenn Sie mit der Verwendung weiterer Bibliotheken einverstanden sind, können Sie sich RxJava ansehen. Der Code sieht dann folgendermaßen aus:
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"); }
Und last but not least, wenn Sie Ihren asynchronen Anruf wiederverwenden möchten, sollten Sie sich Hystrix ansehen, mit dem Sie - zusätzlich zu einer Unmenge super cooler anderer Dinge - Folgendes schreiben können:
Zum Beispiel:
public class AsyncGetCommand extends HystrixCommand<String> { 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); } }
Das Aufrufen dieses Befehls würde folgendermaßen aussehen:
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: Ich weiß, dass der Thread alt ist, aber es fühlte sich falsch an, dass niemand den Rx / Hystrix-Weg in den hochgestimmten Antworten erwähnt.
quelle
Möglicherweise möchten Sie sich auch den Async Http Client ansehen .
quelle
Aufgrund eines Links zu Apache-HTTP-Komponenten in diesem SO-Thread bin ich auf die Fluent-Fassaden-API für HTTP-Komponenten gestoßen. Ein Beispiel dort zeigt, wie Sie eine Warteschlange für asynchrone HTTP-Anforderungen einrichten (und über deren Abschluss / Fehler / Abbruch benachrichtigt werden). In meinem Fall brauchte ich keine Warteschlange, sondern jeweils nur eine asynchrone Anforderung.
Hier bin ich gelandet (auch mit URIBuilder von HTTP Components, Beispiel hier ).
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 () {} });
quelle
Vielleicht möchten Sie sich diese Frage ansehen: Asynchrone E / A in Java?
Es sieht aus wie Ihre beste Wahl, wenn Sie nicht die Threads selbst streiten wollen, ist ein Rahmen. Im vorherigen Beitrag werden Grizzly ( https://grizzly.dev.java.net/ ) und Netty ( http://www.jboss.org/netty/) erwähnt .
Aus den Netty Docs:
Das Netty-Projekt ist ein Versuch, ein asynchrones ereignisgesteuertes Netzwerkanwendungsframework und Tools für die schnelle Entwicklung wartungsfähiger Protokollserver und -clients mit hoher Leistung und hoher Skalierbarkeit bereitzustellen.
quelle
Apache HttpComponents hat jetzt auch einen asynchronen http-Client:
/** <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; } } }
quelle
Es muss klargestellt werden, dass das HTTP-Protokoll synchron ist und dies nichts mit der Programmiersprache zu tun hat. Der Client sendet eine Anfrage und erhält eine synchrone Antwort.
Wenn Sie ein asynchrones Verhalten über HTTP wünschen, muss dieses über HTTP erstellt werden (ich weiß nichts über ActionScript, aber ich nehme an, dass dies auch das ActionScript tut). Es gibt viele Bibliotheken, die Ihnen solche Funktionen bieten könnten (z . B. Jersey SSE ). Beachten Sie, dass sie Abhängigkeiten zwischen dem Client und dem Server irgendwie definieren, da sie sich auf die genaue nicht standardmäßige Kommunikationsmethode über HTTP einigen müssen.
Wenn Sie nicht sowohl den Client als auch den Server steuern können oder keine Abhängigkeiten zwischen ihnen haben möchten, verwendet der häufigste Ansatz zur Implementierung einer asynchronen (z. B. ereignisbasierten) Kommunikation über HTTP den Webhooks-Ansatz (Sie können dies auf eine überprüfen Beispiel Implementierung in Java).
Hoffe ich habe geholfen!
quelle