HttpClient 该知道不该知道的一些事


一、简介:

  • Apache开源项目: http://hc.apache.org/
  • 基于HTTP协议提供强大的支持,构建HTTP客户端应用程序
  • 执行HTTP协议时,包含了HTTP请求和响应不同状态,可以对关键参数设置和获取

二、HTTP协议(扫盲)

  • HTTP请求包含三部分,分别由请求行(请求方法)、请求头(消息报文)、请求正文组成。
  • HTTP请求详解:
     
  • HTTP 响应详解
    

三、URI URL和URN区别:

  • URI(Uniform Resource Identifier) 统一资源标识符
  • URL(Uniform Resource Locator)  统一资源定位符
  • URN(Uniform Resource Name)    统一资源名称
  • 整体关系:
          
 
  • 举个栗子么:
比如有一个虚拟地址,首先这是一个URI:
http://bitpoetry.io/posts/hello.html#intro
xxxxxxxxxx
1
 
1
http://bitpoetry.io/posts/hello.html#intro
我们分析:
http://
xxxxxxxxxx
1
 
1
http://
 是定义如何访问资源的方式。
bitpoetry.io/posts/hello.html
xxxxxxxxxx
1
 
1
bitpoetry.io/posts/hello.html
是资源存放的位置,那么,在这个栗子中,
#intro
xxxxxxxxxx
1
 
1
#intro
是资源。
  • URL是URI的一个子集,告诉我们访问网络位置的方式,
http://bitpoetry.io/posts/hello.html
xxxxxxxxxx
1
 
1
http://bitpoetry.io/posts/hello.html
  • URN是URI的子集,包括名字(给定的命名空间内),但不包括访问方式
bitpoetry.io/posts/hello.html#intro
xxxxxxxxxx
1
 
1
bitpoetry.io/posts/hello.html#intro

四、调用步骤:

  1. 创建 HttpClient 对象
  2. 创建请求方法的实例,并指定URL。
    1. GET 请求,创建 HttpGet 对象
    2. POST 请求,创建 HttpPost 对象
  3. 调用 SetParams(HttpParams params) 方法来添加请求参数,  对于 HttpPost 对象而言,也可以调用 setEntity(HttpEntity entity) 方法来设置请求参数
  4. 调用 HttpClient 对象的 execute(HttpUriRequest request) 发送请求,该方法返回一个 HttpResponse
  5. 调用 HttpResponse 的 getAllHeaders()、getHeaders(String name) 等方法可获取服务器的响应头;调用 HttpResponse 的 getEntity() 方法可获取 HttpEntity 对象,该对象包装了服务器的相应内容。程序可以通过获取服务器的相应内容
  6. 释放连接,无论执行方法是否成功,都必须释放连接
例如下图:
        

五、调用细节:

  • HttpClient提供了URIBuilder类来简化和修改请求URI
http://image.baidu.com/search/detail?ct=503316480&word=scheme
xxxxxxxxxx
1
 
1
http://image.baidu.com/search/detail?ct=503316480&word=scheme
     可以有如下写法:
URI uri = new URIBuilder()
.setScheme("http") //设置scheme
.setHost("image.baidu.com")//set host
.setPath("/search/detail")// set path
.setParameter("ct","503316480")// set param
.setParameter("word","scheme")
.build();
xxxxxxxxxx
7
 
1
URI uri = new URIBuilder()
2
                .setScheme("http") //设置scheme
3
                .setHost("image.baidu.com")//set host
4
                .setPath("/search/detail")// set path
5
                .setParameter("ct","503316480")// set param
6
                .setParameter("word","scheme")
7
                .build();

  • 在Response中几个关键参数获取:
response.getProtocolVersion() // 协议
response.getStatusLine().getStatusCode() //状态码
response.getStatusLine().getReasonPhrase()//表单含义
xxxxxxxxxx
3
 
1
response.getProtocolVersion() // 协议
2
response.getStatusLine().getStatusCode() //状态码
3
response.getStatusLine().getReasonPhrase()//表单含义
  • 获取给定类型的所有头部信息最有效的方式是使用HeaderIterator接口:
public static void main(String[] args) {
HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK");
response.addHeader("Set-Cookie", "c1=a; path=/; domain=localhost");
response.addHeader("Set-Cookie", "c2=b; path=\"/\", c3=c; domain=\"localhost\"");
HeaderElementIterator it = new BasicHeaderElementIterator(response.headerIterator("Set-Cookie"));
while (it.hasNext()) {
HeaderElement elem = it.nextElement();
System.out.println(elem.getName() + " = " + elem.getValue());
NameValuePair[] params = elem.getParameters();
for (int i = 0; i < params.length; i++) {
System.out.println(" " + params[i]);
}
}
}

运行输出:

c1 = a

path=/

domain=localhost

c2 = b

path=/

c3 = c

domain=localhost

xxxxxxxxxx
30
 
1
public static void main(String[] args) {
2
        HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK");
3
            response.addHeader("Set-Cookie", "c1=a; path=/; domain=localhost");
4
            response.addHeader("Set-Cookie", "c2=b; path=\"/\", c3=c; domain=\"localhost\"");
5
            HeaderElementIterator it = new BasicHeaderElementIterator(response.headerIterator("Set-Cookie"));
6
            while (it.hasNext()) {
7
                HeaderElement elem = it.nextElement(); 
8
                System.out.println(elem.getName() + " = " + elem.getValue());
9
                NameValuePair[] params = elem.getParameters();
10
                for (int i = 0; i < params.length; i++) {
11
                    System.out.println(" " + params[i]);
12
                }
13
          }
14
}
15

16
运行输出:
17

18
c1 = a
19

20
 path=/
21

22
 domain=localhost
23

24
c2 = b
25

26
 path=/
27

28
c3 = c
29

30
 domain=localhost

  • 为了保证系统资源被正确地释放,我们要么管理HTTP实体流,要么关闭http响应。
  • 关闭HTTP实体内容流和关闭HTTP响应的区别,前者通过消耗掉HTTP实体内容来保持相关HTTP连接,然而后者会立即关闭,丢弃HTTP连接。
  • HttpClient 推荐使用 HttpEntity 的 getContent() 方法或者 HttpEntity 的 writeTo(OutputStream) 方法读取Http实体内容。
  • EntityUtils 提供的方法可以以字符串或者字节数组的形式读取 Http 实体,但是一般不建议,确保相应的实体长度不大。
  • 希望把 Http 实体内容缓存在内存或者磁盘上,最简单方法就是把 Http Entity 转化为 BufferedHttpEntity,
CloseableHttpResponse response = <...>
HttpEntity entity = response.getEntity();
if (entity != null) {
entity = new BufferedHttpEntity(entity);
}
xxxxxxxxxx
5
 
1
CloseableHttpResponse response = <...>
2
HttpEntity entity = response.getEntity();
3
if (entity != null) {
4
    entity = new BufferedHttpEntity(entity);
5
}
  • HttpClient 提供了一些类,这些类可以通过http连接高效地输出Http实体内容。
  • HttpClient 提供的这几个类涵盖的常见的数据类型,如String,byte 数组,输入流,和文件类型:StringEntity,ByteArrayEntity,InputStreamEntity,FileEntity。
File file = new File("somefile.txt");
FileEntity entity = new FileEntity(file,
ContentType.create("text/plain", "UTF-8"));

HttpPost httppost = new HttpPost("http://localhost/action.do");
httppost.setEntity(entity);

xxxxxxxxxx
6
 
1
File file = new File("somefile.txt");
2
FileEntity entity = new FileEntity(file, 
3
    ContentType.create("text/plain", "UTF-8"));        
4
 
5
HttpPost httppost = new HttpPost("http://localhost/action.do");
6
httppost.setEntity(entity);
  • 请注意由于 InputStreamEntity 只能从下层的数据流中读取一次,所以它是不能重复的。推荐,通过继承 HttpEntity 这个自包含的类来自定义HttpEntity 类,而不是直接使用 InputStreamEntity 这个类。FileEntity 就是一个很好的起点(FileEntity 就是继承的 HttpEntity)。
  • 模拟 HTML 表单提交
List<NameValuePair> formparams = new ArrayList<NameValuePair>();
formparams.add(new BasicNameValuePair("param1", "value1"));
formparams.add(new BasicNameValuePair("param2", "value2"));
UrlEncodedFormEntity entity = new UrlEncodedFormEntity(formparams, Consts.UTF_8);
HttpPost httppost = new HttpPost("http://localhost/handler.do");
httppost.setEntity(entity);
xxxxxxxxxx
6
 
1
List<NameValuePair> formparams = new ArrayList<NameValuePair>();
2
formparams.add(new BasicNameValuePair("param1", "value1"));
3
formparams.add(new BasicNameValuePair("param2", "value2"));
4
UrlEncodedFormEntity entity = new UrlEncodedFormEntity(formparams, Consts.UTF_8);
5
HttpPost httppost = new HttpPost("http://localhost/handler.do");
6
httppost.setEntity(entity);

  • 设置传输编码方式(1.0不支持)
StringEntity entity = new StringEntity("important message",
ContentType.create("plain/text", Consts.UTF_8));
entity.setChunked(true);
HttpPost httppost = new HttpPost("http://localhost/acrtion.do");
httppost.setEntity(entity);
xxxxxxxxxx
 
1
StringEntity entity = new StringEntity("important message",
2
        ContentType.create("plain/text", Consts.UTF_8));
3
entity.setChunked(true);
4
HttpPost httppost = new HttpPost("http://localhost/acrtion.do");
5
httppost.setEntity(entity);

  • 处理http响应的方法就是使用ResponseHandler接口,这个接口中有handleResponse(HttpResponse response)方法。使用这个方法,用户完全不用关心http连接管理器。当使用ResponseHandler时,HttpClient会自动地将Http连接释放给Http管理器,即使http请求失败了或者抛出了异常。
CloseableHttpClient httpclient = HttpClients.createDefault();
HttpGet httpget = new HttpGet("http://localhost/json");

ResponseHandler<MyJsonObject> rh = new ResponseHandler<MyJsonObject>() {

@Override
public JsonObject handleResponse(
final HttpResponse response) throws IOException {
StatusLine statusLine = response.getStatusLine();
HttpEntity entity = response.getEntity();
if (statusLine.getStatusCode() >= 300) {
throw new HttpResponseException(
statusLine.getStatusCode(),
statusLine.getReasonPhrase());
}
if (entity == null) {
throw new ClientProtocolException("Response contains no content");
}
Gson gson = new GsonBuilder().create();
ContentType contentType = ContentType.getOrDefault(entity);
Charset charset = contentType.getCharset();
Reader reader = new InputStreamReader(entity.getContent(), charset);
return gson.fromJson(reader, MyJsonObject.class);
}
};
MyJsonObject myjson = client.execute(httpget, rh);

xxxxxxxxxx
26
 
1
CloseableHttpClient httpclient = HttpClients.createDefault();
2
HttpGet httpget = new HttpGet("http://localhost/json");
3
 
4
ResponseHandler<MyJsonObject> rh = new ResponseHandler<MyJsonObject>() {
5
 
6
    @Override
7
    public JsonObject handleResponse(
8
            final HttpResponse response) throws IOException {
9
        StatusLine statusLine = response.getStatusLine();
10
        HttpEntity entity = response.getEntity();
11
        if (statusLine.getStatusCode() >= 300) {
12
            throw new HttpResponseException(
13
                    statusLine.getStatusCode(),
14
                    statusLine.getReasonPhrase());
15
        }
16
        if (entity == null) {
17
            throw new ClientProtocolException("Response contains no content");
18
        }
19
        Gson gson = new GsonBuilder().create();
20
        ContentType contentType = ContentType.getOrDefault(entity);
21
        Charset charset = contentType.getCharset();
22
        Reader reader = new InputStreamReader(entity.getContent(), charset);
23
        return gson.fromJson(reader, MyJsonObject.class);
24
    }
25
};
26
MyJsonObject myjson = client.execute(httpget, rh);
































 

HttpClient 该知道一些概念的更多相关文章

  1. HttpClient学习之 客户端HTTP编程入门

    说明 本文存在的原因,是想深入的学习下HttpClient.对应的网址是: http://hc.apache.org/httpcomponents-client-4.5.x/primer.html h ...

  2. Vert.x学习之 Web Client

    Vert.x Web Client 原文档 组件源码 组件示例 中英对照表 Pump:泵(平滑流式数据读入内存的机制,防止一次性将大量数据读入内存导致内存溢出) Response Codec:响应编解 ...

  3. Java 爬虫遇到需要登录的网站,该怎么办?

    这是 Java 网络爬虫系列博文的第二篇,在上一篇 Java 网络爬虫,就是这么的简单 中,我们简单的学习了一下如何利用 Java 进行网络爬虫.在这一篇中我们将简单的聊一聊在网络爬虫时,遇到需要登录 ...

  4. HttpClientFactory-向外请求的最佳

    简介 它的组件包是Microsoft.Extensions.Http 复原HttpClient带来的问题 HttpClient相关问题 虽然HttpClient类实现了IDisposable,但不是首 ...

  5. 爬虫概念与编程学习之如何爬取视频网站页面(用HttpClient)(二)

    先看,前一期博客,理清好思路. 爬虫概念与编程学习之如何爬取网页源代码(一) 不多说,直接上代码. 编写代码 运行 <!DOCTYPE html><html><head& ...

  6. 揭秘Windows10 UWP中的httpclient接口[2]

    阅读目录: 概述 如何选择 System.Net.Http Windows.Web.Http HTTP的常用功能 修改http头部 设置超时 使用身份验证凭据 使用客户端证书 cookie处理 概述 ...

  7. 大叔也说Xamarin~Android篇~为HttpClient共享Session,android与api的session共享机制

    回到目录 杂谈 在进行android进行开发时,我们的数据一般通过接口来获收,这里指的接口泛指web api,webservice,wcf,web应用程序等:它们做为服务端与数据库进行直接通讯,而AP ...

  8. [Android] HttpURLConnection & HttpClient & Socket

    Android的三种网络联接方式 1.标准Java接口:java.net.*提供相关的类//定义地址URL url = new URL("http://www.google.com" ...

  9. Android系列之网络(一)----使用HttpClient发送HTTP请求(通过get方法获取数据)

    [声明] 欢迎转载,但请保留文章原始出处→_→ 生命壹号:http://www.cnblogs.com/smyhvae/ 文章来源:http://www.cnblogs.com/smyhvae/p/4 ...

随机推荐

  1. MapReduce深入理解输入和输出格式(1)-输入分片与记录

    一个输入分片( in put split)就是能够被单个map 操作 处理的输入块. 每一个map 操作只处理一个输入分片,并且一个一个地处理每条记录,也就是一个键/值对.输入分片和记录都是逻辑上的, ...

  2. JZOJ100045 【NOIP2017提高A组模拟7.13】好数

    题目 题目大意 首先有一个定义: 对于一个数,如果和它互质的数可以组成一个等差数列,那么这个数叫"好数". 现在给你一个数列,有三种操作: 1.询问一段区间内的好数的个数. 2.将 ...

  3. Mysql8+mybatisGenerator (mysql 8的逆向工程)

    最近试了一下mysql8的逆向工程工具 1.xml <?xml version="1.0" encoding="UTF-8" ?> <!DOC ...

  4. DataLakeAnalytics: 解析IP地址对应的国家城市地址的能力

    Data Lake Analytics 作为云上数据处理的枢纽,最近加入了通过IP地址查找对应的国家.省份.城市.ISP的函数, 今天带大家体验一下. 函数详细介绍 本次一共添加了下面这些函数: ip ...

  5. Trie树 模板

    普通Trie: struct TRIE{ ],tot,end[MAXN]; TRIE(){tot=;} void insert(char *s){//s为要插入的字符串 int len=strlen( ...

  6. node概览和安装

    一.node是一个平台环境,可以运行js代码的服务器端平台. 设计最初node是用来解决并发问题的,现在可以用来放在服务端使用. node平台的有优点:运行速度快,支持高并发,轻便.小巧 但是与jav ...

  7. sqlserver数据往别的数据库迁移

    背景:sqlserver数据库数据是服务于一个.net项目.后来由于去.net 要将数据前往高斯数据库 或者Oracle. 问题是 当sql Name Age Gender from student ...

  8. require模块开发(一)

    1.require下载和加载 1.1 下载 工欲善其事必先利其器,先下载require.js下载地址, 然后添加 require.js 到 scripts 目录 1.2 加载 然后加载require ...

  9. LA2238 Fixed Partition Memory Management

    题目大意: m(m<=10)个内存区域,n(n<=50)个程序.找出一个方案来,使得平均结束时刻尽量小.题目保证有解. 同一个程序运行在不同大小的内存区域内,其运行时间不同.(注意,这里说 ...

  10. CI框架 - Xhprof性能监控,用钩子hooks实现

    安装Xhprof参考:http://www.cnblogs.com/qq917937712/p/8889001.html 第一步:配置config.php $config['enable_hooks' ...