当Tomcat收到路由到Servlet的Post请求时,Tomcat是在调用Servlet的处理程序方法之前是否等待直到获得整个帖子主体,还是立即调用该方法?
我通过扩展HttpServlet
类并实现doPost(request, response)
方法创建了一个简单的servlet。在我的方法中,我正在调用request.getInputStream()
通过输入流来检索帖子正文。
假设客户端正在发布一个非常大的对象,并且在上载过程中,客户端中止了上载或它们的Internet连接失败。在这种情况下,我的doPost
方法将永远不会被调用吗?还是会被调用,但是在读取输入流的过程中会失败?
差异对我来说很重要,因为我想弄清楚在输入流读取期间是否能够捕获IOException
并在那里执行一些操作。
答案 0 :(得分:1)
查看Tomcat源代码,我们看到默认的ServeltInputStream
实现是CoyoteInputStream
,它从org.apache.catalina.connector.InputBuffer
的实例读取。该缓冲区具有各种扩展类,这些扩展类是特定于协议的。看来,在调用doPost()
之前被完全读取的请求正文是一个实现细节,具体取决于所使用的协议,例如对于StreamInputBuffer
类中的HTTP2,我们看到以下注释:
需要两个缓冲区来避免各种多线程问题。 这些问题是由于Stream(或 应用程序使用的请求/响应)在一个线程中处理 但连接是在另一个中处理的。因此有可能 在应用程序之前可以接收到请求主体框架 准备阅读它。如果没有缓冲,则处理 连接(以及所有流)将一直阻塞,直到应用程序 读取数据。因此,传入的数据必须被缓冲。 如果仅使用一个缓冲区,则如果 连接线程正在尝试将其同时添加到 应用程序被读取。虽然应该可以避免这种情况 通过谨慎使用缓冲区来破坏它,仍然需要 与使用两个缓冲区相同的副本,并且行为会更少 清除。
这适用于其他servlet容器,例如如果连接可以挂在内部,则JBoss WildFly可以在完全基于[WFLY-6671] ajp connection hangs if a post HTTP request header contains 'Transfer-Encoding: chunked'读取请求正文之前开始执行doPost()
。
答案 1 :(得分:0)
在读取正文之前,将调用doPost()
方法。
在通常的POST请求中,当您调用request.getParameter(..)
,.getParameterNames()
,.getPart(..)
或.getParts()
时,将读取并使用主体。如果您能够呼叫request.getInputStream()
,则表示该正文尚未被读取。
使用HTTP / 1.1协议,如果客户端使用100 Continue
标头请求服务器,则服务器可以向客户端(Expect
)发送确认。它发生在阅读身体之前。