Siga a @AsyncHttpClient en Twitter.
La biblioteca AsyncHttpClient (AHC) permite que las aplicaciones Java ejecuten fácilmente solicitudes HTTP y procesen respuestas HTTP de forma asincrónica. La biblioteca también admite el protocolo WebSocket.
Está construido sobre Netty. Está compilado con Java 11.
Los binarios se implementan en Maven Central. Agregue una dependencia en el artefacto principal AsyncHttpClient:
experto:
< dependencies >
< dependency >
< groupId >org.asynchttpclient</ groupId >
< artifactId >async-http-client</ artifactId >
< version >3.0.1</ version >
</ dependency >
</ dependencies >
Gradle:
dependencies {
implementation ' org.asynchttpclient:async-http-client:3.0.1 '
}
Importe los asistentes de Dsl para utilizar métodos convenientes para iniciar componentes:
import static org . asynchttpclient . Dsl .*;
import static org . asynchttpclient . Dsl .*;
AsyncHttpClient asyncHttpClient = asyncHttpClient ();
Las instancias de AsyncHttpClient deben cerrarse (llame al método close
) una vez que haya terminado con ellas, generalmente al cerrar su aplicación. Si no lo hace, experimentará hilos colgados y fugas de recursos.
Las instancias de AsyncHttpClient están destinadas a ser recursos globales que comparten el mismo ciclo de vida que la aplicación. Normalmente, AHC tendrá un rendimiento inferior si crea un nuevo cliente para cada solicitud, ya que creará nuevos subprocesos y grupos de conexiones para cada uno. Es posible crear recursos compartidos (EventLoop y Timer) de antemano y pasarlos a múltiples instancias de cliente en la configuración. Luego serás responsable de cerrar esos recursos compartidos.
Finalmente, también puedes configurar la instancia AsyncHttpClient a través de su objeto AsyncHttpClientConfig:
import static org . asynchttpclient . Dsl .*;
AsyncHttpClient c = asyncHttpClient ( config (). setProxyServer ( proxyServer ( "127.0.0.1" , 38080 )));
AHC proporciona 2 API para definir solicitudes: vinculadas y no vinculadas. AsyncHttpClient
y Dsl` proporcionan métodos para métodos HTTP estándar (POST, PUT, etc.), pero también puede pasar uno personalizado.
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 );
Utilice el método setBody
para agregar un cuerpo a la solicitud.
Este cuerpo puede ser de tipo:
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
es una abstracción genérica que le permite crear cuerpos de solicitud sobre la marcha. Eche un vistazo a FeedableBodyGenerator
si está buscando una manera de pasar fragmentos de solicitudes sobre la marcha.
Utilice el método addBodyPart
para agregar una parte de varias partes a la solicitud.
Esta parte puede ser de tipo:
ByteArrayPart
FilePart
InputStreamPart
StringPart
Los métodos execute
devuelven un java.util.concurrent.Future
. Simplemente puede bloquear el hilo de llamada para obtener la respuesta.
Future < Response > whenResponse = asyncHttpClient . prepareGet ( "http://www.example.com/" ). execute ();
Response response = whenResponse . get ();
Esto es útil para depurar, pero lo más probable es que perjudique el rendimiento o cree errores al ejecutar dicho código en producción. ¡El objetivo de utilizar un cliente sin bloqueo es NO BLOQUEAR el hilo de llamada!
Los métodos execute
en realidad devuelven un org.asynchttpclient.ListenableFuture
similar al de Guava. Puede configurar los oyentes para que sean notificados de la finalización del futuro.
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 );
Si el parámetro executor
es nulo, la devolución de llamada se ejecutará en el subproceso IO. NUNCA DEBE REALIZAR operaciones de BLOQUEO allí, normalmente enviando otra solicitud y bloqueando en un futuro.
Los métodos execute
pueden requerir que un org.asynchttpclient.AsyncHandler
sea notificado sobre los diferentes eventos, como la recepción del estado, los encabezados y los fragmentos del cuerpo. Cuando no especifica uno, AHC usará un org.asynchttpclient.AsyncCompletionHandler
;
Los métodos AsyncHandler
pueden permitirle cancelar el procesamiento anticipadamente (devolver AsyncHandler.State.ABORT
) y pueden permitirle devolver un resultado de cálculo de onCompleted
que se utilizará como resultado del futuro. Consulte la implementación AsyncCompletionHandler
como ejemplo.
El siguiente ejemplo simplemente captura el estado de la respuesta y omite el procesamiento de los fragmentos del cuerpo de la respuesta.
Tenga en cuenta que devolver ABORT
cierra la conexión subyacente.
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
tiene un método toCompletableFuture
que devuelve CompletableFuture
. Tenga en cuenta que cancelar este CompletableFuture
no cancelará correctamente la solicitud en curso. Hay muchas posibilidades de que devolvamos un CompletionStage
en la próxima versión.
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
Puede obtener el proyecto maven completo para esta demostración sencilla en org.asynchttpclient.example
Async Http Client también es compatible con WebSocket. Debe pasar un WebSocketUpgradeHandler
donde registraría un 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 ();
Manténgase actualizado sobre el desarrollo de la biblioteca uniéndose al grupo de discusión del Cliente HTTP asíncrono
Discusiones de GitHub