zoukankan      html  css  js  c++  java
  • 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的设计。后续会继续从这些接口实现细节上,抽出一部分值得分享,记录的内容写下来。由于这篇文章只是学习笔记,如果您看起来比较不知所然,建议详细学习文中的给出的学习链接。

  • 相关阅读:
    Java并发 --对象的共享
    建立一个二叉查找树
    Tomcat 服务优化
    Mina框架(实战详解)
    ES 查询实战
    IEDA安装配置
    Redis操作以及连接异常
    CyclicBarrier[进程同步辅助类]实现进程间同步
    Linux下端口占用解决方法
    物化视图插入记录,手动刷新问题
  • 原文地址:https://www.cnblogs.com/jcli/p/2727632.html
Copyright © 2011-2022 走看看