httpclient 学习

本文详细介绍了HttpClient的基本使用方法,包括模拟GET请求、设置请求头、处理响应状态和内容类型,以及如何使用代理IP绕过反爬机制等内容。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Http协议的重要性相信不用我多说了,HttpClient相比传统JDK自带的URLConnection,增加了易用性和灵活性,它不仅是客户端发送Http请求变得容易,而且也方便了开发人员测试接口(基于Http协议的),即提高了开发的效率,也方便提高代码的健壮性。因此熟练掌握HttpClient是很重要的必修内容,掌握HttpClient后,相信对于Http协议的了解会更加深入。

一、简介

HttpClient是Apache Jakarta Common下的子项目,用来提供高效的、最新的、功能丰富的支持HTTP协议的客户端编程工具包,并且它支持HTTP协议最新的版本和建议。HttpClient已经应用在很多的项目中,比如Apache Jakarta上很著名的另外两个开源项目Cactus和HTMLUnit都使用了HttpClient。

 

二、特性

1. 基于标准、纯净的Java语言。实现了Http1.0和Http1.1

2. 以可扩展的面向对象的结构实现了Http全部的方法(GET, POST, PUT, DELETE, HEAD, OPTIONS, and TRACE)。

3. 支持HTTPS协议。

4. 通过Http代理建立透明的连接。

5. 利用CONNECT方法通过Http代理建立隧道的https连接。

6. Basic, Digest, NTLMv1, NTLMv2, NTLM2 Session, SNPNEGO/Kerberos认证方案。

7. 插件式的自定义认证方案。

8. 便携可靠的套接字工厂使它更容易的使用第三方解决方案。

9. 连接管理器支持多线程应用。支持设置最大连接数,同时支持设置每个主机的最大连接数,发现并关闭过期的连接。

10. 自动处理Set-Cookie中的Cookie。

11. 插件式的自定义Cookie策略。

12. Request的输出流可以避免流中内容直接缓冲到socket服务器。

13. Response的输入流可以有效的从socket服务器直接读取相应内容。

14. 在http1.0和http1.1中利用KeepAlive保持持久连接。

15. 直接获取服务器发送的response code和 headers。

16. 设置连接超时的能力。

17. 实验性的支持http1.1 response caching。

18. 源代码基于Apache License 可免费获取。

三、使用方法

使用HttpClient发送请求、接收响应很简单,一般需要如下几步即可。

1. 创建HttpClient对象。

2. 创建请求方法的实例,并指定请求URL。如果需要发送GET请求,创建HttpGet对象;如果需要发送POST请求,创建HttpPost对象。

3. 如果需要发送请求参数,可调用HttpGet、HttpPost共同的setParams(HetpParams params)方法来添加请求参数;对于HttpPost对象而言,也可调用setEntity(HttpEntity entity)方法来设置请求参数。

4. 调用HttpClient对象的execute(HttpUriRequest request)发送请求,该方法返回一个HttpResponse。

5. 调用HttpResponse的getAllHeaders()、getHeaders(String name)等方法可获取服务器的响应头;调用HttpResponse的getEntity()方法可获取HttpEntity对象,该对象包装了服务器的响应内容。程序可通过该对象获取服务器的响应内容。

6. 释放连接。无论执行方法是否成功,都必须释放连接

四、实例

实例一:模拟get请求发送,获取返回的内容。

package httpclient;

import java.io.IOException;

import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;

/**
 * Hello world!
 *
 */
public class App 
{
    public static void main( String[] args ) throws Exception, IOException
    {
        CloseableHttpClient httpclient = HttpClients.createDefault(); //创建httpclient
        HttpGet httpGet = new HttpGet("https://www.cnblogs.com"); //创建get 请求
        CloseableHttpResponse response = httpclient.execute(httpGet); //通过httpcleint 发送get 请求
        if(response != null)
        {
            HttpEntity httpentity = response.getEntity(); //获取响应
            System.out.println(EntityUtils.toString(httpentity,"UTF-8")); //采用工具来将实体进行转换输出
        }
        response.close();
        httpclient.close();
    }
}

 

结果如下:

 

说明上面代码采用的maven 项目需要导入httpclient相关的包,pom文件如下:

<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.2</version>
</dependency>

总结,上面我看看到httpclient 很容易的模拟了,客户端发送了http请求,post方式方式一样,但是接下来我们看下面的一个实例:

 

package httpclient;

import java.io.IOException;

import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;

/**
 * Hello world!
 *
 */
public class App 
{
    public static void main( String[] args ) throws Exception, IOException
    {
        CloseableHttpClient httpclient = HttpClients.createDefault(); //创建httpclient
        HttpGet httpGet = new HttpGet("http://www.tuicool.com/"); //创建get 请求
        CloseableHttpResponse response = httpclient.execute(httpGet); //通过httpcleint 发送get 请求
        if(response != null)
        {
            HttpEntity httpentity = response.getEntity(); //获取响应
            System.out.println(EntityUtils.toString(httpentity,"UTF-8")); //采用工具来将实体进行转换输出
        }
        response.close();
        httpclient.close();
    }
}

 

结果如下:

 

 这是为什么呢? 原因就在于我们上面模拟的是客户端发送了http请求,但不是模拟的浏览器发出的请求,因此有些网站做了防护,怎么来模拟浏览器发出的请求呢? 浏览器在请的过程中,我们知道会有请求头信息,以便目标服务器识别,如下:

 

 

 

会有一个:

  1. Accept:
    text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
  2. Accept-Encoding:
    gzip, deflate
  3. Accept-Language:
    zh-CN,zh;q=0.8
  4. Cache-Control:
    max-age=0
  5. Connection:
    keep-alive
  6. Cookie:
    _tuicool_session=BAh7CEkiD3Nlc3Npb25faWQGOgZFRkkiJWE5MWZjYzMwMDBmYjRjZWJjZWI5ZmE1MWNlNzQwNzQ4BjsAVEkiEF9jc3JmX3Rva2VuBjsARkkiMXpvZzZRVEVLNHNEYlJNYVJqMVlrUG5tUHJWR0FaeDh0RzFxY28za3pzR009BjsARkkiDnJldHVybl90bwY7AEZJIitodHRwOi8vd3d3LnR1aWNvb2wuY29tL2FydGljbGVzL2JRajJFMwY7AEY%3D--d83358350fdbe214e013c16660630e5ffa3fc4f0; UM_distinctid=15e47ec08fe321-044bcb8a12f122-546b3971-100200-15e47ec08ff33c; CNZZDATA5541078=cnzz_eid%3D626609411-1504443418-%26ntime%3D1504443418
  7. Host:
    www.tuicool.com
  8. If-None-Match:
    W/"a415838fed502ea413339b0b13542108"
  9. Upgrade-Insecure-Requests:
    1
  10. User-Agent:
    Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36

其中最重要的是就是User-Agent,那么我们要模拟浏览器,则需要设置头消息,代码如下:

package httpclient;

import java.io.IOException;

import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;

/**
 * Hello world!
 *
 */
public class App 
{
    public static void main( String[] args ) throws Exception, IOException
    {
        CloseableHttpClient httpclient = HttpClients.createDefault(); //创建httpclient
        HttpGet httpGet = new HttpGet("http://www.tuicool.com/"); //创建get 请求
        httpGet.setHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36");
        CloseableHttpResponse response = httpclient.execute(httpGet); //通过httpcleint 发送get 请求
        if(response != null)
        {
            HttpEntity httpentity = response.getEntity(); //获取响应
            System.out.println(EntityUtils.toString(httpentity,"UTF-8")); //采用工具来将实体进行转换输出
        }
        response.close();
        httpclient.close();
    }
}

 

这个时候,我们测试一下可以看到结果如下:

 

结果已经正常显示出来了,但这个时候,我们是否想到,既然一个浏览器发送了http请求,我们会看到有状态,那么如何通过httpclient返回的response来获取对应的状态呢,以及如何获取响应的类型呢?类型即我们说的content-type

 

这个时候我们需要通过HttpEntity 来获取,为什么获取content-type 是因为获取的类型非常多,有些是不需要我们采集的,这个时候我们可以通过这个内容类型进行采集过滤。

代码如下:

package httpclient;

import java.io.IOException;

import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;

/**
 * Hello world!
 *
 */
public class App 
{
    public static void main( String[] args ) throws Exception, IOException
    {
        CloseableHttpClient httpclient = HttpClients.createDefault(); //创建httpclient
        HttpGet httpGet = new HttpGet("http://www.tuicool.com/"); //创建get 请求
        httpGet.setHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36");
        CloseableHttpResponse response = httpclient.execute(httpGet); //通过httpcleint 发送get 请求
        if(response != null)
        {
            System.out.println(response.getStatusLine().getStatusCode());
            HttpEntity httpentity = response.getEntity(); //获取响应
            System.out.println(httpentity.getContentType().getValue());
            //System.out.println(EntityUtils.toString(httpentity,"UTF-8")); //采用工具来将实体进行转换输出
        }
        response.close();
        httpclient.close();
    }
}

结果如下:

 

总结,上面我们采取的都静态的文本等,但是我们采集的时候,如果要采集图片怎么办,图片的获取处理方式如下:

比如:http://aimg2.tuicool.com/qm6Rre6.jpg!index  采集这个图片。

 

package httpclient;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;

import org.apache.commons.io.FileUtils;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;

/**
 * Hello world!
 *
 */
public class App 
{
    public static void main( String[] args ) throws Exception, IOException
    {
        CloseableHttpClient httpclient = HttpClients.createDefault(); //创建httpclient
        HttpGet httpGet = new HttpGet("http://aimg2.tuicool.com/qm6Rre6.jpg!index"); //创建get 请求
        httpGet.setHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36");
        CloseableHttpResponse response = httpclient.execute(httpGet); //通过httpcleint 发送get 请求
        if(response != null)
        {
            //System.out.println(response.getStatusLine().getStatusCode());
            HttpEntity httpentity = response.getEntity(); //获取响应
            if(httpentity != null)
            {
                System.out.println(httpentity.getContentType().getValue()); //判断内容的类型,因为我们要采集图片,所以要过滤掉其它内容.
                //接着,图片肯定要通过流的方式去读取.
                InputStream inputStream = httpentity.getContent();
                //然后通过输入流,然后读取流,输出流,则可以转换读取我们的图片,流的复制.
                //在这里我们可以 通过Apache 提供的IO 工具流来直接进行流的复制.
                FileUtils.copyToFile(inputStream, new File("D://a.jpg")); //实际中是要拷贝真是的目录下面,并且图片的名称也是唯一的。
            }
            //System.out.println(httpentity.getContentType().getValue());
            //System.out.println(EntityUtils.toString(httpentity,"UTF-8")); //采用工具来将实体进行转换输出
        }
        response.close();
        httpclient.close();
    }
}

 

注意上面,需要导入io 包。

https://mvnrepository.com/artifact/commons-io/commons-io/2.5

<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.5</version>
</dependency>

 

 

实例二 :上面我们演示了,图片的采集,和静态信息的采集,但是对于一些有防范的网站,一般大公司会有屏蔽信,即不让你长时间采集,一旦你长时间采集,则会进行封掉IP,那这个时候我们该怎么办,这个时候我们需要代码IP,先看下面的介绍:

在爬取网页的时候,有的目标站点有反爬虫机制,对于频繁访问站点以及规则性访问站点的行为,会采集屏蔽IP措施。

 

这时候,代理IP就派上用场了。

 

关于代理IP的话 也分几种 透明代理、匿名代理、混淆代理、高匿代理

 

1、透明代理(Transparent Proxy)

 

REMOTE_ADDR = Proxy IP

 

HTTP_VIA = Proxy IP

 

HTTP_X_FORWARDED_FOR = Your IP

 

透明代理虽然可以直接“隐藏”你的IP地址,但是还是可以从HTTP_X_FORWARDED_FOR来查到你是谁。

 

2、匿名代理(Anonymous Proxy)

 

REMOTE_ADDR = proxy IP

 

HTTP_VIA = proxy IP

 

HTTP_X_FORWARDED_FOR = proxy IP

 

匿名代理比透明代理进步了一点:别人只能知道你用了代理,无法知道你是谁。

 

还有一种比纯匿名代理更先进一点的:混淆代理,见下节。

 

3、混淆代理(Distorting Proxies)

 

REMOTE_ADDR = Proxy IP

HTTP_VIA = Proxy IP

HTTP_X_FORWARDED_FOR = Random IP address

 

如上,与匿名代理相同,如果使用了混淆代理,别人还是能知道你在用代理,但是会得到一个假的IP地址,伪装的更逼真:-)

 

4、高匿代理(Elite proxy或High Anonymity Proxy)

 

REMOTE_ADDR = Proxy IP

 

HTTP_VIA = not determined

 

HTTP_X_FORWARDED_FOR = not determined

 

可以看出来,高匿代理让别人根本无法发现你是在用代理,所以是最好的选择。

 

一般我们搞爬虫 用的都是 高匿的代理IP;

 

那代理IP 从哪里搞呢 很简单  百度一下,你就知道 一大堆代理IP站点。  一般都会给出一些免费的,但是花点钱搞收费接口更加方便;

 

比如 http://www.66ip.cn/

 

httpClient使用代理IP代码:

package httpclient;

import java.io.IOException;

import org.apache.http.HttpEntity;
import org.apache.http.HttpHost;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;

/**
 * Hello world!
 *
 */
public class App 
{
    public static void main( String[] args ) throws Exception, IOException
    {
        CloseableHttpClient httpclient = HttpClients.createDefault(); //创建httpclient
        HttpGet httpGet = new HttpGet("https://www.taobao.com/"); //创建get 请求
        HttpHost proxy = new HttpHost("115.202.167.56",808);
        RequestConfig config = RequestConfig.custom().setProxy(proxy).build();
        //设置代理IP
        httpGet.setConfig(config);
        httpGet.setHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36");
        CloseableHttpResponse response = httpclient.execute(httpGet); //通过httpcleint 发送get 请求
        if(response != null)
        {
            //System.out.println(response.getStatusLine().getStatusCode());
            HttpEntity httpentity = response.getEntity(); //获取响应
            if(httpentity != null)
            {
                System.out.println(httpentity.getContentType().getValue());
                System.out.println(EntityUtils.toString(httpentity,"UTF-8")); //采用工具来将实体进行转换输出
                //System.out.println(httpentity.getContentType().getValue()); //判断内容的类型,因为我们要采集图片,所以要过滤掉其它内容.
                //接着,图片肯定要通过流的方式去读取.
                //InputStream inputStream = httpentity.getContent();
                //然后通过输入流,然后读取流,输出流,则可以转换读取我们的图片,流的复制.
                //在这里我们可以 通过Apache 提供的IO 工具流来直接进行流的复制.
                //FileUtils.copyToFile(inputStream, new File("D://a.jpg")); //实际中是要拷贝真是的目录下面,并且图片的名称也是唯一的。
            }
            //System.out.println(httpentity.getContentType().getValue());
            //System.out.println(EntityUtils.toString(httpentity,"UTF-8")); //采用工具来将实体进行转换输出
        }
        response.close();
        httpclient.close();
    }
}

 

通过代理IP,测试结果如下:

 

其它知识点:

如连接超时时间设置,读取内容超时时间设置等。

 

实例三:连接超时和内容超时

httpClient在执行具体http请求时候 有一个连接的时间和读取内容的时间;

HttpClient连接时间

所谓连接的时候 是HttpClient发送请求的地方开始到连接上目标url主机地址的时间,理论上是距离越短越快,

线路越通畅越快,但是由于路由复杂交错,往往连接上的时间都不固定,运气不好连不上,HttpClient的默认连接时间,据我测试,

默认是1分钟,假如超过1分钟 过一会继续尝试连接,这样会有一个问题 假如遇到一个url老是连不上,会影响其他线程的线程进去,说难听点,

就是蹲着茅坑不拉屎。所以我们有必要进行特殊设置,比如设置10秒钟 假如10秒钟没有连接上 我们就报错,这样我们就可以进行业务上的处理,

比如我们业务上控制 过会再连接试试看。并且这个特殊url写到log4j日志里去。方便管理员查看。

HttpClient读取时间

所谓读取的时间 是HttpClient已经连接到了目标服务器,然后进行内容数据的获取,一般情况 读取数据都是很快速的,

但是假如读取的数据量大,或者是目标服务器本身的问题(比如读取数据库速度慢,并发量大等等..)也会影响读取时间。

同上,我们还是需要来特殊设置下,比如设置10秒钟 假如10秒钟还没读取完,就报错,同上,我们可以业务上处理。

 

HttpClient给我们提供了一个RequestConfig类 专门用于配置参数比如连接时间,读取时间以及前面讲解的代理IP等。

主要通过:

RequestConfig config=RequestConfig.custom()
                .setConnectTimeout(5000)
                .setSocketTimeout(5000)
                .build();
        httpGet.setConfig(config);

 

 到此,httpclient 相关的一些基本知识就学到这里了,如果深入学习,可以参考httpclient的书籍深入.

 

<think>我们正在学习HttpClient框架的使用。根据引用[1]和[2],HttpClient是Apache软件基金会的一个开源项目,用于处理HTTP通信。它提供了高效、可靠的HTTP通信能力,支持连接池管理、多线程安全、HTTPS等特性。我们将从基础开始,逐步介绍如何使用HttpClient。 ### 1. 添加依赖 首先,在项目中添加HttpClient依赖。如果使用Maven,在pom.xml中添加(注意版本号,这里以4.5.3为例,但建议使用最新稳定版本): ```xml <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> <version>4.5.13</version> <!-- 请检查最新版本 --> </dependency> ``` ### 2. 创建HttpClient实例 HttpClient实例是线程安全的,建议重复使用同一个实例。可以通过`HttpClientBuilder`创建: ```java import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; public class HttpClientExample { public static void main(String[] args) { // 创建HttpClient实例 try (CloseableHttpClient httpClient = HttpClients.createDefault()) { // 使用httpClient执行请求 } catch (Exception e) { e.printStackTrace(); } } } ``` ### 3. 执行HTTP请求 下面以GET请求为例,展示如何发送请求并处理响应: ```java import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpGet; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; import org.apache.http.util.EntityUtils; public class GetExample { public static void main(String[] args) { try (CloseableHttpClient httpClient = HttpClients.createDefault()) { HttpGet httpGet = new HttpGet("https://example.com"); try (CloseableHttpResponse response = httpClient.execute(httpGet)) { // 获取响应状态码 int statusCode = response.getStatusLine().getStatusCode(); System.out.println("Status Code: " + statusCode); // 获取响应内容 String responseBody = EntityUtils.toString(response.getEntity()); System.out.println("Response Body: " + responseBody); } } catch (Exception e) { e.printStackTrace(); } } } ``` ### 4. 处理POST请求 发送POST请求需要构建请求体。以下示例发送JSON数据: ```java import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpPost; import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; import org.apache.http.util.EntityUtils; public class PostExample { public static void main(String[] args) { try (CloseableHttpClient httpClient = HttpClients.createDefault()) { HttpPost httpPost = new HttpPost("https://example.com/api"); // 设置请求头 httpPost.setHeader("Content-Type", "application/json"); // 设置请求体 String json = "{\"username\":\"admin\",\"password\":\"123456\"}"; httpPost.setEntity(new StringEntity(json)); try (CloseableHttpResponse response = httpClient.execute(httpPost)) { // 处理响应 System.out.println("Status Code: " + response.getStatusLine().getStatusCode()); System.out.println("Response Body: " + EntityUtils.toString(response.getEntity())); } } catch (Exception e) { e.printStackTrace(); } } } ``` ### 5. 高级特性 - **连接池管理**:通过配置连接池提高性能。使用`PoolingHttpClientConnectionManager`可以管理多个连接。 - **HTTPS支持**:HttpClient默认支持HTTPS,但可能需要配置SSL上下文以处理自签名证书等。 - **Cookie管理**:使用`CookieStore`和`HttpClientContext`来管理Cookie。 ### 6. 实战示例:使用连接池 ```java import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; public class ConnectionPoolExample { public static void main(String[] args) { // 创建连接池管理器 PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager(); cm.setMaxTotal(200); // 最大连接数 cm.setDefaultMaxPerRoute(20); // 每个路由最大连接数 // 创建HttpClient try (CloseableHttpClient httpClient = HttpClients.custom() .setConnectionManager(cm) .build()) { // 使用httpClient执行多个请求 } catch (Exception e) { e.printStackTrace(); } } } ``` ### 7. 注意事项 - **资源释放**:确保关闭`CloseableHttpResponse`和`CloseableHttpClient`,避免资源泄漏。 - **异常处理**:妥善处理IO异常和HTTP状态异常。 - **性能优化**:合理配置连接池参数,避免频繁创建和销毁连接。 --- 通过以上步骤,你可以开始使用HttpClient进行HTTP通信。更多高级用法请参考官方文档[^1][^2]。 §§相关问题§§ 1. 如何在HttpClient中处理HTTPS请求并忽略证书验证? 2. 如何使用HttpClient进行文件上传? 3. HttpClient如何设置超时时间? 4. 如何通过HttpClient实现重试机制? 5. 如何使用HttpClient进行身份认证(如Basic Auth)?</think>### Apache HttpClient 学习与使用指南 Apache HttpClient 是 Java 领域最强大的 HTTP 客户端库之一,支持 HTTP/1.1、HTTP/2、HTTPS、连接池、Cookie 管理等高级特性。以下是核心使用指南: --- ### 一、快速入门 #### 1. 添加依赖(Maven) ```xml <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> <version>4.5.13</version> <!-- 检查最新版本 --> </dependency> ``` #### 2. 发送 GET 请求 ```java import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpGet; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; import org.apache.http.util.EntityUtils; public class BasicGetExample { public static void main(String[] args) throws Exception { try (CloseableHttpClient httpClient = HttpClients.createDefault()) { HttpGet httpGet = new HttpGet("https://api.example.com/data"); try (CloseableHttpResponse response = httpClient.execute(httpGet)) { // 获取状态码 int statusCode = response.getStatusLine().getStatusCode(); // 获取响应内容 String responseBody = EntityUtils.toString(response.getEntity()); System.out.println("Status: " + statusCode); System.out.println("Response: " + responseBody); } } } } ``` --- ### 二、核心功能详解 #### 1. 连接池管理 通过连接池提升性能: ```java PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager(); cm.setMaxTotal(200); // 最大连接数 cm.setDefaultMaxPerRoute(20); // 每个路由的最大连接数 try (CloseableHttpClient httpClient = HttpClients.custom() .setConnectionManager(cm) .build()) { // 执行请求... } ``` #### 2. 处理 HTTPS 忽略证书验证(仅测试环境使用): ```java SSLContext sslContext = SSLContexts.custom() .loadTrustMaterial((chain, authType) -> true) // 信任所有证书 .build(); try (CloseableHttpClient httpClient = HttpClients.custom() .setSSLContext(sslContext) .setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE) .build()) { // 执行HTTPS请求... } ``` #### 3. 请求超时控制 ```java RequestConfig config = RequestConfig.custom() .setConnectTimeout(5000) // 连接超时(ms) .setSocketTimeout(10000) // 数据传输超时(ms) .build(); HttpGet httpGet = new HttpGet("https://api.example.com"); httpGet.setConfig(config); ``` #### 4. 表单提交(POST) ```java HttpPost httpPost = new HttpPost("https://api.example.com/login"); List<NameValuePair> params = new ArrayList<>(); params.add(new BasicNameValuePair("username", "test")); params.add(new BasicNameValuePair("password", "123456")); httpPost.setEntity(new UrlEncodedFormEntity(params)); try (CloseableHttpResponse response = httpClient.execute(httpPost)) { // 处理响应... } ``` #### 5. 文件上传 ```java HttpPost httpPost = new HttpPost("https://api.example.com/upload"); FileBody fileBody = new FileBody(new File("test.txt")); MultipartEntityBuilder builder = MultipartEntityBuilder.create(); builder.addPart("file", fileBody); httpPost.setEntity(builder.build()); ``` --- ### 三、高级特性 #### 1. Cookie 管理 ```java CookieStore cookieStore = new BasicCookieStore(); try (CloseableHttpClient httpClient = HttpClients.custom() .setDefaultCookieStore(cookieStore) .build()) { // 首次登录(存储Cookie) HttpPost login = new HttpPost("https://api.example.com/login"); // ... 执行登录 // 后续请求自动携带Cookie HttpGet profile = new HttpGet("https://api.example.com/profile"); httpClient.execute(profile); } ``` #### 2. 异步请求 ```java Future<HttpResponse> future = httpClient.execute( new HttpGet("https://api.example.com/async"), new FutureCallback<HttpResponse>() { @Override public void completed(HttpResponse response) { System.out.println("请求完成"); } @Override public void failed(Exception ex) { ex.printStackTrace(); } @Override public void cancelled() { System.out.println("请求取消"); } } ); ``` --- ### 四、最佳实践 1. **资源释放** 确保关闭 `CloseableHttpResponse` 和 `CloseableHttpClient`(使用 try-with-resources)。 2. **异常处理** 捕获 `IOException` 和 `ClientProtocolException`。 3. **连接复用** 避免频繁创建/销毁 HttpClient 实例,使用连接池[^1]。 4. **日志调试** 添加日志依赖查看网络交互细节: ```xml <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-core</artifactId> <version>2.17.1</version> </dependency> ``` --- ### 五、实战示例:API 测试框架 ```java public class ApiTester { private final CloseableHttpClient httpClient; public ApiTester() { this.httpClient = HttpClients.custom() .setConnectionManager(new PoolingHttpClientConnectionManager()) .build(); } public String get(String url) throws IOException { HttpGet request = new HttpGet(url); try (CloseableHttpResponse response = httpClient.execute(request)) { return EntityUtils.toString(response.getEntity()); } } public int post(String url, Map<String, String> params) throws IOException { HttpPost request = new HttpPost(url); List<NameValuePair> nvpList = new ArrayList<>(); params.forEach((k, v) -> nvpList.add(new BasicNameValuePair(k, v))); request.setEntity(new UrlEncodedFormEntity(nvpList)); try (CloseableHttpResponse response = httpClient.execute(request)) { return response.getStatusLine().getStatusCode(); } } } ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值