Apache HttpCore 学习

最近有点时间,想学习下 http 的规范,理论和实践结合学习是最有效果的学习方法,如是结合 Apache httpcomponets 的源码,尝试理解http的设计思想,但是整个学习下来,在代码设计规划上也学习到不少东西,这要得益于httpcore,httpclient优秀的源码.

http协议所描述的可以用一句话概括:点对点的消息交换(一端向另一端发起请求(request),接收端处理请求并返回消息(response)). 不管是http请求还是http响应,我们都把它当做http消息(message)。

                                               (picture 1)

Apache HttpCore 中完全按照rfc文档定义对象接口关系。HttpRequestHttpResponse 都扩展继承自 HttpMessage接口。picture 1 中,接口 HttpEntityClosingRequest 扩展了 HttpReqeust 接口,那HttpEntityClosingRequest 是在rfc文档中对应怎样的描述?

7 Entity
Request and Response messages MAY transfer an entity if not otherwise restricted by the request method or
response status code. An entity consists of entity-header fields and an entity-body, although some responses will only
include the entity-headers.
In this section, both sender and recipient refer to either the client or the server, depending on who sends and who
receives the entity.

请求和返回消息都可以附带一个消息实体传输,如果请求方法和返回码都没有限制的话。消息实体可以包括实体头和实体内容,尽管有些返回消息只包括实体头。

我在最开始看文档时,始终对entiy的概念模模糊糊,理解不透,通过google一些文章和反复看文档才有些眉目。其实我们可以这么理解entiy:对于消息请求时,例于post请求时,提交的表单内容即可看成entity消息实体;对于消息返回时,我们接收到<html>...</html>标记文档即可看做entity实体。所以说一个消息(不管是请求还是响应消息),里面除了消息头(header),就是消息实体(entity),当然目前为止,你可以这样理解,后面我们会指出这里有些问题。相关参考

                                                    (picture 2)

消息实体在Apache HttpCore中相关接口定义如图picture 2,可以看到有各种版本的entiy实现,不同的实现区别仅在对entiy的表现存在形式不同而也:
ByteArrayEntiy          : byte数组实现
FileEntiy                   : 本地文件实现
InputStreamEntiy       : io流文件实现
HttpEntityWrapper     : 对别的entity进行包装,添加新功能,利用decorator模式
BufferedHttpEntity     : 继承扩展HttpEntityWrapper,实现可缓冲的entity

   这些entity接照其内容存在地方形式分为如下类别:

  • streamed: The content is received from a stream, or generated on the fly. In particular, this category includes entities being received from a connection. Streamed entities are generally not repeatable.
  • self-contained: The content is in memory or obtained by means that are independent from a connection or other entity. Self-contained entities are generally repeatable.
  • wrapping: The content is obtained from another entity.
  1. streamed : BaseHttpEntity,InputStreamEntity
  2. self-contained : FileEntity,BufferedHttpEntity
  3. wrapping : HttpEntityWrapper

这里比较有意思的是BufferedHttpEntity,它既是wrapping类别,也属于self-contained类别。正是因为它是wrapping类别的,所以它会包装其它的entity,如果被包装的entity本身是self-contained的,则直接调用它的方法,如果被包装的entity是streamed类型的,则会把它缓存起来,形成self-contained形式。

 ----------------------------------------------------------------------

Request Method(请求方法)

  • Options
  • Get
  • Head
  • Post
  • Put
  • Delete
  • Trace
  • Connect

这些请求方法中,我们最熟悉是Get和Post这两种方法,其它的基本上没有用到。不过由于最近开放平台的兴起,开发人员慢慢的要接触和熟悉起这些方法来。其实从这些方法名的语义上,便可直观的了解这些方法所要表达的行为方式。Get:得到资源数据,Delete删除资源数据......。关于其中更高层的思想境界,值得一看的是Roy Fielding的论文

这里最容易让人不理解的是Put和Post的区别到底是什么。它们都是通过指定的Uri来提交带有entity的消息请求(request),并要求服务端(server)接收并处理这些请求。但是Post方法指的是广义的处理方式,何为广义上的处理呢,引用rfc文档:

· Annotation of existing resources;
· Posting a message to a bulletin board, newsgroup, mailing list, or similar group of articles;
· Providing a block of data, such as the result of submitting a form, to a data-handling process;
· Extending a database through an append operation.

引用内容大概是说Post方法是对存在的资源进行注解;提交生成一个内部通告,新闻组,邮件列表;提交一些表单数据进行处理;扩展数据库。
而Put方法具有更狭义的语义:提交一个附带entity的请求消息(request)到指定的Uri,在该Uri上保存entity,如果该Uri之前保存过entity,则最新的entity覆盖之。
所以说Post的操作语义范围较Put更广,Post指所有的处理资源方式,而Put则是注重Uri和Entity的对应关系。

举个形象的例子:

POST/book/add           这里是添加一本书,每Post一次则新增一本书

PUT   :  /book/add/1         这里添加ID为1的一本书,如果服务端发现此id=1的书已存在,则覆盖之,相当于edit操作

   -----------------------------------------------------------------

 消息头(Header)

消息头可以看成是消息的元数据描述对象,它是对请求消息(request),响应消息(response),消息实体(entity)的元描述,比如请求消息头Accept就是指定请求客户端可以理解哪些媒体类型,Content-Length头指定entity的大小长度。

                                                                                                           (picture 3)

 

------------------------------------------------------------

下面把Apache HttpCore设计得比较好的地方拿出来分析下:


HttpParams


在Http各组件运行中,都要用到各种运行时的参数

(picture 4)

针对Connection(网络连接资源,如Socket)进行“池”管理。

 (picture 5)

 主要是对URI中相同的Host建立的Socket连接实现reuseable化,提高效率和优化性能,满足Http1.1中的Connection头描述(值为keep-alive时不关闭每个当前连接,以供下次请求使用)

 AOP架构模式,拦截处理request和response消息的各种头,内容体处理

 

 

 ------------------------------------------------------------------------------

总结

这篇文章只是根据rfc规范和Apache HttpCore中的架构设计相互参考学习后的一些笔记,图中列出的UML类图也只是从抽象层面理解http的设计。后续会继续从这些接口实现细节上,抽出一部分值得分享,记录的内容写下来。由于这篇文章只是学习笔记,如果您看起来比较不知所然,建议详细学习文中的给出的学习链接。

 

 

 

 

 

 

 

 

posted @ 2012-10-17 17:18  海鸟  阅读(4229)  评论(0编辑  收藏  举报