您的位置:首页 > 理论基础 > 计算机网络

学习ApacheHttpComponents,HttpCore第一部分,基本翻译官方教程

2013-12-12 14:03 591 查看


前言

在Java领域,谈到网络编程,如果是NB人物,脑海里第一反应就是MINA,NETTY,GRIZZLY等优秀的开源框架。

MINA:Apache MINA(Multipurpose Infrastructure for Network Applications) 是 Apache 组织一个较新的项目,它为开发高性能和高可用性的网络应用程序提供了非常便利的框架。当前发行的 MINA 版本支持基于 Java NIO 技术的 TCP/UDP 应用程序开发、串口通讯程序(只在最新的预览版中提供),MINA 所支持的功能也在进一步的扩展中。授权协议:
Apache 开发语言: Java
Netty是由JBOSS提供的一个java开源框架。Netty提供异步的、事件驱动的网络应用程序框架和工具,用以快速开发高性能、高可靠性的网络服务器和客户端程序。
Grizzly是一种应用程序框架,专门解决编写成千上万用户访问服务器时候产生的各种问题。使用JAVA NIO作为基础,并隐藏其编程的复杂性。容易使用的高性能的API。带来非阻塞socketd到协议处理层。利用高性能的缓冲和缓冲管理使用高性能的线程池.

上面看看而已,对于刚接触网络编程的人来说,最原始最底层的才是最重要的.自然最先的是java.net.*类库.HTTP协议方面的知识.

然后Apache的HttpComponents很不错吧,用的人很多,现在我学的就是HttpComponents.

Apache的各个技术的新旧影响觉得不是非常大,没JBOSS的一些技术换个版本技术感觉大变样一样.各个类名都变化无常的.所以我也经常吐槽JBOSS那帮家伙就是喜欢吹牛逼.现在的公司一帮子东西都是JBOSS...我说实话感觉头大.其实最主要还是自己英语垃圾....哎.....跑题了.

HttpComponents已经是Apache的顶级项目了,它旨在为我们提供一个Http协议相关的Java平台工具集。超文本传输协议 (HTTP) 也许是今天在因特网上使用的最重要协议。HttpComponents就专门搞这个的.

HttpComponents结构

1.HttpComponents Core

HttpCore是一组低级别的HTTP传输组件,可用于构建自定义的客户端和服务器端的HTTP服务,以最小的足迹。 HttpCore支持两种I/O模式:阻塞I/O模型的基础上经典的Java I/O和非阻塞的,事件驱动的I/O模型的基础上的Java NIO。
阻塞 I/O 模型可能更适合于数据密集型、 低延迟的方案,而非阻塞模型可能适用于高延迟情况,原始数据吞吐量不是那么重要,但又要处理成千上万的数据量.
HttpCore Examples: http://hc.apache.org/httpcomponents-core-ga/examples.html
2.HttpComponents Client

HttpClient是 HTTP/1.1 兼容的 HTTP 代理实现,基于 HttpCore。它还提供可重用的组件,客户端的身份验证、 HTTP 状态管理,和 HTTP 连接管理。

HttpClient Examples:http://hc.apache.org/httpcomponents-client-ga/examples.html

3.HttpComponents AsyncClien

异步HttpClient的是一个HTTP/1.1兼容的HTTP代理实现基于HttpCore NIO和HttpClient的组成部分。这是一个互补模块,用于特殊情况下的Apache的HttpClient,处理大量的并发连接的原始数据吞吐量比性能更重要。

HttpCore 教程

前言

HttpCore 是一套的组件执行的最基本的方面. 1.提供一致的 API,用于构建客户端/代理服务器/服务器端 HTTP 服务.2.提供一致的 API 构建同步和异步 HTTP 服务. 3.本身是基于阻塞 (经典) 和非阻塞 (NIO) I/O 模型的一组低级别的组件.

2.HttpCore 目标

1.提供最基本的 HTTP 传输方面的执行情况
2.提供良好的性能及清晰度和表现力的API之间的平衡
3.内存占用量小
4.不依赖外部jar包

第1章 基本

1.1 HTTP 消息

1.结构

第一部分叫Request line, 第二部分叫Request header, 第三部分是body. header和body之间有个空行.

HttpCore 定义要密切注视这一定义的 HTTP 消息对象模型,并为 (格式) 序列化和反序列化 (解析) 的 HTTP 消息元素提供广泛的支持。

2.基本操作

1.1.2.1.HTTP 请求消息

HTTP 请求是从客户端发送到服务器的消息。该消息的第一行包含要应用于资源,该资源,和使用的协议版本标识符的方法。

HttpRequest request = new BasicHttpRequest("GET", "/",HttpVersion.HTTP_1_1);

System.out.println(request.getRequestLine().getMethod());

System.out.println(request.getRequestLine().getUri());

System.out.println(request.getProtocolVersion());

System.out.println(request.getRequestLine().toString());

输出

GET

/

HTTP/1.1

GET / HTTP/1.1

1.1.2.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.2.3 HTTP 消息常用属性和方法

HTTP 消息可以包含一系列描述消息属性 (如内容长度标头,内容类型,等等。HttpCore 提供的方法来检索、 添加、 删除和枚举此类标头。

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"

2

有有效的方法,以获取给定的类型,使用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[i]);

}

c1 = a

path=/

domain=localhost

c2 = b

path=/

c3 = c

domain=localhost

HTTP 标头获取标记化为单个标头元素只能在需求上。通过 HTTP 连接收到的 HTTP 标头是内部存储为一个字符数组和延迟的解析仅当访问其属性。

1.1.3.HTTP 实体

HTTP 邮件可以携带相关联的请求或响应内容实体。实体可以在某些请求和一些反应中,发现它们是可选。使用实体的请求被称为封闭请求的实体。HTTP 规范定义了两个实体封闭方法: 开机自检和付诸表决。响应通常预计将括内容的实体。还有如对 HEAD 方法和 204 响应此规则的例外情况没有内容,304 未修改,205 重置内容作出反应。

HttpCore 区分三种实体,根据其内容来自的位置:

streamed:内容是接收从流或动态生成的。尤其是,这一类别包括正在接收来自连接的实体。流式的实体一般不是可重复的。
self-contained:内容是在内存中,或以独立于连接或其他实体的手段获得的。独立的实体是一般可重复的。
wrapping:从另一个实体中获得内容。

这种区分是重要的连接管理与传入的实体。对于是由应用程序创建和唯一使用的 HttpCore 框架发送的实体,流式与独立之间的差异是很重要。在这种情况下,建议考虑非可重复的实体,作为流式传输,和那些作为独立可重复。

1.1.3.1.可重复的实体

实体可以是可重复的这意味着可以不止一次读取其内容。这是唯一可能的自包含实体 (如ByteArrayEntity或StringEntity).

1.1.3.2.使用 HTTP 实体

实体可以表示二进制和字符的内容.

当执行请求包含的内容,该请求成功响应正文时用于将结果发送回客户端时,将创建实体。

从实体读取内容.其中一个可以要么检索通过HttpEntity#getContent()方法,它返回java.io.InputStream或通过HttpEntity#writeTo(OutputStream)方法,这将返回--所有内容被写入到给定的流。

EntityUtils类公开几个静态方法来更容易地从一个实体读取的内容或信息。而不是直接读取java.io.InputStream ,一个可以检索字符串中的整个 字符串/字节数组 所使用的此类方法。

当实体已收到传入的邮件时,方法HttpEntity#getContentType()和HttpEntity#getContentLength()方法可以用于阅读常见的元数据,如Content-Type和Content-Length标头 (如果可用)。由于Content-Type标头可以包含文本 mime 类型,如text/plain或text/html字符编码, HttpEntity#getContentEncoding()方法用于读取此信息。如果邮件头不可用,将返回一个长度为-1,和NULL的内容,请键入。如果可用的Content-Type标头,将返回一个标头对象。

当创建的传出消息的实体,此元数据,由该实体的创建者提供。

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.3.3.确保释放的系统资源

要确保正确释放的系统资源之一必须关闭与实体关联的内容流。

HttpResponse response;

HttpEntity entity = response.getEntity();

if (entity != null) {

InputStream instream = entity.getContent();

try {

// do something useful

} finally {

instream.close();

}

请注意HttpEntity#writeTo(OutputStream)方法亦须确保适当释放的系统资源,一旦该实体已完全写出。如果此方法通过调用HttpEntity#getContent()获得java.io.InputStream的实例,则它还预计关闭该流 finally 子句。

使用的流媒体实体时,一个可以使用的EntityUtils#consume(HttpEntity)方法,确保充分消耗了的实体内容和基础流已关闭.

1.1.4.创建实体

有几种方法来创建实体。由 HttpCore 提供以下实现:

BasicHttpEntity
ByteArrayEntity
StringEntity
InputStreamEntity
FileEntity
EntityTemplate
HttpEntityWrapper
BufferedHttpEntity

1.1.4.1 BasicHttpEntity

表示基础流的基本实体.这通常用于从 HTTP 消息接收的实体.

此实体有一个空构造函数.施工后它代表没有内容,并且有一个负面内容长度。

一个需要设置的内容的流,和 (可选)长度。这可以分别用BasicHttpEntity#setContent(InputStream)和BasicHttpEntity#setContentLength(long)的方法进行。

BasicHttpEntity myEntity = new BasicHttpEntity();

myEntity.setContent(someInputStream);

myEntity.setContentLength(340); // sets the length to 340

1.1.4.2. ByteArrayEntity

ByteArrayEntity是自包含、 可重复的实体,从一个给定的字节数组中获取其内容。此字节数组被提供给构造函数。

String myData = "Hello world on the other side!!";

ByteArrayEntity myEntity = new ByteArrayEntity(myData.getBytes());

1.1.4.3. StringEntity

StringEntity是自包含,可重复的实体从一个java.lang.String对象中获取其内容。它有三个构造函数,其中一只是构造默认的的java.lang.String 对象 ;第二个考虑字符串的字符编码第三个要指定的 mime 类型。

StringBuilder sb = new StringBuilder();

Map<String, String> env = System.getenv();

for (Entry<String, String> envEntry : env.entrySet()) {

sb.append(envEntry.getKey()).append(": ")

.append(envEntry.getValue()).append("\n");

}

// construct without a character encoding (defaults to ISO-8859-1)

HttpEntity myEntity1 = new StringEntity(sb.toString());

// alternatively construct with an encoding (mime type defaults to "text/plain")

HttpEntity myEntity2 = new StringEntity(sb.toString(), "UTF-8");

// alternatively construct with an encoding and a mime type

HttpEntity myEntity3 = new StringEntity(sb.toString(), "text/html", "UTF-8");

1.1.4.4 InputStreamEntity

InputStreamEntity是一个流式、 非可重复的实体,从输入流中获取其内容。它由提供输入流和内容的长度。内容的长度是用来限制数量的数据读取从java io inputstream。如果长度匹配内容长度可在输入流,然后所有的数据将被发送。另外一个负面内容长度将读取所有数据从输入流,这是提供准确的内容一样的长度,所以这个长度是最常用于限制长度。

InputStream instream = getSomeInputStream();

InputStreamEntity myEntity = new InputStreamEntity(instream, 16);

1.1.4.5 FileEntity

FileEntity是自包含、 可重复的实体,从文件中获取其内容。由于这大多用于流的不同类型的大型文件,一个需要提供的文件,例如,发送一个 zip 文件将需要 application/zip,XML 的application/xml的内容类型的内容类型.

HttpEntity entity = new FileEntity(staticFile,"application/java-archive");

1.1.4.6 HttpEntityWrapper

这是基类来创建包装的实体。包装实体持有一个包装实体和代表所有调用它。实现包装实体可以继承这个类和需要覆盖只有那些方法,不应该委托给包装的实体。

1.1.4.7 BufferedHttpEntity

BufferedHttpEntity是HttpEntityWrapper的一个子类。 它由提供另一个实体。它读取内容从提供的实体,它在内存缓冲区。

这使得它可以让一个可重复的实体,从一个不可重复的实体。如果提供的实体已经是可重复的,调用只是传递到底层的实体.

myNonRepeatableEntity.setContent(someInputStream);

BufferedHttpEntity myBufferedEntity = new BufferedHttpEntity(myNonRepeatableEntity);
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: