Java HTTP请求:读取响应体是否是保持连接存活的必要操作?
我正在学习Java中的HTTP请求,想了解读取响应体是否对保持连接存活至关重要。以下是一段向某URL发送POST请求的示例代码:
private void writeToConnection(String url, String msg) throws IOException { try { HttpURLConnection connection = open(url); // "Try with resources" try (BufferedWriter writer = new BufferedWriter( new OutputStreamWriter(connection.getOutputStream()))) { writer.write(msg); } // Why do I need this line? IOUtils.readStringFromStream(connection.getInputStream()); int code = connection.getResponseCode(); System.out.println(String.format("Returned response code %d.", code)); } catch (IOException e) { e.printStackTrace(); } }
我的疑问:
- 为什么必须读取输入流?
readStringFromStream方法返回的字符串未被赋值,却仍要执行该调用,这能确保连接存活吗?- 方法中第一行会新建连接,若后续调用该方法写入新数据,是否会丢弃旧连接并新建?
为什么必须读取输入流?
HttpURLConnection默认支持HTTP/1.1的持久连接(连接复用),但有个前提:客户端必须完整读取服务器返回的全部响应内容。如果不读取输入流,或者只读了一部分,服务器发送的响应数据会滞留在TCP缓冲区里,这个连接会被标记为"不可复用",底层的TCP连接会被直接关闭,而不是放回连接池。另外,长期不读取输入流还可能导致连接阻塞,触发超时异常。
读取输入流能确保连接存活(复用)吗?
是的,但必须是完整读取整个响应体。示例里的IOUtils.readStringFromStream会把输入流的内容全部读到末尾,这时HttpURLConnection才会把这个TCP连接放回连接池,让后续同域名的请求可以复用这个连接。
至于代码里没用到返回的字符串,只是这个场景里不需要处理响应内容——实际开发中你通常会用到响应数据,但哪怕不需要,为了复用连接也得把响应体读完。
后续调用方法会新建连接吗?
不一定。如果之前的请求已经完整读取了响应体,且连接没有超时、服务器也支持持久连接,那么后续调用writeToConnection时,open(url)(假设用的是HttpURLConnection默认逻辑)会优先从连接池里拿空闲的持久连接复用,不会新建。但如果连接池里没有可用连接,或者之前的连接因为没读响应体被丢弃了,那就会新建连接。
补充:HttpURLConnection的连接池是JVM全局维护的,会根据域名、协议等条件管理连接,只要符合复用规则就会优先复用已有连接。
内容的提问来源于stack exchange,提问作者Fiery Phoenix

