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. AIO异步非阻塞学习

    Client:客户端 package aio; import java.io.UnsupportedEncodingException; import java.net.InetSocketAddre ...

  2. 如何在Mac上切换python2和python3以及下载安装包 & 在Mac上如何查找系统自带python2.7的路径

    电脑:系统是Mac OS  系统自带python2.7  自己下载安装了python3.6 问题:一开始我想在终端下执行python2的相关代码   例如 python kNN.py (kNN.py这 ...

  3. Apache 禁用IP 访问 和 HTTP 跳转 HTTPS

    如果需要 禁用IP 访问并且 需要 HTTP 跳转到 HTTPS <VirtualHost *:80> ServerName xxx.xxx.com RewriteEngine On Re ...

  4. 免费提取百度文库 doc 文件

    首先说明,今天要推荐的这款软件,不能不能不能免费提取百度文库里 PDF 格式的文件. 对于其他的格式,无论收费与否都能免费提取. 只是口头说说免不了耍流氓的嫌疑,举栗如下: 百度文库里<喜迎党的 ...

  5. oracel 管理维护

    共享池中的缓存: 绑定变量是一种优化执行的方式. lgwr 重做日志进程dbwr 数据写进程smon 系统监督进程pmon 进程监督进程ckpt 校验点进程 arch 归档日志进程 spool 命令可 ...

  6. spring整合http

    本文版权归作者所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接出处:https://blog.csdn.net/qq_3076499,否则保留追究法律责任的权利. 如果 ...

  7. Vue设置element的dialog

    1.设置css:参考https://www.jianshu.com/p/a3eb60b75b92 <style> .el-dialog { max-height: 600px; displ ...

  8. Docker(四)安装Redis

    1.安装redis https://blog.csdn.net/qq_29917523/article/details/78019511 2.测试连接

  9. DevCloud会员权益升级!日常领码豆,轻松换好礼!

    为了回馈每一位用户的使用和支持, 华为云DevCloud上线了会员中心, 大家在会员中心可以通过完成任务赚取码豆, 并在兑换商城兑换精美礼品. 如何通过任务获得码豆? 我们为大家准备了各种日常任务, ...

  10. Delphi 设计模式:《HeadFirst设计模式》Delphi7代码---状态模式[转]

    {没有应用状态模式的代码} //工程文件 program Project1; {$APPTYPE CONSOLE} uses  uGumballMachine in 'uGumballMachine. ...