利用HttpClient4訪問網頁


一、HttpClient介紹

  雖然在 JDK 的 java.net 包中已經提供了訪問 HTTP 協議的基本功能,但是它沒有提供足夠的靈活性和其他應用程序需要的功能。HttpClient 是 Apache Jakarta Common 下的子項目,用來提供高效的、最新的、功能豐富的支持 HTTP 協議的客戶端編程工具包,並且它支持 HTTP 協議最新的版本和建議。

二、使用范例(以下版本4.3)

  1,通過get方式,請求網頁內容。我們首先創建httpclient對象,然后通過httpclient來執行http get方法,httpresponse獲得服務端響應的所有內容,httpentity為獲取的網頁消息體。

        CloseableHttpClient httpclient = HttpClients.createDefault();
        try {
            // 以get方法執行請求
            HttpGet httpGet = new HttpGet(“http://localhost/”);
            // 獲得服務器響應的所有信息
            CloseableHttpResponse responseGet = httpclient.execute(httpGet);
            try {
                System.out.println(responseGet.getStatusLine());
                // 獲得服務器響應的消息體(不包括http head)
                HttpEntity entity = responseGet.getEntity();

                if (entity != null) {
                    // 獲得響應字符集編碼
                    ContentType contentType = ContentType.getOrDefault(entity);
                    Charset charset = contentType.getCharset();
                    InputStream is = entity.getContent();
                    // 將inputstream轉化為reader,並使用緩沖讀取,還可按行讀取內容
                    BufferedReader br = new BufferedReader(
                            new InputStreamReader(is, charset));
                    String line = null;
                    while ((line = br.readLine()) != null) {
                        System.out.println(line);
                    }
                    is.close();
                }
            } finally {
                responseGet.close();
            }

        } finally {
            httpclient.close();
        }
View Code

  2,通過post方式提交表單。瀏覽器可將登錄后的會話信息存儲到本地,登陸之后的每次請求都會自動向服務器發送cookie信息,幸好的是httpclient亦可自動處理cookie信息。

        CloseableHttpClient httpclient = HttpClients.createDefault();

            // 以post方法發起登錄請求
            String urlString = "http://localhost/llogin.do";
            HttpPost httpPost = new HttpPost(urlString);
            List<NameValuePair> nvps = new ArrayList<NameValuePair>();
            nvps.add(new BasicNameValuePair("username", "admin"));
            nvps.add(new BasicNameValuePair("password", "admin"));
            // 添加post參數
            httpPost.setEntity(new UrlEncodedFormEntity(nvps));
            CloseableHttpResponse response = httpclient.execute(httpPost);

            try {
                // 狀態302的話,重定向,則無法獲取響應消息體
                System.out.println(response.getStatusLine());
                // 獲得服務器響應的消息體(不包括http head)
                HttpEntity entity = response.getEntity();

                if (entity != null) {
                    // 獲得響應字符集編碼
                    ContentType contentType = ContentType.getOrDefault(entity);
                    Charset charset = contentType.getCharset();
                    InputStream is = entity.getContent();
                    // 將inputstream轉化為reader,並使用緩沖讀取,還可按行讀取內容
                    BufferedReader br = new BufferedReader(
                            new InputStreamReader(is, charset));
                    String line = null;
                    while ((line = br.readLine()) != null) {
                        System.out.println(line);
                    }
                    is.close();
                }

            } finally {
                response.close();
            }
View Code

  3,重定向。httpclient默認可自動處理重定向請求,但是post方式需另外設置。

        LaxRedirectStrategy redirectStrategy = new LaxRedirectStrategy();
        CloseableHttpClient httpclient = HttpClients.custom()
                .setRedirectStrategy(redirectStrategy)
                .build();
        HttpClientContext context = HttpClientContext.create();
        try {
            // 以post方法執行登錄請求
            HttpPost httpPost = new HttpPost(urlString);
            List<NameValuePair> nvps = new ArrayList<NameValuePair>();
            nvps.add(new BasicNameValuePair("username", "admin"));
            nvps.add(new BasicNameValuePair("password", "admin"));
            // 添加post參數
            httpPost.setEntity(new UrlEncodedFormEntity(nvps));
            CloseableHttpResponse response = httpclient.execute(httpPost, context);

            try {
                // 狀態302的話,重定向,則無法獲取響應消息體
                System.out.println(response.getStatusLine());
                // 獲得服務器響應的消息體(不包括http head)
                HttpEntity entity = response.getEntity();

                //輸出最終訪問地址
                HttpHost targetHost = context.getTargetHost();
                System.out.println(targetHost);
                List<URI> redirecLocations = context.getRedirectLocations();
                URI location = URIUtils.resolve(httpPost.getURI(), targetHost, redirecLocations);
                System.out.println("Final HTTP location: " + location.toASCIIString());
                
                
                if (entity != null) {
                    // 獲得響應字符集編碼
                    ContentType contentType = ContentType.getOrDefault(entity);
                    Charset charset = contentType.getCharset();
                    InputStream is = entity.getContent();
                    // 將inputstream轉化為reader,並使用緩沖讀取,還可按行讀取內容
                    BufferedReader br = new BufferedReader(
                            new InputStreamReader(is, charset));
                    String line = null;
                    while ((line = br.readLine()) != null) {
                        System.out.println(line);
                    }
                    is.close();
                }

            } finally {
                response.close();
            }

        } finally {
            httpclient.close();
        }
View Code

  4,利用httpclient,我們可以封裝一個方法,只要傳入httpclient對象和url地址,即可返回網頁內容。

    public static String getHtml(HttpClient httpClient, String url)  {

        // HttpClient主要用來執行http方法
        CloseableHttpClient httpclient = HttpClients.createDefault();
        try {
            // 以get方法向服務端發起請求
            HttpGet httpGet = new HttpGet(url);
            // 獲得服務器響應的所有信息
            CloseableHttpResponse responseGet = httpclient.execute(httpGet);

            try {
                // 獲得服務器響應的消息體(不包括http head)
                HttpEntity entity = responseGet.getEntity();

                if (entity != null) {
                    // 獲得響應字符集編碼
                    ContentType contentType = ContentType.getOrDefault(entity);
                    Charset charset = contentType.getCharset();
                    InputStream is = entity.getContent();
                    //IOUtils是common-io提供的
                    String htmlString = IOUtils.toString(is);
                    
                    is.close();
                    return htmlString;
                }
            } finally {
                responseGet.close();
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
        
        return null;
    }
View Code

  另外,若訪問的是圖片,則可從輸入流中將內容存儲到byte數組中,如byte[] image = IOUtils.toByteArray(is),返回byte[]即可;若想下載保存到本地,可使用IOUtils的方法:IOUtils.copy(is, new FileOutputStream(filename))。

這里略提一下Apache-Commons-IO組件,它是對jdk中的io包進行拓展,讓我們可以更方便處理輸入輸出流和對文件的處理。

最后,要想學習熟悉httpclient,最好就是查看其官方文檔和它提供的范例,它的文檔和范例都很不錯,推薦閱讀。


免責聲明!

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



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