(第一章 上)
前言
超文本传输协议(HTTP)也许是当今互联网上使用的最重要的协议了。Web服务,有网络功能的设备和网络计算的发展,都持续扩展了HTTP协议的角色,超越了用户使用的Web浏览器范畴,同时,也增加了需要HTTP协议支持的应用程序的数量。
尽管java.net包提供了基本通过HTTP访问资源的功能,但它没有提供全面的灵活性和其它很多应用程序需要的功能。HttpClient就是寻求弥补这项空白的组件,通过提供一个有效的,保持更新的,功能丰富的软件包来实现客户端最新的HTTP标准和建议。
为扩展而设计,同时为基本的HTTP协议提供强大的支持,HttpClient组件也许就是构建HTTP客户端应用程序,比如web浏览器,web服务端,利用或扩展HTTP协议进行分布式通信的系统的开发人员的关注点。
1. HttpClient的范围基于HttpCore[http://hc.apache.org/httpcomponents-core/index.html]的客户端HTTP运输实现库
基于经典(阻塞)I/O
内容无关
2. 什么是HttpClient不能做的HttpClient不是一个浏览器。它是一个客户端的HTTP通信实现库。HttpClient的目标是发送和接收HTTP报文。 HttpClient不会去缓存内容,执行嵌入在HTML页面中的javascript代码,猜测内容类型,重新格式化请求/重定向URI,或者其它和 HTTP运输无关的功能。
第一章 基础1.1 执行请求HttpClient最重要的功能是执行HTTP方法。一个HTTP方法的执行包含一个或多个HTTP请求/HTTP响应交换,通常由 HttpClient的内部来处理。而期望用户提供一个要执行的请求对象,而HttpClient期望传输请求到目标服务器并返回对应的响应对象,或者当执行不成功时抛出异常。
很自然地,HttpClient API的主要切入点就是定义描述上述规约的HttpClient接口。
这里有一个很简单的请求执行过程的示例:
HttpClient httpclient = new DefaultHttpClient();
HttpGet httpget = new HttpGet("http://localhost/");
HttpResponse response = httpclient.execute(httpget);
HttpEntity entity = response.getEntity();
if (entity != null) {
InputStream instream = entity.getContent();
int l;
byte[] tmp = new byte[2048];
while ((l = instream.read(tmp)) != -1) {
}
}
1.1.1 HTTP请求所有HTTP请求有一个组合了方法名,请求URI和HTTP协议版本的请求行。
HttpClient支持所有定义在HTTP/1.1版本中的HTTP方法:GET,HEAD,POST,PUT,DELETE,TRACE和 OPTIONS。对于每个方法类型都有一个特殊的类:HttpGet,HttpHead,HttpPost,HttpPut,HttpDelete,HttpTrace和HttpOptions。
请求的URI是统一资源定位符,它标识了应用于哪个请求之上的资源。HTTP请求URI包含一个协议模式,主机名称,可选的端口,资源路径,可选的查询和可选的片段。
HttpGet httpget = new HttpGet(
"http://www.google.com/search?hl=en&q=httpclient&btnG=Google+Search&aq=f&oq=");
HttpClient提供很多工具方法来简化创建和修改执行URI。
URI也可以编程来拼装:
URI uri = URIUtils.createURI("http", "www.google.com", -1, "/search",
"q=httpclient&btnG=Google+Search&aq=f&oq=", null);
HttpGet httpget = new HttpGet(uri);
System.out.println(httpget.getURI());
输出内容为:
http://www.google.com/search?q=httpclient&btnG=Google+Search&aq=f&oq=
查询字符串也可以从独立的参数中来生成:
List<NameValuePair> qparams = new ArrayList<NameValuePair>();
qparams.add(new BasicNameValuePair("q", "httpclient"));
qparams.add(new BasicNameValuePair("btnG", "Google Search"));
qparams.add(new BasicNameValuePair("aq", "f"));
qparams.add(new BasicNameValuePair("oq", null));
URI uri = URIUtils.createURI("http", "www.google.com", -1, "/search",
URLEncodedUtils.format(qparams, "UTF-8"), null);
HttpGet httpget = new HttpGet(uri);
System.out.println(httpget.getURI());
输出内容为:
http://www.google.com/search?q=httpclient&btnG=Google+Search&aq=f&oq=
1.1.2 HTTP响应HTTP响应是由服务器在接收和解释请求报文之后返回发送给客户端的报文。响应报文的第一行包含了协议版本,之后是数字状态码和相关联的文本段。
HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1,
HttpStatus.SC_OK, "OK");
System.out.println(response.getProtocolVersion());
System.out.println(response.getStatusLine().getStatusCode());
System.out.println(response.getStatusLine().getReasonPhrase());
System.out.println(response.getStatusLine().toString());
输出内容为:
HTTP/1.1
200
OK
HTTP/1.1 200 OK
1.1.3 处理报文头部一个HTTP报文可以包含很多描述如内容长度,内容类型等信息属性的头部信息。
HttpClient提供获取,添加,移除和枚举头部信息的方法。
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\"");
Header h1 = response.getFirstHeader("Set-Cookie");
System.out.println(h1);
Header h2 = response.getLastHeader("Set-Cookie");
System.out.println(h2);
Header[] hs = response.getHeaders("Set-Cookie");
System.out.println(hs.length);
输出内容为:
Set-Cookie: c1=a; path=/; domain=localhost
Set-Cookie: c2=b; path="/", c3=c; domain="localhost"
获得给定类型的所有头部信息最有效的方式是使用HeaderIterator接口。
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\"");
HeaderIterator it = response.headerIterator("Set-Cookie");
while (it.hasNext()) {
System.out.println(it.next());
}
输出内容为:
Set-Cookie: c1=a; path=/; domain=localhost
Set-Cookie: c2=b; path="/", c3=c; domain="localhost"
它也提供解析HTTP报文到独立头部信息元素的方法方法。
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);
}
}
输出内容为:
c1 = a
path=/
domain=localhost
c2 = b
path=/
c3 = c
domain=localhost
1.1.4 HTTP实体HTTP报文可以携带和请求或响应相关的内容实体。实体可以在一些请求和响应中找到,因为它们也是可选的。使用了实体的请求被称为封闭实体请求。 HTTP规范定义了两种封闭实体的方法:POST和PUT。响应通常期望包含一个内容实体。这个规则也有特例,比如HEAD方法的响应和204 No Content,304 Not Modified和205 Reset Content响应。
HttpClient根据其内容出自何处区分三种类型的实体:
streamed流式:内容从流中获得,或者在运行中产生。特别是这种分类包含从HTTP响应中获取的实体。流式实体是不可重复生成的。
self-contained自我包含式:内容在内存中或通过独立的连接或其它实体中获得。自我包含式的实体是可以重复生成的。这种类型的实体会经常用于封闭HTTP请求的实体。
wrapping包装式:内容从另外一个实体中获得。
当从一个HTTP响应中获取流式内容时,这个区别对于连接管理很重要。对于由应用程序创建而且只使用HttpClient发送的请求实体,流式和自我包含式的不同就不那么重要了。这种情况下,建议考虑如流式这种不能重复的实体,和可以重复的自我包含式实体。
1.1.4.1 重复实体实体可以重复,意味着它的内容可以被多次读取。这就仅仅是自我包含式的实体了(像ByteArrayEntity或StringEntity)。
1.1.4.2 使用HTTP实体因为一个实体既可以代表二进制内容又可以代表字符内容,它也支持字符编码(支持后者也就是字符内容)。
实体是当使用封闭内容执行请求,或当请求已经成功执行,或当响应体结果发功到客户端时创建的。
要从实体中读取内容,可以通过HttpEntity#getContent()方法从输入流中获取,这会返回一个 java.io.InputStream对象,或者提供一个输出流到HttpEntity#writeTo(OutputStream)方法中,这会一次返回所有写入到给定流中的内容。
当实体通过一个收到的报文获取时,HttpEntity#getContentType()方法和 HttpEntity#getContentLength()方法可以用来读取通用的元数据,如Content-Type和Content-Length 头部信息(如果它们是可用的)。因为头部信息Content-Type可以包含对文本MIME类型的字符编码,比如text/plain或text /html,HttpEntity#getContentEncoding()方法用来读取这个信息。如果头部信息不可用,那么就返回长度-1,而对于内容类型返回NULL。如果头部信息Content-Type是可用的,那么就会返回一个Header对象。
当为一个传出报文创建实体时,这个元数据不得不通过实体创建器来提供。
StringEntity myEntity = new StringEntity("important message",
"UTF-8");
System.out.println(myEntity.getContentType());
System.out.println(myEntity.getContentLength());
System.out.println(EntityUtils.getContentCharSet(myEntity));
System.out.println(EntityUtils.toString(myEntity));
System.out.println(EntityUtils.toByteArray(myEntity).length);
输出内容为
Content-Type: text/plain; charset=UTF-8
17
UTF-8
important message
17
1.1.5 确保低级别资源释放当完成一个响应实体,那么保证所有实体内容已经被完全消耗是很重要的,所以连接可以安全的放回到连接池中,而且可以通过连接管理器对后续的请求重用连接。处理这个操作的最方便的方法是调用HttpEntity#consumeContent()方法来消耗流中的任意可用内容。HttpClient 探测到内容流尾部已经到达后,会立即会自动释放低层连接,并放回到连接管理器。HttpEntity#consumeContent()方法调用多次也是安全的。
也可能会有特殊情况,当整个响应内容的一小部分需要获取,消耗剩余内容而损失性能,还有重用连接的代价太高,则可以仅仅通过调用HttpUriRequest#abort()方法来中止请求。
HttpGet httpget = new HttpGet("http://localhost/");
HttpResponse response = httpclient.execute(httpget);
HttpEntity entity = response.getEntity();
if (entity != null) {
InputStream instream = entity.getContent();
int byteOne = instream.read();
int byteTwo = instream.read();
// Do not need the rest
httpget.abort();
}
连接不会被重用,但是由它持有的所有级别的资源将会被正确释放。
1.1.6 消耗实体内容推荐消耗实体内容的方式是使用它的HttpEntity#getContent()或 HttpEntity#writeTo(OutputStream)方法。HttpClient也自带EntityUtils类,这会暴露出一些静态方法,这些方法可以更加容易地从实体中读取内容或信息。代替直接读取java.io.InputStream,也可以使用这个类中的方法以字符串/字节数组的形式获取整个内容体。然而,EntityUtils的使用是强烈不鼓励的,除非响应实体源自可靠的HTTP服务器和已知的长度限制。
HttpGet httpget = new HttpGet("http://localhost/");
HttpResponse response = httpclient.execute(httpget);
HttpEntity entity = response.getEntity();
if (entity != null) {
long len = entity.getContentLength();
if (len != -1 && len < 2048) {
System.out.println(EntityUtils.toString(entity));
} else {
// Stream content out
}
}
在一些情况下可能会不止一次的读取实体。此时实体内容必须以某种方式在内存或磁盘上被缓冲起来。最简单的方法是通过使用BufferedHttpEntity类来包装源实体完成。这会引起源实体内容被读取到内存的缓冲区中。在其它所有方式中,实体包装器将会得到源实体。
HttpGet httpget = new HttpGet("http://localhost/");
HttpResponse response = httpclient.execute(httpget);
HttpEntity entity = response.getEntity();
if (entity != null) {
entity = new BufferedHttpEntity(entity);
}
1.1.7 生成实体内容HttpClient提供一些类,它们可以用于生成通过HTTP连接获得内容的有效输出流。为了封闭实体从HTTP请求中获得的输出内容,那些类的实例可以和封闭如POST和PUT请求的实体相关联。HttpClient为很多公用的数据容器,比如字符串,字节数组,输入流和文件提供了一些类:StringEntity,ByteArrayEntity,InputStreamEntity和FileEntity。
File file = new File("somefile.txt");
FileEntity entity = new FileEntity(file, "text/plain; charset=\"UTF-8\"");
HttpPost httppost = new HttpPost("http://localhost/action.do");
httppost.setEntity(entity);
请注意InputStreamEntity是不可重复的,因为它仅仅能从低层数据流中读取一次内容。通常来说,我们推荐实现一个定制的 HttpEntity类,这是自我包含式的,用来代替使用通用的InputStreamEntity。FileEntity也是一个很好的起点。
1.1.7.1 动态内容实体通常来说,HTTP实体需要基于特定的执行上下文来动态地生成。通过使用EntityTemplate实体类和ContentProducer接口,HttpClient提供了动态实体的支持。内容生成器是按照需求生成它们内容的对象,将它们写入到一个输出流中。它们是每次被请求时来生成内容。所以用EntityTemplate创建的实体通常是自我包含而且可以重复的。
ContentProducer cp = new ContentProducer() {
public void writeTo(OutputStream outstream) throws IOException {
Writer writer = new OutputStreamWriter(outstream, "UTF-8");
writer.write("<response>");
writer.write(" <content>");
writer.write(" important stuff");
writer.write(" </content>");
writer.write("</response>");
writer.flush();
}
};
HttpEntity entity = new EntityTemplate(cp);
HttpPost httppost = new HttpPost("http://localhost/handler.do");
httppost.setEntity(entity);

转载于:https://www.cnblogs.com/astroboyx/archive/2011/09/20/2739850.html

httpclient4 中文版帮助文档,最新官方版翻译版(第一章 上)相关推荐

  1. 服务器安装360文档卫士,360文档卫士官方版_360文档卫士详细使用方法

    在我们进行文档编辑的过程中,经常会遇到一些木马或者病毒对文档窃取,怎样有效的保证这些文档信息的安全呢?360文档卫士是由官方推出的一种专门针对于敲诈作者病毒开发的专业性工具.更多软件咨询体验,请前往Q ...

  2. python3 chm文档下载_python3.7.0官方参考文档 最新api文档 chm_Python教程_源雷技术空间...

    资源名称:python3.7.0官方参考文档 最新api文档 chm 1.新语法特性: PEP 563, 推迟评估类型注释 2.向后不兼容语法更改: async 和 await 现在保留关键字 3.新 ...

  3. 英文VS2010安装中文版MSDN文档方法

    在2010年4月12号发布Visual Studio 2010 and .NET 4正式版.5月26日微软发布了Visual Studio 2010 and .NET 4 RTM中文版,我们还是喜欢使 ...

  4. win10系统下载中文版 64位32位 官方版​

    win10系统下载中文版 64位&32位 官方版 软件大小:4.9GB 软件语言:简体中文 软件类别:操作系统 软件授权:官方版 更新时间:2015-01-22 应用平台:/Win8/Win7 ...

  5. android11用石墨文档,轻协作 | 石墨文档 for Android 版轻体验

    前几天喜闻石墨文档终于推出 Android 版本,算是全面支持 ios.Android 和 web 平台.身为 Android 用户,可以告别体验不佳的 web 端,下面为大家送上石墨文档 for A ...

  6. AKKA文档(java版)——准备开始

     http://ifeve.com/akka-doc-java-getting-started/ AKKA文档(java版)--准备开始 原文:http://doc.akka.io/docs/ak ...

  7. grasshop 犀牛5.0下载_神契幻奇谭 v1.129版发布 快来下载神契幻奇谭2020最新官方版...

    全文导读 下载神契幻奇谭就上高手游,神契幻奇谭是一款具有二次元.烧脑特征的角色扮演手机游戏,最让人难忘的是精致生动的形象设计系统和宏大的剧情,平平淡淡还是揭竿而起,传奇史诗由您亲自谱写!神契幻奇谭日前 ...

  8. (征求意见稿)中国银河证券公募基金分类体系规则文档 (2019版)

    (征求意见稿)中国银河证券公募基金分类体系规则文档 (2019版) 银河证券基金研究中心 4天前 备注说明:2019版基金分类体系(征求意见稿)从2018年12月5日开始进行一个月的征求意见,欢迎基金 ...

  9. Servlet中文API文档-个人整理版

    Servlet中文API文档-个人整理版 一.Servlet 说明:servlet抽象集是javax.servlet.Servlet接口,它规定了必须由Servlet类实现由servlet引擎识别和管 ...

最新文章

  1. 保证你现在和未来不失业的10种关键技【转载】
  2. TensorFlow练习27: 验证码生成器-从文本生成图像
  3. CART决策树(分类回归树)分析及应用建模
  4. 【IOS】获取顶层UIViewController
  5. 四章: CentOS6.5 配置连接Windows远程桌面、创建新用户、禁用root在本地或远程使用ssh登录
  6. 用tf-faster-rcnn训练自己制作的车牌号数据集(VOC2007格式)
  7. 在tomcat上全手工部署Servlet3.0
  8. php mongo 类,mongo php类
  9. mask rcnn算法分析_实例分割综述(单阶段/两阶段/实时分割算法汇总)
  10. 线程范围内的线程共享(多线程)
  11. 软件工程实验二Visio的使用
  12. windows7安装ffmpeg教程
  13. 北京交通大学计算机学院 于剑,北京交通大学计算机与信息技术学院硕导介绍:于剑...
  14. 爬虫需谨慎,你不知道的爬虫与反爬虫套路!
  15. UE4 键盘控制开关灯
  16. 谷歌浏览器播放器声音
  17. iOS 2020 开发者账号 身份验证步骤
  18. [组合数学] NC13611树 (逆元的计算)
  19. c语言 关键字volatile和register
  20. AD19 基础应用技巧(快速定义PCB板框,CAD中DWG转DXF格式导入)

热门文章

  1. session.merge 缓存不更新_这几个缓存更新的设计你都知道吗?
  2. vue 2个方法先后执行_4个简单靠谱的所得税节税方法,老板看完都批示财务执行...
  3. Warning: POST Content-Length of 29328854 bytes exceeds the limit of 8388608 bytes in Unknown on line
  4. 《美团编程题》丢失的三个数
  5. Pycharn比较好的配色方案
  6. 安装hadoop2.6.0伪分布式环境
  7. Scala入门到精通—— 第二节Scala基本类型及操作、程序控制结构
  8. dojo 的DOM操作 dojo/dom
  9. elasticsearch api中的Delete By Query API操作
  10. LRU算法四种实现方式介绍