正确设置 HttpURLConnection 需在 connect() 或 I/O 调用前完成:用 setRequestProperty() 覆盖同名 header,addRequestProperty() 多次添加(如 Cookie);setDoOutput(true) 才启用请求体写入并隐式设 POST;超时必须提前设,单位毫秒;header 名限 ASCII,值含中文需 URLEncoder 编码;调用 I/O 方法后设 header 无效。

如何用 HttpURLConnection 设置请求头
直接调用 setRequestProperty() 即可,它会覆盖同名 header;若需多次设置(比如多个 Cookie),得用 addRequestProperty(),否则后设的会把前一个顶掉。
常见错误是误用 setRequestProperty("Content-Type", "application/json") 后又手动写入 JSON 字符串但没设 setDoOutput(true) —— 这会导致连接静默失败或返回 415 错误。
-
setRequestProperty("Authorization", "Bearer abc123")是最常用的身份认证方式 -
setRequestProperty("Accept", "application/json")告诉服务端你期望什么格式响应 - 自定义 header 如
X-Trace-ID可直接传字符串,无需额外编码 - 不要在 header 中硬塞中文,除非明确服务端支持并已用
URLEncoder.encode()处理值(header key 始终是 ASCII)
如何正确设置连接与读取超时
setConnectTimeout() 控制的是 TCP 握手 + TLS 握手完成的时间上限;setReadTimeout() 控制的是从 socket 读取第一个字节开始、到整个响应体接收完毕的最大等待时间。两者必须在 connect() 或 getInputStream() 调用前设置,否则无效。
典型陷阱是只设了 setConnectTimeout(5000) 却没设 setReadTimeout(),结果遇到网络卡顿或服务端迟迟不发响应体,线程就无限挂起。
- 生产环境建议
setConnectTimeout(3000)+setReadTimeout(10000)起步 - 超时单位是毫秒,不是秒 —— 写成
setReadTimeout(30)实际只有 30ms,基本必超 - 若用
setInstanceFollowRedirects(false)并手动处理重定向,每个跳转都要单独设超时
为什么 setRequestProperty() 有时不生效
根本原因通常是调用了 getOutputStream() 或 getInputStream() 之后再设 header —— 此时请求头已发送,JDK 会忽略后续设置,并可能抛出 IllegalStateException: Already connected。
分析 Java Spring Boot 后端 Controller 代码,自动生成 Markdown 格式的接口文档。当用户说“生成 Java 接口文档”、“生成 API 文档”、“从 Spring 代码生成文档”时触发。
另一个隐蔽问题是某些 header 名被 JDK 内部拦截或强制重写,比如 Host、Connection、Keep-Alive 等,即使你调用 setRequestProperty("Host", "...") 也不会生效。
- 务必在
openConnection()后、任何 I/O 方法调用前设置所有 header - 调试时可用
getHeaderFields()检查实际发出的 header(仅限响应头);请求头需靠抓包确认 - 如果依赖动态 header(如 token 刷新),建议封装成工厂方法,避免状态残留
对比 setDoOutput(true) 和 setRequestMethod("POST") 的影响
setRequestMethod("POST") 只改 HTTP 方法,不自动开启输出流;而 setDoOutput(true) 才真正允许写请求体,并隐式将 method 设为 POST(除非已显式设为 PUT 等)。两者顺序错乱会导致 ProtocolException: POST method does not support writing。
更麻烦的是:一旦设了 setDoOutput(true),就不能再用 getInputStream() 读响应,除非先调用 connect() —— 否则会抛 IllegalStateException。
- GET 请求不需要
setDoOutput(true),加了反而容易出错 - POST/PUT 带 body 时,必须同时设
setDoOutput(true)和setRequestProperty("Content-Length", ...)(或让 JDK 自动计算,不手动设) - 用
setFixedLengthStreamingMode()或setChunkedStreamingMode()可绕过Content-Length计算,但要求 JDK ≥ 7
真正难的不是设 header 或超时,而是确保这些调用发生在连接建立前、且彼此不冲突。哪怕只漏掉一个 setDoOutput(true) 或把 setReadTimeout() 放在 getInputStream() 后面,都会导致行为不可预测 —— 这类问题在线上往往表现为偶发性超时或空响应,排查成本远高于写的时候多看两眼文档。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










