doGet和doHead方法之间的区别 - java

我知道doHead方法不会通过http发送正文,但是doGet也不会。
两者之间有明显区别吗?
提前致谢。

参考方案

简短答案

HEAD仅发送回与相应GET请求相同的标题信息,但没有实体主体。 GET将发送相同的标头和实体正文。当然,在极少数/可争论的情况下,GET不会在其体内发送任何内容,然后GET和HEAD的行为类似。

本书HTTP The Definitive Guide添加:

这允许客户端检查资源的标头,而无需
必须实际获取资源。使用HEAD,您可以:

  • 在不获取资源的情况下查找该资源(例如,确定其类型)。
  • 通过查看响应的状态码来查看对象是否存在。
  • 通过查看标头,测试资源是否已被修改。
  • 服务器开发人员必须确保返回的标头完全相同
    那些返回GET请求的代码。 HEAD方法也是
    符合HTTP / 1.1要求。

    因此,doHead是否调用doGet可能只是实现细节,但是如果是这样,则doHead将需要在发送响应之前剥离doGet的正文。但是,此实现方式效率不高,因为理想情况下doHead不会造成执行整个doGet请求以确定要发回哪些标头的困难。

    但是,某些标头的计算可能会带来困难。例如,“Content-Length”标头意味着我们需要知道实际资源的大小,因此HEAD可能需要“获取”资源来确定相应GET请求的实际大小(以字节为单位),但这不会增加负担实际发送资源的网络,尽管它可能使服务器承担了检索资源的负担,以便确定要发送回哪些报头(即Content-Length,Content-Type,Content-Language等)

    详细答案

    HTTP specification说

    9.4头

    HEAD方法与GET相同,除了服务器不得
    在响应中返回一个消息正文。包含的元信息
    HTTP标头中对HEAD请求的响应应该相同
    响应于GET请求而发送的信息。这种方法可以
    用于获取有关隐含实体的元信息
    请求,而不转移实体本身。这个方法是
    通常用于测试超文本链接的有效性,可访问性,
    和最近的修改。

    从某种意义上说,对HEAD请求的响应可以是可缓存的
    响应中包含的信息可用于更新
    先前从该资源缓存的实体。如果新的字段值
    指示缓存的实体与当前实体不同(如
    将通过Content-Length,Content-MD5,ETag或
    最后修改),然后缓存必须将缓存条目视为过期。

    GET表示:

    9.3获取

    GET方法表示检索任何信息(以
    实体)由Request-URI标识。如果请求URI指向
    数据产生过程,应是产生的数据
    作为响应中的实体返回,而不是
    流程,除非该文本恰好是流程的输出。

    如果GET方法的语义更改为“条件GET”,
    请求消息包括If-Modified-Since,If-Unmodified-Since,
    If-Match,If-None-Match或If-Range标头字段。有条件的GET
    方法要求仅在
    条件标头字段描述的情况。的
    有条件的GET方法旨在减少不必要的网络使用
    通过允许刷新缓存的实体而不需要多个
    请求或传输客户端已经拥有的数据。

    如果GET方法的语义更改为“部分GET”,
    请求消息包括范围标头字段。部分GET请求
    如本节所述,仅转移实体的一部分
    14.35。部分GET方法旨在通过允许部分取回的实体完成来减少不必要的网络使用
    而不传输客户端已经拥有的数据。

    只有在满足以下条件时,对GET请求的响应才可以缓存:
    第13节中描述的HTTP缓存要求。

    有关用于表单的安全注意事项,请参见15.1.3节。

    如果您使用read the source code for javax.servlet.http.HttpServlet ,则可以看到其文档显示:

    从受保护的服务方法接收HTTP HEAD请求,并
    处理请求。客户端在需要时发送HEAD请求
    仅查看响应的标头,例如Content-Type或
    内容长度。 HTTP HEAD方法对输出字节进行计数
    响应以准确设置Content-Length标头。如果您覆盖
    这种方法,您可以避免计算响应主体,而只需设置
    直接响应头,以提高性能。确保
    您编写的doHead方法既安全又幂等(即,
    保护自己免受一个HTTP HEAD的多次调用
    请求)。如果HTTP HEAD请求的格式错误,请执行doHead
    返回HTTP“错误请求”消息。

    默认方法实现如下所示:

    protected void doHead(HttpServletRequest req, HttpServletResponse resp)
    throws ServletException, IOException
    {
       NoBodyResponse response = new NoBodyResponse(resp);
       doGet(req, response);
       response.setContentLength();
    }
    

    如果您阅读NoBodyResponse的代码,您将看到它只是一个响应,其输出流将丢弃所有数据,并且仅对字节进行计数即可确定相应GET响应的正确Content-Length。

    因此,Servlet规范以这种方式提出了如何生成有效的HEAD响应的方式。只要您遵守HTTP规范准则,就可以覆盖此行为以使其更有效。

    Java:正则表达式模式匹配器是否有大小限制? - java

    我的模式类似于OR:“word1 | word2 | word3”我大约有800个字。可能有问题吗? 参考方案 您仅受记忆和理智的限制。 :)

    Java:线程池如何将线程映射到可运行对象 - java

    试图绕过Java并发问题,并且很难理解线程池,线程以及它们正在执行的可运行“任务”之间的关系。如果我创建一个有10个线程的线程池,那么我是否必须将相同的任务传递给池中的每个线程,或者池化的线程实际上只是与任务无关的“工人无人机”可用于执行任何任务?无论哪种方式,Executor / ExecutorService如何将正确的任务分配给正确的线程? 参考方案 …

    JAVA:字节码和二进制有什么区别? - java

    java字节代码(已编译的语言,也称为目标代码)与机器代码(当前计算机的本机代码)之间有什么区别?我读过一些书,他们将字节码称为二进制指令,但我不知道为什么。 参考方案 字节码是独立于平台的,在Windows中运行的编译器编译的字节码仍将在linux / unix / mac中运行。机器代码是特定于平台的,如果在Windows x86中编译,则它将仅在Win…

    java:继承 - java

    有哪些替代继承的方法? java大神给出的解决方案 有效的Java:偏重于继承而不是继承。 (这实际上也来自“四人帮”)。他提出的理由是,如果扩展类未明确设计为继承,则继承会引起很多不正常的副作用。例如,对super.someMethod()的任何调用都可以引导您通过未知代码的意外路径。取而代之的是,持有对本来应该扩展的类的引用,然后委托给它。这是与Eric…

    Java:BigInteger,如何通过OutputStream编写它 - java

    我想将BigInteger写入文件。做这个的最好方式是什么。当然,我想从输入流中读取(使用程序,而不是人工)。我必须使用ObjectOutputStream还是有更好的方法?目的是使用尽可能少的字节。谢谢马丁 参考方案 Java序列化(ObjectOutputStream / ObjectInputStream)是将对象序列化为八位字节序列的一种通用方法。但…