执子之手

与子偕老


  • 首页

  • 分类

  • 归档

  • 标签

  • 关于

  • 搜索
close

Apache HttpClient 使用(上)

时间: 2018-04-23   |   分类: 开发     |   阅读: 3444 字 ~7分钟   |   访问: 0

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

目前最新的版本是4.5,支持HTTP 1.0/HTTP 1.1协议。正在开发中的5.0版本(还在Beta阶段)支持HTTP/2协议。

1. 特性

  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 可免费获取。

2. 使用方法

下面以一个简单的例子来说明一下HttpClient的使用方法。

2.1 pom

1    <dependency>
2        <groupId>org.apache.httpcomponents</groupId>
3        <artifactId>httpclient</artifactId>
4        <version>4.5.4</version>
5    </dependency>

首先引入相关的Maven库。

2.2 代码

 1String url = "http://www.baidu.com";
 2// 1. 使用默认的配置的httpclient
 3CloseableHttpClient client = HttpClients.createDefault();
 4// 2. 使用GET方法
 5HttpGet httpGet = new HttpGet(url);
 6InputStream inputStream = null;
 7CloseableHttpResponse response = null;
 8try {
 9    //3.执行请求,获取响应
10    response = client.execute(httpGet);
11    //看请求是否成功,这儿打印的是http状态码
12    System.out.println(response.getStatusLine().getStatusCode());
13
14    //4.获取响应的实体内容,就是我们所要抓取得网页内容
15    HttpEntity entity = response.getEntity();
16
17    //5.将其打印到控制台上面
18    //方法一:使用EntityUtils
19    if (entity != null) {
20        System.out.println(EntityUtils.toString(entity, "utf-8"));
21    }
22    EntityUtils.consume(entity);
23
24    //方法二:使用inputStream(不能同时使用)
25   if (entity != null) {
26        inputStream = entity.getContent();
27
28        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
29        String line = "";
30        while ((line = bufferedReader.readLine()) != null) {
31            System.out.println(line);
32
33        }
34    }
35
36} catch (ClientProtocolException e) {
37    e.printStackTrace();
38} catch (IOException e) {
39    e.printStackTrace();
40} finally {
41    if (inputStream != null) {
42        try {
43            inputStream.close();
44        } catch (IOException e) {
45            e.printStackTrace();
46        }
47    }
48    if (response != null) {
49        try {
50            response.close();
51        } catch (IOException e) {
52            e.printStackTrace();
53        }
54    }
55}

这段代码的用途是使用GET方法获取百度首页,并打印出来。

2.3 代码分析

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

  1. 创建HttpClient对象。 例子中使用的是org.apache.http.impl.client.CloseableHtttpClient,它是HttpClient接口的一个实例,创建该对象的最简单方法是:CloseableHttpClient client = HttpClients.createDefault();。 HttpClients是创建CloseableHttpClient的工厂,采用默认的配置来创建实例,一般情况下我们就用这个默认实例就可以了。以后我们会讨论如何自定义这个对象。

  2. 创建请求方法的实例,并指定请求URL。如果需要发送GET请求,创建HttpGet对象;如果需要发送POST请求,创建HttpPost对象。 其他的类型还有:HttpHead, HttpPut, HttpDelete, HttpTrace, HttpOptions等。分别对应不同的Http请求方法:

方法 描述 是否包含主体
GET 从服务器获取一份文档 否
HEAD 只从服务器获取文档的首部 否
POST 向服务器发送需要处理的数据 是
PUT 将请求的主体部分存储在服务器上 是
TRACE 对可能经过代理服务器传送到服务器上去的报文进行追踪 否
OPTIONS 决定可以在服务器上执行哪些方法 否
DELETE 从服务器上删除一份文档 否
  1. 如果需要发送请求参数,可调用HttpGet、HttpPost共同的setParams(HetpParams params)方法来添加请求参数;对于HttpPost对象而言,也可调用setEntity(HttpEntity entity)方法来设置请求参数。

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

  3. 调用HttpResponse的getAllHeaders()、getHeaders(String name)等方法可获取服务器的响应头;调用HttpResponse getEntity()方法可获取HttpEntity对象,该对象包装了服务器的响应内容。对getEntity获取的结果,有两种处理方法: 方法一:使用EntityUtils工具类来处理。该类是官方提供的一个处理实体的工具类,toSting方法将返回的实体转换为字符串,但是官网不建议使用这个,除非响应实体从一个可信HTTP服务器发起和已知是有限长度的。 方法二:使用InputStream来读取。因为httpEntity.getContent方法返回的就是InputStream类型。这种方法是官网推荐的方式,需要记得要自己释放底层资源。

  4. 释放连接。无论执行方法是否成功,都必须释放连接 如果使用EntityUtils来处理返回值,则可以使用EntityUtils.consume(entity)来释放资源。

如果使用InputStream来处理返回值,则要关闭inputStream然后关闭response对象就行了。

 1if (inputStream != null) {
 2    try {
 3        inputStream.close();
 4    } catch (IOException e) {
 5        e.printStackTrace();
 6    }
 7}
 8if (response != null) {
 9    try {
10        response.close();
11    } catch (IOException e) {
12        e.printStackTrace();
13    }
14}

2.4 关于资源释放

使用EntityUtils#consume这个方法会自动关闭底层的inputStream。如果不需要读取全部的实体,则可以直接关闭response,来种植对inputStream的读取。注意:关闭response会自动关闭对应的inputStream。

 1CloseableHttpClient httpclient = HttpClients.createDefault();
 2HttpGet httpget = new HttpGet("http://localhost/");
 3CloseableHttpResponse response = httpclient.execute(httpget);
 4try {
 5    HttpEntity entity = response.getEntity();
 6    if (entity != null) {
 7        InputStream instream = entity.getContent();
 8        int byteOne = instream.read();
 9        int byteTwo = instream.read();
10        // Do not need the rest
11    }
12} finally {
13    response.close();   // 直接关闭response
14}

不推荐使用EntityUtils#toString方法,如果确实需要,最好先自己判断长度:entity.getContentLength()。这是因为toString方法默认最大的长度是Integer.MAX_VALUE(0x7fffffff)。这个长度太大了,很容易导致缓冲区溢出。

如果希望重复使用Entity,可以使用:new BufferedHttpEntity(entity)创建一个新对象缓存起来。

2.5 Entity

用于生成请求的Entity的类主要有四种:StringEntity, ByteArrayEntity, InputStreamEntity和FileEntity。 例子:FileEntity:

1File file = new File("somefile.txt");
2FileEntity entity = new FileEntity(file, 
3    ContentType.create("text/plain", "UTF-8"));        
4HttpPost httppost = new HttpPost("http://localhost/action.do");
5httppost.setEntity(entity);

例子:

1List<NameValuePair> formparams = new ArrayList<NameValuePair>();
2formparams.add(new BasicNameValuePair("param1", "value1"));
3formparams.add(new BasicNameValuePair("param2", "value2"));
4UrlEncodedFormEntity entity = new UrlEncodedFormEntity(formparams, Consts.UTF_8);
5HttpPost httppost = new HttpPost("http://localhost/handler.do");
6httppost.setEntity(entity);

3. 实例代码

3.1 普通GET请求

 1// 创建Httpclient对象  
 2CloseableHttpClient httpclient = HttpClients.createDefault();  
 3// 创建http GET请求  
 4HttpGet httpGet = new HttpGet("http://www.baidu.com/s?wd=java");  
 5CloseableHttpResponse response = null;         
 6try {
 7    // 执行请求  
 8    response = httpclient.execute(httpGet);
 9    // 判断返回状态是否为200  
10    if (response.getStatusLine().getStatusCode() == 200) {
11        ...
12    }
13}

3.2 带有参数的Get请求

1// 定义请求的参数  
2URI uri = new URIBuilder("http://www.baidu.com/s").setParameter("wd", "java").build();  
3// 创建http GET请求  
4HttpGet httpGet = new HttpGet(uri); 

3.3 普通的POST请求

1// 创建http POST请求  
2HttpPost httpPost = new HttpPost("http://www.oschina.net/");  
3   // 伪装浏览器请求  
4httpPost.setHeader("User-Agent",  
5        "Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.118 Safari/537.36");  
6// 执行请求  
7response = httpclient.execute(httpPost);  

3.4 带有参数的Post请求

 1// 创建http POST请求  
 2HttpPost httpPost = new HttpPost("http://www.oschina.net/search");  
 3  
 4// 设置2个post参数,一个是scope、一个是q  
 5List<NameValuePair> parameters = new ArrayList<NameValuePair>();  
 6parameters.add(new BasicNameValuePair("scope", "project"));  
 7parameters.add(new BasicNameValuePair("q", "java"));  
 8// 构造一个form表单式的实体  
 9UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity(parameters);  
10// 将请求实体设置到httpPost对象中  
11httpPost.setEntity(formEntity);  
12// 伪装浏览器请求  
13httpPost.setHeader(  
14        "User-Agent",  
15        "Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.118 Safari/537.36");  
16        
17// 执行请求  
18response = httpclient.execute(httpPost); 

3.5 配置超时时间等

 1// 创建http GET请求  
 2HttpGet httpGet = new HttpGet("http://www.baidu.com/");  
 3  
 4// 构建请求配置信息  
 5RequestConfig config = RequestConfig.custom()
 6        .setConnectTimeout(1000) // 创建连接的最长时间  
 7        .setConnectionRequestTimeout(500) // 从连接池中获取到连接的最长时间  
 8        .setSocketTimeout(10 * 1000) // 数据传输的最长时间  
 9        .setStaleConnectionCheckEnabled(true) // 提交请求前测试连接是否可用  
10        .build();  
11// 设置请求配置信息  
12httpGet.setConfig(config);  

几个函数的含义:

  • setConnectionRequestTimeout 从链接池获取一个连接的最长等待时间;
  • setConnectTimeout 创建链接的最长等待时间;
  • setSocketTimeout 获取数据的最长等待时间;
  • setStaleConnectionCheckEnabled 检查链接状态是否可用。这个选项会花费最长30ms时间已确定一个连接是否可用。对性能要求高的应用不要开启这个选项。
#Java# #HttpClient#
迁移到SpringBoot 00 - 背景介绍
Apache HttpClient 使用(下)
  • 文章目录
  • 站点概览
Orchidflower

Orchidflower

Do one thing at a time, and do well.

77 日志
6 分类
84 标签
GitHub 知乎 OSC 豆瓣
  • 1. 特性
  • 2. 使用方法
    • 2.1 pom
    • 2.2 代码
    • 2.3 代码分析
    • 2.4 关于资源释放
    • 2.5 Entity
  • 3. 实例代码
    • 3.1 普通GET请求
    • 3.2 带有参数的Get请求
    • 3.3 普通的POST请求
    • 3.4 带有参数的Post请求
    • 3.5 配置超时时间等
© 2009 - 2024 执子之手
Powered by - Hugo v0.113.0
Theme by - NexT
ICP - 鲁ICP备17006463号-1
0%