doGet和doHead方法之间的区别

Rol*_*all 4 java methods servlets

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

Edw*_*rzo 7

简短的回答

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请求的实际大小(以字节为单位),但这不会增加负担实际上发回资源的网络,虽然它可能已经通过检索资源来加重服务器以确定要发回的标头(即内容长度,内容类型,内容语言等)

答案很长

在HTTP规范说

9.4头

HEAD方法与GET相同,只是服务器不能在响应中返回消息体.响应HEAD请求的HTTP头中包含的元信息应该与响应GET请求时发送的信息相同.该方法可用于获得关于请求所暗示的实体的元信息,而无需转移实体主体本身.此方法通常用于测试超文本链接的有效性,可访问性和最近的修改.

对于HEAD请求的响应可以是可缓存的,因为响应中包含的信息可以用于从该资源更新先前缓存的实体.如果新字段值指示缓存的实体与当前实体不同(如Content-Length,Content-MD5,ETag或Last-Modified中的更改所示),则缓存必须将缓存条目视为陈旧.

鉴于GET,它说:

9.3 GET

GET方法意味着检索由Request-URI标识的任何信息(以实体的形式).如果Request-URI引用数据生成过程,则生成的数据应作为响应中的实体而不是过程的源文本返回,除非该文本恰好是过程的输出.

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

如果请求消息包括Range头字段,则GET方法的语义变为"部分GET".部分GET请求仅传输实体的一部分,如第14.35节所述.部分GET方法旨在通过允许完成部分检索的实体而不传输客户端已经拥有的数据来减少不必要的网络使用.

当且仅当它满足第13节中描述的HTTP缓存要求时,对GET请求的响应才是可缓存的.

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

如果您阅读了源代码,javax.servlet.http.HttpServlet可以看到它的文档说:

从受保护的服务方法接收HTTP HEAD请求并处理该请求.当客户端想要仅查看响应的标头(例如Content-Type或Content-Length)时,它会发送HEAD请求.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();
}
Run Code Online (Sandbox Code Playgroud)

如果您读取代码,NoBodyResponse您将看到它只是一个响应,其输出流丢弃所有数据,并只计算字节以确定相应GET响应的正确Content-Length.

因此,这就是Servlet规范提出如何生成有效HEAD响应的方式.只要遵守HTTP规范准则,您可以覆盖此行为以提高效率.