Java网络传输乱码的核心是发送端与接收端编码一致,最稳妥做法是全程统一UTF-8并显式声明;HTTP请求响应需在Content-Type头中明确charset=UTF-8,读取响应流时必须用StandardCharsets.UTF_8构造InputStreamReader,GET参数需URLEncoder编码并配置Tomcat URIEncoding或手动转码。

Java 中处理网络传输乱码,核心是确保“发送端编码”和“接收端解码”使用完全一致的字符集,最稳妥的做法是全程统一为 UTF-8,并显式声明,不依赖系统默认。
HTTP 请求与响应中显式指定 charset
HTTP 协议本身不强制要求字符编码,但通过 Content-Type 头明确声明可避免歧义。无论是客户端发请求,还是服务端写响应,都应带上 charset=UTF-8:
- 服务端返回 JSON 时:设置响应头
Content-Type: application/json; charset=UTF-8 - 客户端发送表单或 JSON 时:在请求头中添加
Content-Type: application/x-www-form-urlencoded; charset=UTF-8或application/json; charset=UTF-8 - 若用 Spring MVC,可通过
@RequestMapping(produces = "application/json;charset=UTF-8")或全局配置StringHttpMessageConverter的默认编码
读取 HTTP 响应流时必须指定 InputStreamReader 编码
很多乱码源于未显式传入编码,导致 InputStreamReader 使用平台默认编码(如 Windows 上是 GBK),而服务端实际发的是 UTF-8:
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
- 错误写法(依赖默认):
new InputStreamReader(url.openStream()) - 正确写法:
new InputStreamReader(url.openStream(), StandardCharsets.UTF_8) - 使用 Apache HttpClient 时,推荐用
EntityUtils.toString(httpResponse.getEntity(), "UTF-8") - 用 OkHttp 时,调用
response.body().string()默认按响应头 charset 解析;若头缺失,它会尝试 BOM 或 Content-Type,但更稳妥的是用response.body().string(StandardCharsets.UTF_8)
URL 参数与查询字符串的编码一致性
GET 请求中的中文参数需 URL 编码(percent-encoding),否则可能被截断或误解析:
立即学习“Java免费学习笔记(深入)”;
- 发送前用
URLEncoder.encode("中文", "UTF-8")编码,例如转为%E4%B8%AD%E6%96%87 - 服务端接收后,Servlet 容器(如 Tomcat)默认对 GET 参数用 ISO-8859-1 解码,需手动按 UTF-8 重新解码:
new String(request.getParameter("q").getBytes("ISO-8859-1"), "UTF-8") - Tomcat 更推荐在
server.xml的 Connector 中配置URIEncoding="UTF-8",一劳永逸解决 GET 参数乱码
第三方 API 或微服务调用中的编码约定
对接外部系统时,不能假设对方用 UTF-8。务必查阅其文档,确认其请求/响应的编码方式,并在代码中严格匹配:
- 若对方明确使用 GBK,你就得用
"GBK"构造InputStreamReader,而非硬写 UTF-8 - 建议在调用封装层做统一适配,比如定义一个
CharsetAwareHttpClient,根据目标域名或接口配置动态选择编码 - 对返回内容做预检:读取前先看响应头
Content-Type是否含charset=,有则优先采用;无则按约定 fallback

















