HttpURLConnection 默认重定向易出错,需显式关闭并手动处理;GET 请求须调用 getInputStream() 才真正发送;超时设置须在 connect() 前完成;中文参数需 URLEncoder 单独编码值;连接复用依赖 Keep-Alive 头,流必须显式关闭防泄漏。

HttpURLConnection 默认会重定向,但 GET 请求可能意外失败
Java 原生 HttpURLConnection 默认开启自动重定向(setInstanceFollowRedirects(true)),看似省事,但实际容易踩坑:比如服务端返回 302 且 Location 头缺失,或重定向到非 GET 方法(如 307/308),它会直接抛 IOException 或静默失败。更隐蔽的是,某些代理或 CDN 会在重定向时丢掉原始请求头(如 Authorization),导致后续请求鉴权失败。
实操建议:
立即学习“Java免费学习笔记(深入)”;
- 显式关闭自动重定向:
conn.setInstanceFollowRedirects(false),自己处理 3xx 响应 - 检查响应码,手动发起新请求(注意复用
Authorization、Cookie等关键头) - 若必须开自动重定向,务必捕获
IOException并检查conn.getResponseCode()是否为 3xx 后的最终状态
GET 请求必须调用 getInputStream() 才真正发出去
HttpURLConnection 是惰性执行的——调用 connect() 只是建立连接准备,真正发送请求头和触发网络 I/O,要等到第一次调用 getInputStream() 或 getErrorStream()。很多人写了 setRequestMethod("GET") 就以为请求已发出,结果 getResponseCode() 返回 -1 或阻塞。
实操建议:
立即学习“Java免费学习笔记(深入)”;
- 确保在读取响应前至少调用一次
getInputStream()(哪怕只读一个字节)或getResponseCode()(它内部会触发连接) - 不要在
getResponseCode() == 200判断后才去读流——如果状态不是 200,得改用getErrorStream(),否则会抛异常 - 超时设置必须在
connect()前完成:conn.setConnectTimeout(5000)、conn.setReadTimeout(10000)
中文参数 URL 编码不处理,直接拼接会导致 400 错误
GET 请求的查询参数如果含中文、空格、斜杠等,必须用 URLEncoder.encode(value, "UTF-8") 编码,且只编码值部分(key 和 =、& 不参与编码)。常见错误是整段 URL 丢给 URLEncoder,结果把 http:// 也编码了;或者忘了指定字符集,用默认平台编码(Windows 上是 GBK),服务端 UTF-8 解码就乱码。
实操建议:
立即学习“Java免费学习笔记(深入)”;
- 用
StringBuilder拼接 query string,对每个value单独编码:URLEncoder.encode("张三", "UTF-8") - 避免手拼 URL,更别用
String.format直接插值 - 如果参数来自用户输入,记得先 trim 再 encode,防止前后空格被编码成
+或%20
连接复用依赖 Keep-Alive 头,但默认行为因 JDK 版本而异
JDK 7+ 默认启用 HTTP/1.1 和连接复用,但前提是服务端响应头包含 Connection: keep-alive 且未显式关闭。JDK 6 默认用 HTTP/1.0,除非手动设 conn.setRequestProperty("Connection", "keep-alive")。更麻烦的是,HttpURLConnection 的连接池由 JVM 全局管理,无法配置最大空闲数或过期时间,高并发下容易耗尽 socket。
实操建议:
立即学习“Java免费学习笔记(深入)”;
- 显式设置协议版本(可选):
conn.setRequestProperty("Connection", "keep-alive") - 每次用完必须调用
conn.getInputStream().close()或conn.getErrorStream().close(),否则连接不会归还池中 - 生产环境高并发场景,优先考虑
Apache HttpClient或OkHttp,它们的连接池可控、调试友好、超时粒度更细
最常被忽略的是流关闭时机和重定向逻辑耦合——比如手动处理 302 时开了新连接,但忘了关老连接的输入流,JVM 连接池会缓慢泄漏。这事没法靠 GC 补救,得每条路径都覆盖到。









