Java的異步HttpClient


上篇提到了高性能處理的關鍵是異步,而我們當中許多人依舊在使用同步模式的HttpClient訪問第三方Web資源,我認為原因之一是:異步的HttpClient誕生較晚,許多人不知道;另外也可能是大多數Web程序其實不在意這點性能損失了。

而要自己實現一個異步的HttpClient則比較困難,通常都是自己開一個新的工作線程,利用HttpClient的同步去訪問,完成后再回調這種形式,這樣做其實不是真正的異步,因為依舊會有一個線程處於阻塞中,等待着第三方Web資源的返回。

而如今訪問第三方Web資源的情景越來越多,最典型就是使用第三方登錄平台,如QQ或微信等,我們需要訪問騰訊的服務器去驗證登錄者的身份,根據我的經驗,這個過程可能會阻塞好幾秒鍾,可看作是一個“長時間調用”,所以最好要使用異步方式。

OK,廢話少說,要使用異步的HttpClient,請Maven中帶上:

        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpasyncclient</artifactId>
            <version>4.1.1</version>
        </dependency>

接下來是一個完整的Demo代碼:

import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.concurrent.FutureCallback;
import org.apache.http.impl.nio.client.CloseableHttpAsyncClient;
import org.apache.http.impl.nio.client.HttpAsyncClients;
import org.apache.http.util.EntityUtils;

import java.io.IOException;
import java.util.concurrent.CountDownLatch;

public class Main {
    public static void main(String[] argv) {
        CloseableHttpAsyncClient httpclient = HttpAsyncClients.createDefault();
        httpclient.start();

        final CountDownLatch latch = new CountDownLatch(1);
        final HttpGet request = new HttpGet("https://www.alipay.com/");

        System.out.println(" caller thread id is : " + Thread.currentThread().getId());

        httpclient.execute(request, new FutureCallback<HttpResponse>() {

            public void completed(final HttpResponse response) {
                latch.countDown();
                System.out.println(" callback thread id is : " + Thread.currentThread().getId());
                System.out.println(request.getRequestLine() + "->" + response.getStatusLine());
                try {
                    String content = EntityUtils.toString(response.getEntity(), "UTF-8");
                    System.out.println(" response content is : " + content);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

            public void failed(final Exception ex) {
                latch.countDown();
                System.out.println(request.getRequestLine() + "->" + ex);
                System.out.println(" callback thread id is : " + Thread.currentThread().getId());
            }

            public void cancelled() {
                latch.countDown();
                System.out.println(request.getRequestLine() + " cancelled");
                System.out.println(" callback thread id is : " + Thread.currentThread().getId());
            }

        });
        try {
            latch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        try {
            httpclient.close();
        } catch (IOException ignore) {

        }
    }
}

 呃……代碼很簡單,好像也沒什么好說的了,稍作封裝就可以實現如“getJson()”這樣的方法。

也許你還注意到了,這個HttpClient跟同步的版本一樣,直接支持https,但如果網站的證書是自簽的,默認還是不行的,解決方法當然有,但代碼有些麻煩,我覺得還不如直接買張證書來得簡單,如果網站是你管的話。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM