HTTP tak segerak dengan klien async-http di Java

1. Gambaran keseluruhan

AsyncHttpClient (AHC) adalah pustaka yang dibina di atas Netty, dengan tujuan untuk melaksanakan permintaan HTTP dan memproses respons secara tidak segerak dengan mudah.

Dalam artikel ini, kami akan menyajikan cara mengkonfigurasi dan menggunakan klien HTTP, cara melaksanakan permintaan dan memproses respons menggunakan AHC.

2. Persediaan

Versi terbaru perpustakaan boleh didapati di repositori Maven. Kita harus berhati-hati menggunakan kebergantungan dengan id kumpulan org.asynchttpclient dan bukan yang mempunyai com.ning:

 org.asynchttpclient async-http-client 2.2.0 

3. Konfigurasi Pelanggan HTTP

Kaedah yang paling mudah untuk mendapatkan klien HTTP adalah dengan menggunakan kelas Dsl . Kaedah statik asyncHttpClient () mengembalikan objek AsyncHttpClient :

AsyncHttpClient client = Dsl.asyncHttpClient();

Sekiranya kita memerlukan konfigurasi khusus klien HTTP, kita dapat membina objek AsyncHttpClient menggunakan pembangun DefaultAsyncHttpClientConfig.Builder :

DefaultAsyncHttpClientConfig.Builder clientBuilder = Dsl.config()

Ini menawarkan kemungkinan untuk mengkonfigurasi waktu tunggu, pelayan proksi, sijil HTTP dan banyak lagi:

DefaultAsyncHttpClientConfig.Builder clientBuilder = Dsl.config() .setConnectTimeout(500) .setProxyServer(new ProxyServer(...)); AsyncHttpClient client = Dsl.asyncHttpClient(clientBuilder);

Setelah kami mengkonfigurasi dan memperoleh contoh klien HTTP, kami dapat menggunakannya kembali di seluruh aplikasi . Kami tidak perlu membuat instance untuk setiap permintaan kerana secara dalaman ia membuat utas baru dan kumpulan sambungan, yang akan menyebabkan masalah prestasi.

Juga, perlu diperhatikan bahawa setelah kita selesai menggunakan klien, kita harus memanggil kaedah untuk menutup () untuk mengelakkan kebocoran memori atau sumber gantung.

4. Membuat Permintaan HTTP

Terdapat dua kaedah di mana kita dapat menentukan permintaan HTTP menggunakan AHC:

  • terikat
  • tidak terikat

Tidak ada perbezaan besar antara kedua jenis permintaan dari segi prestasi. Mereka hanya mewakili dua API berasingan yang dapat kita gunakan untuk menentukan permintaan. Permintaan terikat terikat dengan klien HTTP yang dibuatnya dan, secara lalai, akan menggunakan konfigurasi klien tertentu jika tidak dinyatakan sebaliknya.

Sebagai contoh, ketika membuat permintaan terikat bendera disableUrlEncoding dibaca dari konfigurasi klien HTTP, sementara untuk permintaan yang tidak terikat ini, secara default ditetapkan ke false. Ini berguna kerana konfigurasi klien dapat diubah tanpa mengkompilasi ulang keseluruhan aplikasi dengan menggunakan sifat sistem yang dilewatkan sebagai argumen VM:

java -jar -Dorg.asynchttpclient.disableUrlEncodingForBoundRequests=true

Senarai lengkap sifat boleh didapati di fail ahc-default.properties .

4.1. Permintaan Terikat

Untuk membuat permintaan terikat kami menggunakan kaedah pembantu dari kelas AsyncHttpClient yang bermula dengan awalan “persiapan” . Juga, kita dapat menggunakan kaedah preprequest () yang menerima objek Request yang sudah dibuat .

Contohnya, kaedah siapGet () akan membuat permintaan HTTP GET:

BoundRequestBuilder getRequest = client.prepareGet("//www.baeldung.com");

4.2. Permintaan Tidak Terikat

Permintaan tidak terikat dapat dibuat menggunakan kelas RequestBuilder :

Request getRequest = new RequestBuilder(HttpConstants.Methods.GET) .setUrl("//www.baeldung.com") .build();

atau dengan menggunakan kelas pembantu Dsl , yang sebenarnya menggunakan RequestBuilder untuk mengkonfigurasi kaedah HTTP dan URL permintaan:

Request getRequest = Dsl.get("//www.baeldung.com").build()

5. Melaksanakan Permintaan HTTP

Nama perpustakaan memberi kita petunjuk tentang bagaimana permintaan dapat dilaksanakan. AHC mempunyai sokongan untuk permintaan segerak dan tidak segerak.

Melaksanakan permintaan bergantung pada jenisnya. Semasa menggunakan permintaan terikat kami menggunakan kaedah eksekusi () dari kelas BoundRequestBuilder dan apabila kami mempunyai permintaan tidak terikat, kami akan melaksanakannya menggunakan salah satu pelaksanaan metode executeRequest () dari antara muka AsyncHttpClient .

5.1. Secara serentak

Perpustakaan ini dirancang agar tidak segerak, tetapi bila diperlukan kita dapat mensimulasikan panggilan segerak dengan menyekat objek Future . Kedua-dua kaedah execute () dan executeRequest () mengembalikan objek ListenableFuture . Kelas ini memperluaskan antara muka Java Future , sehingga mewarisi kaedah get () , yang dapat digunakan untuk menyekat utas semasa sehingga permintaan HTTP selesai dan mengembalikan respons:

Future responseFuture = boundGetRequest.execute(); responseFuture.get();
Future responseFuture = client.executeRequest(unboundRequest); responseFuture.get();

Menggunakan panggilan segerak berguna ketika cuba menyahpepijat bahagian kod kami, tetapi tidak disyorkan untuk digunakan dalam persekitaran pengeluaran di mana pelaksanaan asinkron menyebabkan prestasi dan hasil yang lebih baik.

5.2. Tidak segerak

When we talk about asynchronous executions, we also talk about listeners for processing the results. The AHC library provides 3 types of listeners that can be used for asynchronous HTTP calls:

  • AsyncHandler
  • AsyncCompletionHandler
  • ListenableFuture listeners

The AsyncHandler listener offers the possibility to control and process the HTTP call before it has completed. Using it can handle a series of events related to the HTTP call:

request.execute(new AsyncHandler() { @Override public State onStatusReceived(HttpResponseStatus responseStatus) throws Exception { return null; } @Override public State onHeadersReceived(HttpHeaders headers) throws Exception { return null; } @Override public State onBodyPartReceived(HttpResponseBodyPart bodyPart) throws Exception { return null; } @Override public void onThrowable(Throwable t) { } @Override public Object onCompleted() throws Exception { return null; } });

The State enum lets us control the processing of the HTTP request. By returning State.ABORT we can stop the processing at a specific moment and by using State.CONTINUE we let the processing finish.

It's important to mention that the AsyncHandler isn't thread-safe and shouldn't be reused when executing concurrent requests.

AsyncCompletionHandler inherits all the methods from the AsyncHandler interface and adds the onCompleted(Response) helper method for handling the call completion. All the other listener methods are overridden to return State.CONTINUE, thus making the code more readable:

request.execute(new AsyncCompletionHandler() { @Override public Object onCompleted(Response response) throws Exception { return response; } });

The ListenableFuture interface lets us add listeners that will run when the HTTP call is completed.

Also, it let's execute the code from the listeners – by using another thread pool:

ListenableFuture listenableFuture = client .executeRequest(unboundRequest); listenableFuture.addListener(() -> { Response response = listenableFuture.get(); LOG.debug(response.getStatusCode()); }, Executors.newCachedThreadPool());

Selain itu, pilihan untuk menambahkan pendengar, antara muka ListenableFuture memungkinkan kita mengubah respons Masa Depan menjadi CompletableFuture .

7. Kesimpulannya

AHC adalah perpustakaan yang sangat hebat, dengan banyak ciri menarik. Ia menawarkan cara yang sangat mudah untuk mengkonfigurasi klien HTTP dan kemampuan melaksanakan permintaan segerak dan tidak segerak.

Seperti biasa, kod sumber untuk artikel tersebut terdapat di GitHub.