urlconnection需显式关闭响应流以防卡死;httpclient发json须设content-type和utf-8编码;连接池须配置三类超时;java.net.http.httpclient需用cookiehandler管理cookie。

URLConnection 发送 GET 请求时,响应流不关闭会卡死
Java 原生 URLConnection 默认启用连接复用,但不显式关闭输入流会导致底层 socket 连接被挂起,后续请求可能阻塞或超时。
- 必须在读完响应后调用
responseStream.close(),哪怕只读一行;try-with-resources是最稳妥写法 -
setDoInput(true)和setDoOutput(false)要配对设置,否则某些 JDK 版本(如 8u202+)会抛IOException: Illegal HTTP method - 手动设置
setRequestProperty("User-Agent", "xxx"),否则部分服务(如 GitHub API)直接返回 403
URL url = new URL("https://httpbin.org/get");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
conn.setRequestProperty("User-Agent", "Java");
conn.setDoInput(true);
conn.setConnectTimeout(5000);
try (InputStream is = conn.getInputStream()) {
// 读取响应
}
HttpClient POST JSON 数据,Content-Type 和编码必须手动指定
Apache HttpClient 不会自动补全 Content-Type 或字符集,发 JSON 时漏掉这两项,服务端大概率解析为空或报 400。
- 必须显式调用
setHeader("Content-Type", "application/json; charset=UTF-8") - JSON 字符串要用
StringEntity包装,并设置entity.setContentEncoding("UTF-8") - JDK 11+ 用户注意:若项目已迁移到
java.net.http.HttpClient,它不支持StringEntity,得用HttpRequest.BodyPublishers.ofString()
HttpPost post = new HttpPost("https://httpbin.org/post");
String json = "{\"name\":\"alice\"}";
StringEntity entity = new StringEntity(json, ContentType.APPLICATION_JSON);
post.setEntity(entity);
post.setHeader("Content-Type", "application/json; charset=UTF-8");
HttpClient 连接池没配置超时,线程会永久卡在 getConnection()
默认的 PoolingHttpClientConnectionManager 不设超时,一旦后端不可达或网络抖动,httpClient.execute() 可能无限等待,拖垮整个线程池。
- 连接获取超时用
setMaxWaitTime()(HttpClient 5.0+)或setConnectionPoolSize()配合setConnectionTimeToLive() - 务必设置
RequestConfig的setConnectionRequestTimeout()(获取连接)、setConnectTimeout()(建连)、setSocketTimeout()(读响应) - 别复用全局
CloseableHttpClient实例却不关连接池——httpClient.close()会关闭底层连接池,应由容器统一管理生命周期
用 java.net.http.HttpClient 发送带 cookie 的请求,不能直接 setHeader("Cookie")
JDK 11 引入的 java.net.http.HttpClient 对 cookie 处理更严格:手动设 Cookie header 会被忽略,必须通过 CookieHandler 注入。
立即学习“Java免费学习笔记(深入)”;
- 创建
HttpClient时传入自定义CookieHandler,例如new CookieManager(null, CookiePolicy.ACCEPT_ALL) - 首次请求后,服务端 Set-Cookie 会自动存入该 manager;后续请求无需干预,自动携带
- 如需预置 cookie(比如登录态),得调用
cookieManager.getCookieStore().add(...),注意 URI 必须匹配,否则不发送
CookieManager cookieManager = new CookieManager(null, CookiePolicy.ACCEPT_ALL);
HttpClient client = HttpClient.newBuilder()
.cookieHandler(cookieManager)
.build();
JDK 版本和 HTTP 客户端选型不是非此即彼的问题,而是得看你的 cookie 管理粒度、连接复用控制需求、以及是否允许引入第三方依赖。原生 URLConnection 最轻量但容易漏关流;HttpClient 功能全但配置项多;java.net.http.HttpClient 看似简洁,可 cookie 和重定向行为默认更保守——这些差异点,往往在压测或线上异常时才突然暴露。










