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. Ajax请求Session超时解决

    web前端js代码: $.ajaxSetup({ contentType : "application/x-www-form-urlencoded;charset=utf-8", ...

  2. PHP简单实现“相关文章推荐”功能的方法(此方法不是自创)

    1, 所用的函数:int similar_text ( string $first, string $second[, float $percent] ) 利用similar_text将这些文章标题同 ...

  3. Django项目:CRM(客户关系管理系统)--80--70PerfectCRM实现CRM业务流程(bpm)课程排行分页

    # coursetop_views.py # ————————64PerfectCRM实现CRM课程排名详情———————— #————班级学生详情——#计算#{学员ID:分数}——#计算 #{学员I ...

  4. iframe加载完成事件

    var iframe = document.createElement("iframe"); iframe.src = "http://www.jb51.net" ...

  5. Filter - 过滤敏感词汇(动态代理)

    /** * 敏感词汇过滤器 */ @WebFilter("/*") public class SensitiveWordsFilter implements Filter { pu ...

  6. 【DM642学习笔记五】FVID驱动模型 API函数

    1.FVID_control 作用:发送一个控制命令到mini_driver 语法: status = FVID_control(fvidChan, cmd, args); 参数: FVID_Hand ...

  7. sort方法

    作用:对列表进行排序 >>> spam=[2,5,3,14,1,-7] >>> spam.sort() >>> spam [-7, 1, 2, 3 ...

  8. android 数据绑定(1)Ativity、Fragment、Item绑定数据源

    1.简介 官方文档:  https://developer.android.com/topic/libraries/data-binding 官方示例: https://github.com/andr ...

  9. Django项目:CRM(客户关系管理系统)--51--42PerfectCRM实现AJAX全局账号注册

    #urls.py """PerfectCRM URL Configuration The `urlpatterns` list routes URLs to views. ...

  10. 策略模式(Strategy)(策略类,场景不同策略不同,环境策略分离组合,)

    (定义一组算法,将每个算法都封装起来,并且使它们之间可以互换.)   例:button 与 listener ,在使用时具体根据情况实例化listener,做不同的操作. 背景 在软件开发中常常遇到这 ...