Следите за @AsyncHttpClient в Твиттере.
Библиотека AsyncHttpClient (AHC) позволяет приложениям Java легко выполнять HTTP-запросы и асинхронно обрабатывать HTTP-ответы. Библиотека также поддерживает протокол WebSocket.
Он построен на основе Netty. Он скомпилирован с помощью Java 11.
Двоичные файлы развертываются на Maven Central. Добавьте зависимость от основного артефакта AsyncHttpClient:
Мавен:
< dependencies >
< dependency >
< groupId >org.asynchttpclient</ groupId >
< artifactId >async-http-client</ artifactId >
< version >3.0.1</ version >
</ dependency >
</ dependencies >
Градл:
dependencies {
implementation ' org.asynchttpclient:async-http-client:3.0.1 '
}
Импортируйте помощники Dsl, чтобы использовать удобные методы загрузки компонентов:
import static org . asynchttpclient . Dsl .*;
import static org . asynchttpclient . Dsl .*;
AsyncHttpClient asyncHttpClient = asyncHttpClient ();
Экземпляры AsyncHttpClient необходимо закрыть (вызвать метод close
), как только вы закончите с ними, обычно при закрытии приложения. Если вы этого не сделаете, вы столкнетесь с зависанием потоков и утечкой ресурсов.
Экземпляры AsyncHttpClient представляют собой глобальные ресурсы, имеющие тот же жизненный цикл, что и приложение. Как правило, AHC обычно работает хуже, если вы создаете новый клиент для каждого запроса, поскольку для каждого из них будут создаваться новые потоки и пулы соединений. Можно заранее создать общие ресурсы (EventLoop и Timer) и передать их нескольким экземплярам клиента в конфигурации. Затем вы будете нести ответственность за закрытие этих общих ресурсов.
Наконец, вы также можете настроить экземпляр AsyncHttpClient через его объект AsyncHttpClientConfig:
import static org . asynchttpclient . Dsl .*;
AsyncHttpClient c = asyncHttpClient ( config (). setProxyServer ( proxyServer ( "127.0.0.1" , 38080 )));
AHC предоставляет два API для определения запросов: привязанный и несвязанный. AsyncHttpClient
и Dsl` предоставляют методы для стандартных методов HTTP (POST, PUT и т. д.), но вы также можете передать свои собственные.
import org . asynchttpclient .*;
// bound
Future < Response > whenResponse = asyncHttpClient . prepareGet ( "http://www.example.com/" ). execute ();
// unbound
Request request = get ( "http://www.example.com/" ). build ();
Future < Response > whenResponse = asyncHttpClient . executeRequest ( request );
Используйте метод setBody
, чтобы добавить тело запроса.
Это тело может быть типа:
java.io.File
byte[]
List<byte[]>
String
java.nio.ByteBuffer
java.io.InputStream
Publisher<io.netty.buffer.ByteBuf>
org.asynchttpclient.request.body.generator.BodyGenerator
BodyGenerator
— это общая абстракция, позволяющая создавать тела запросов «на лету». Если вы ищете способ передачи фрагментов запросов на лету, обратите внимание на FeedableBodyGenerator
.
Используйте метод addBodyPart
, чтобы добавить к запросу составную часть.
Эта часть может иметь тип:
ByteArrayPart
FilePart
InputStreamPart
StringPart
методы execute
возвращают java.util.concurrent.Future
. Вы можете просто заблокировать вызывающий поток, чтобы получить ответ.
Future < Response > whenResponse = asyncHttpClient . prepareGet ( "http://www.example.com/" ). execute ();
Response response = whenResponse . get ();
Это полезно для отладки, но вы, скорее всего, ухудшите производительность или создадите ошибки при запуске такого кода в рабочей среде. Смысл использования неблокирующего клиента заключается в том, чтобы НЕ БЛОКИРОВАТЬ вызывающий поток!
Методы execute
фактически возвращают org.asynchttpclient.ListenableFuture
аналогичный Guava. Вы можете настроить прослушиватели для получения уведомлений о завершении Future.
ListenableFuture < Response > whenResponse = ???;
Runnable callback = () - > {
try {
Response response = whenResponse . get ();
System . out . println ( response );
} catch ( InterruptedException | ExecutionException e ) {
e . printStackTrace ();
}
};
java . util . concurrent . Executor executor = ???;
whenResponse . addListener (() - > ??? , executor );
Если параметр executor
имеет значение null, обратный вызов будет выполнен в потоке ввода-вывода. Вы НИКОГДА НЕ ДОЛЖНЫ ВЫПОЛНИТЬ там операции БЛОКИРОВКИ , обычно отправляя еще один запрос и блокируясь в будущем.
Методы execute
могут принимать org.asynchttpclient.AsyncHandler
для получения уведомлений о различных событиях, таких как получение статуса, заголовков и фрагментов тела. Если вы его не укажете, AHC будет использовать org.asynchttpclient.AsyncCompletionHandler
;
Методы AsyncHandler
позволяют досрочно прервать обработку (вернуть AsyncHandler.State.ABORT
) и вернуть результат вычисления из onCompleted
, который будет использоваться в качестве результата Future. В качестве примера см. реализацию AsyncCompletionHandler
.
В приведенном ниже примере просто фиксируется статус ответа и пропускается обработка фрагментов тела ответа.
Обратите внимание, что возврат ABORT
закрывает базовое соединение.
import static org . asynchttpclient . Dsl .*;
import org . asynchttpclient .*;
import io . netty . handler . codec . http . HttpHeaders ;
Future < Integer > whenStatusCode = asyncHttpClient . prepareGet ( "http://www.example.com/" )
. execute ( new AsyncHandler < Integer > () {
private Integer status ;
@ Override
public State onStatusReceived ( HttpResponseStatus responseStatus ) throws Exception {
status = responseStatus . getStatusCode ();
return State . ABORT ;
}
@ Override
public State onHeadersReceived ( HttpHeaders headers ) throws Exception {
return State . ABORT ;
}
@ Override
public State onBodyPartReceived ( HttpResponseBodyPart bodyPart ) throws Exception {
return State . ABORT ;
}
@ Override
public Integer onCompleted () throws Exception {
return status ;
}
@ Override
public void onThrowable ( Throwable t ) {
t . printStackTrace ();
}
});
Integer statusCode = whenStatusCode . get ();
ListenableFuture
имеет метод toCompletableFuture
, который возвращает CompletableFuture
. Помните, что отмена CompletableFuture
не приведет к корректной отмене текущего запроса. Есть очень большая вероятность, что мы вернем CompletionStage
вместо этого в следующем выпуске.
CompletableFuture < Response > whenResponse = asyncHttpClient
. prepareGet ( "http://www.example.com/" )
. execute ()
. toCompletableFuture ()
. exceptionally ( t ->{ /* Something wrong happened... */ })
. thenApply ( response ->{ /* Do something with the Response */ return resp ;});
whenResponse . join (); // wait for completion
Вы можете получить полный проект maven для этой простой демонстрации на сайте org.asynchttpclient.example.
Async Http Client также поддерживает WebSocket. Вам нужно передать WebSocketUpgradeHandler
, в котором вы бы зарегистрировали WebSocketListener
.
WebSocket websocket = c . prepareGet ( "ws://demos.kaazing.com/echo" )
. execute ( new WebSocketUpgradeHandler . Builder (). addWebSocketListener (
new WebSocketListener () {
@ Override
public void onOpen ( WebSocket websocket ) {
websocket . sendTextFrame ( "..." ). sendTextFrame ( "..." );
}
@ Override
public void onClose ( WebSocket websocket ) {
// ...
}
@ Override
public void onTextFrame ( String payload , boolean finalFragment , int rsv ) {
System . out . println ( payload );
}
@ Override
public void onError ( Throwable t ) {
t . printStackTrace ();
}
}). build ()). get ();
Будьте в курсе разработки библиотеки, присоединившись к группе обсуждения асинхронного HTTP-клиента.
Обсуждения на GitHub