gpt4 book ai didi

java - 当一个请求由一个 servlet 处理时,是整个请求头/正文/等。已经加载了吗?

转载 作者:IT老高 更新时间:2023-10-28 13:46:30 30 4
gpt4 key购买 nike

当向网页发出请求并通过 servlet(通过 tomcat 处理)进行处理时,一旦您进入 servlet 级别(或 spring mvc Controller )的处理,就会拥有整个请求 header / body /等已经从客户端发送到服务器了吗?

假设客户端正在对网页执行 http POST,并且该帖子包含分配的表单元素。

所有这些数据是否会通过 tomcat 和您正在执行的 servlet,或者如果您实际上没有引用:

request.getParamater("abc")

那么你不会产生额外的负载,因为它不会被流式传输?

最佳答案

我找不到引用,但我相信一旦整个 header 可用(所有请求 header 后跟两个换行符),servlet 就会开始处理。这就是为什么你有 getInputStream()getReader() 而不是 getBody() 返回 String字节[].

这样,servlet 可以在客户端仍在发送请求数据时开始处理请求数据,从而允许 servlet 以较小的内存占用处理大量数据。比如upload servlet可以逐字节读取上传的文件并保存到磁盘,而不需要同时在内存中有完整的请求内容。

这是我用于测试的 servlet(在 Scala 中,对此感到抱歉):

@WebServlet(Array("/upload"))
class UploadServlet extends HttpServlet {

@Override
override def doPost(request: HttpServletRequest, response: HttpServletResponse) {
println(request.getParameter("name"));
val input = Source.fromInputStream(request.getInputStream)
input.getLines() foreach println
println("Done")
}

}

现在我使用 nc模拟慢客户端:

$ nc localhost 8080

服务器端什么也没有发生。我现在手动发送一些 HTTP header :

POST /upload?name=foo HTTP/1.1
Host: localhost:8080
Content-Length: 10000000

服务器端仍然没有任何反应。 Tomcat 接受了连接,但尚未调用 UploadServlet.doPost。但是当我点击 Enter 两次时,servlet 会打印 name 参数,但会在 getLines() (getInputStream() 下面)。

我现在可以使用 nc 发送文本行(Tomcat 需要 10000000 字节),并且它们会逐渐打印在服务器端(input.getLines() 返回一个 Iterator[String] 阻塞直到有新行可用)。

Servlet 总结

  1. Tomcat 在开始处理请求之前等待 整个 HTTP header (将其传递给匹配的 servlet)

  2. 请求正文不必在 doPost() 调用之前完全可用。这很好,否则我们很快就会耗尽内存。

  3. 这同样适用于发送响应 - 我们可以逐步执行此操作。

Spring MVC

使用 Spring MVC,您必须小心。考虑以下两种方法(注意不同的参数类型):

@Controller
@RequestMapping(value = Array("/upload"))
class UploadController {

@RequestMapping(value = Array("/good"), method = Array(POST))
@ResponseStatus(HttpStatus.NO_CONTENT)
def goodUpload(body: InputStream) {
//...
}

@RequestMapping(value = Array("/bad"), method = Array(POST))
@ResponseStatus(HttpStatus.NO_CONTENT)
def badUpload(@RequestBody body: Array[Byte]) {
//...
}

}

输入 /upload/good 将在收到 HTTP header 后立即调用 goodUpload 处理程序方法,但如果您尝试读取 body InputStream 如果还没有收到正文。

然而,/upload/bad 将等到整个 POST 正文可用,因为我们已将整个正文明确请求为字节数组(String 会产生同样的效果):@RequestBody body: Array[Byte].

因此,Spring MVC 如何处理大型请求体取决于您。

TCP/IP 级别

请记住,HTTP 在 TCP/IP 之上工作。仅仅因为您没有调用 getInputStream()/getReader() 并不意味着服务器没有从客户端接收数据。事实上,操作系统管理网络套接字并不断接收 TCP/IP 数据包,这些数据包没有被消费。这意味着来自客户端的数据被推送到服务器,但操作系统必须缓冲该数据。

也许更有经验的人可以回答在这种情况下发生的事情(对于本网站来说,这并不是一个真正的问题)。如果服务器没有读取传入的数据,O/S 可能会突然关闭套接字,或者如果缓冲区变大,它可能会简单地缓冲它并交换?另一种解决方案可能是停止确认客户端数据包,从而导致客户端减速/停止。真的取决于操作系统,而不是 HTTP/servlet。

关于java - 当一个请求由一个 servlet 处理时,是整个请求头/正文/等。已经加载了吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8733268/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com