最稳方案是手动配置httpurlconnection:启用重定向、设置超时、解压gzip、检查响应码、正确编码url、批量读取字节流、按响应头解析字符集、适配tls协议,避免跳过证书校验。

Java里用HttpURLConnection下载网页源码最稳
直接用HttpURLConnection比第三方库更轻、更可控,尤其适合只做简单抓取的场景。它不依赖外部jar,JDK自带,但默认禁用重定向、超时无限、不自动处理gzip——这些恰恰是新手最容易卡住的地方。
- 必须手动调用
setInstanceFollowRedirects(true),否则302跳转会直接返回空内容 - 务必设置
setConnectTimeout(5000)和setReadTimeout(10000),否则DNS失败或服务器挂起会卡死线程 - 如果目标站返回
Content-Encoding: gzip,得自己用GZIPInputStream解包,否则拿到的是乱码二进制 - 记得调用
getInputStream()前先检查getResponseCode(),4xx/5xx响应直接读流会抛IOException
遇到java.net.UnknownHostException别急着换DNS
这个错表面是域名解析失败,但实际常因URL格式不合法触发——比如漏了http://前缀,或URL含中文没编码,HttpURLConnection会静默转成错误host。
- 用
new URL("https://example.com")前,先用URLEncoder.encode()处理路径参数,但注意:只编码query部分,不要整URL都encode - 检查
URL.getProtocol()是否为http或https,null值说明构造失败 - 本地hosts文件篡改、代理配置残留、甚至IDE内置HTTP代理开关开着,都可能干扰解析,建议在命令行用
java -cp . YourDownloader验证是否环境问题
读取响应体时别用readLine()逐行
readLine()会按\r\n/\n切分,但网页源码里可能有换行符在script标签内、注释里,或UTF-8 BOM导致首行读空——结果源码被截断或错位。
- 统一用
InputStream.read(byte[])批量读取,再转new String(bytes, StandardCharsets.UTF_8) - 优先从响应头取字符集:
connection.getHeaderField("Content-Type")里找charset=,没找到才fallback到UTF-8 - 如果页面声明
charset=gbk但实际是UTF-8,浏览器能容错,Java不会——此时需按HTML meta标签动态检测,但简单下载器建议直接按响应头走,避免引入jsoup等依赖
HTTPS站点报javax.net.ssl.SSLHandshakeException
不是证书问题,大概率是JDK版本太低(如JDK 7u95以下)不支持SNI,或目标站只开TLS 1.2+而JVM默认启用SSLv3/TLS 1.0。
立即学习“Java免费学习笔记(深入)”;
- 加启动参数:
-Dhttps.protocols=TLSv1.2,强制升级协议 - JDK 8u161+默认已禁用SSLv3,但某些老服务器仍要求TLS 1.1,可设为
TLSv1.1,TLSv1.2 - 绝对不要用
TrustManager绕过证书校验——这会让中间人攻击生效,调试时宁可临时换一个可信的测试URL










