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. VIsualSVN server 安装及旧仓库导入

    安装参考: 1,  http://www.cnblogs.com/xiaobaihome/archive/2012/03/20/2407610.html SVN服务器搭建和使用(一) Subversi ...

  2. CodeForces 232C Doe Graphs(分治+搜索)

    CF232C Doe Graphs 题意 题意翻译 \(Doe\)以她自己的名字来命名下面的无向图 \(D(0)\)是只有一个编号为\(1\)的结点的图. \(D(1)\)是只有两个编号分别为\(1\ ...

  3. 【核心核心】4.Spring【IOC】注解方式

    1.导入jar包 2.创建对应的类 public interface HelloService { public void sayHello(); } /** * @Component(value=& ...

  4. phpqrcode.php 生成二维码图片用于推广

    <?php /* * PHP QR Code encoder * * This file contains MERGED version of PHP QR Code library. * It ...

  5. 第四章 Odoo 12 开发之模块继承

    Odoo 的一个强大功能是无需直接修改底层对象就可以添加功能.这是通过其继承机制来实现的,采取在已有对象之上修改层来完成.这种修改可以在不同层上进行-模型层.视图层和业务逻辑层.我们创建新的模块来做出 ...

  6. VS2012与windos版本不兼容问题

    昨天晚上加完班,想着把windows更新下.今天上午就发现再运行VS报错了,提示VS2012与windows版本不兼容,打开.sln文件后,VS自动关闭.错误如下: 查看后网上提示安装VS2012的一 ...

  7. spring cloud深入学习(十一)-----服务网关zuul

    前面的文章我们介绍了,Eureka用于服务的注册于发现,Feign支持服务的调用以及均衡负载,Hystrix处理服务的熔断防止故障扩散,Spring Cloud Config服务集群配置中心,似乎一个 ...

  8. Jmeter设置中文汉化

    下载汉化包logkit-2.0.jar 将汉化包copy至 jmeter文件的lib目录下 打开Jmeter软件,设置汉化包 Options  ->  ChooseLanguage  -> ...

  9. Spinrg WebFlux中Cookie的读写

    WebFLux与WebMvc的差异 WebFlux读写Cookie不像WebMvc那么直接,最主要的原因是WebMvc是基于Servlet规范的,而WebFlux仅仅遵守的是HTTP协议.所以在使用的 ...

  10. KOA 学习(八) koa-bodyparser

    此控件支持Josn,form,text类型 用法 var Koa = require('koa'); var bodyParser = require('koa-bodyparser'); var a ...