Siga @AsyncHttpClient no Twitter.
A biblioteca AsyncHttpClient (AHC) permite que aplicativos Java executem facilmente solicitações HTTP e processem respostas HTTP de forma assíncrona. A biblioteca também oferece suporte ao protocolo WebSocket.
É construído em cima do Netty. É compilado com Java 11.
Os binários são implantados no Maven Central. Adicione uma dependência no artefato principal AsyncHttpClient:
Maven:
< dependencies >
< dependency >
< groupId >org.asynchttpclient</ groupId >
< artifactId >async-http-client</ artifactId >
< version >3.0.1</ version >
</ dependency >
</ dependencies >
Gradil:
dependencies {
implementation ' org.asynchttpclient:async-http-client:3.0.1 '
}
Importe os auxiliares Dsl para usar métodos convenientes para inicializar componentes:
import static org . asynchttpclient . Dsl .*;
import static org . asynchttpclient . Dsl .*;
AsyncHttpClient asyncHttpClient = asyncHttpClient ();
As instâncias de AsyncHttpClient devem ser fechadas (chame o método close
) quando você terminar de usá-las, normalmente ao encerrar seu aplicativo. Caso contrário, você enfrentará threads suspensos e vazamentos de recursos.
As instâncias AsyncHttpClient destinam-se a ser recursos globais que compartilham o mesmo ciclo de vida do aplicativo. Normalmente, o AHC terá um desempenho inferior se você criar um novo cliente para cada solicitação, pois criará novos threads e pools de conexões para cada um. É possível criar recursos compartilhados (EventLoop e Timer) antecipadamente e passá-los para várias instâncias de clientes na configuração. Você será então responsável por fechar esses recursos compartilhados.
Finalmente, você também pode configurar a instância AsyncHttpClient por meio de seu objeto AsyncHttpClientConfig:
import static org . asynchttpclient . Dsl .*;
AsyncHttpClient c = asyncHttpClient ( config (). setProxyServer ( proxyServer ( "127.0.0.1" , 38080 )));
AHC fornece 2 APIs para definir solicitações: vinculadas e não vinculadas. AsyncHttpClient
e Dsl` fornecem métodos para métodos HTTP padrão (POST, PUT, etc), mas você também pode passar um 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 );
Use o método setBody
para adicionar um corpo à solicitação.
Este corpo pode ser do 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
é uma abstração genérica que permite criar corpos de solicitação dinamicamente. Dê uma olhada no FeedableBodyGenerator
se estiver procurando uma maneira de passar blocos de solicitações rapidamente.
Use o método addBodyPart
para adicionar uma parte multipart à solicitação.
Esta parte pode ser do tipo:
ByteArrayPart
FilePart
InputStreamPart
StringPart
Os métodos execute
retornam um java.util.concurrent.Future
. Você pode simplesmente bloquear o thread de chamada para obter a resposta.
Future < Response > whenResponse = asyncHttpClient . prepareGet ( "http://www.example.com/" ). execute ();
Response response = whenResponse . get ();
Isso é útil para depuração, mas você provavelmente prejudicará o desempenho ou criará bugs ao executar esse código em produção. O objetivo de usar um cliente sem bloqueio é NÃO BLOQUEAR o thread de chamada!
Os métodos execute
, na verdade, retornam um org.asynchttpclient.ListenableFuture
semelhante ao do Guava. Você pode configurar os ouvintes para serem notificados sobre a conclusão do 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 );
Se o parâmetro executor
for nulo, o retorno de chamada será executado no thread IO. Você NUNCA DEVE REALIZAR operações de BLOQUEIO lá, normalmente enviando outra solicitação e bloqueando em um futuro.
Os métodos execute
podem levar um org.asynchttpclient.AsyncHandler
para ser notificado sobre os diferentes eventos, como o recebimento do status, os cabeçalhos e partes do corpo. Quando você não especifica um, o AHC usará um org.asynchttpclient.AsyncCompletionHandler
;
Os métodos AsyncHandler
podem permitir que você aborte o processamento antecipadamente (retorne AsyncHandler.State.ABORT
) e retorne um resultado de cálculo de onCompleted
que será usado como o resultado do Future. Consulte a implementação AsyncCompletionHandler
como exemplo.
O exemplo abaixo apenas captura o status da resposta e ignora o processamento dos pedaços do corpo da resposta.
Observe que retornar ABORT
fecha a conexão subjacente.
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
possui um método toCompletableFuture
que retorna um CompletableFuture
. Esteja ciente de que cancelar este CompletableFuture
não cancelará adequadamente a solicitação em andamento. Há uma boa chance de retornarmos um CompletionStage
na próxima versão.
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
Você pode obter o projeto maven completo para esta demonstração simples em org.asynchttpclient.example
O cliente HTTP assíncrono também oferece suporte a WebSocket. Você precisa passar um WebSocketUpgradeHandler
onde registraria um 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 ();
Mantenha-se atualizado sobre o desenvolvimento da biblioteca participando do grupo de discussão Cliente HTTP Assíncrono
Discussões do GitHub