Java Web 中文乱码问题全解析:GET/POST 请求编码解决方案
中文乱码是 Java Web 开发中常见的问题,根源在于请求参数编码与解码方式不匹配。GET 和 POST 请求的参数传递方式不同,乱码原因和解决方案也存在差异。本文将详细分析中文乱码的成因,并提供针对性的解决方法,覆盖 Tomcat 配置、代码处理等多种场景。
中文乱码的本质原因
HTTP 协议默认使用 ISO-8859-1 编码(不支持中文),若客户端发送的中文参数使用 UTF-8 编码,而服务器端用 ISO-8859-1 解码,就会导致乱码(表现为 ??? 或一串无意义字符)。
- GET 请求:参数附加在 URL 中,编码由服务器的 URI 编码配置决定;
- POST 请求:参数放在请求体中,编码由
Content-Type头的charset指定,若未指定则默认使用 ISO-8859-1。
GET 请求中文乱码解决方案
GET 请求参数通过 URL 传递,其编码处理依赖服务器配置(如 Tomcat 的 URI 编码设置),常见解决方案如下:
方案一:修改 Tomcat 配置(推荐)
在 Tomcat 的 conf/server.xml 中,为 Connector 节点添加 URIEncoding="UTF-8" 属性,强制服务器对 URI 中的参数使用 UTF-8 解码:
1 | <Connector port="8080" protocol="HTTP/1.1" |
- 作用:所有 GET 请求的 URL 参数均使用 UTF-8 解码,一劳永逸解决乱码;
- 适用场景:有权限修改服务器配置的环境(如开发、测试环境)。
方案二:使用请求体编码同步 URI 编码
若无法修改 Tomcat 配置,可在 Connector 中添加 useBodyEncodingForURI="true",使 URI 编码与请求体编码保持一致:
1 | <Connector port="8080" protocol="HTTP/1.1" |
同时,在 Servlet 中设置请求体编码(需在获取参数前调用):
1 |
|
- 注意:
useBodyEncodingForURI仅在调用request.setCharacterEncoding()后生效,且优先级低于URIEncoding。
方案三:手动转码(不推荐,仅应急)
若以上配置均无法修改,可手动对乱码参数进行转码:
- 先用 ISO-8859-1 还原参数的字节数组;
- 再用 UTF-8 重新解码。
1 |
|
- 缺点:每个参数都需手动处理,代码冗余,且易遗漏,仅建议作为临时解决方案。
POST 请求中文乱码解决方案
POST 请求参数放在请求体中,编码由 Content-Type: application/x-www-form-urlencoded;charset=UTF-8 中的 charset 决定,解决方案更直接:
核心方案:设置请求体编码
在 Servlet 的 doPost 方法中,获取参数前调用 request.setCharacterEncoding("UTF-8"),指定请求体的解码方式:
1 |
|
- 原理:通知服务器用 UTF-8 解码请求体中的参数,与客户端表单提交的编码(通常为 UTF-8)匹配;
- 注意:若客户端表单未指定
charset,需在 HTML 中设置表单编码:
1 | <!-- 表单中指定编码(与服务器保持一致) --> |
全局过滤方案:使用编码过滤器
为避免在每个 Servlet 中重复设置 request.setCharacterEncoding("UTF-8"),可通过过滤器(Filter) 统一处理所有 POST 请求:
(1)实现编码过滤器
1 | // 拦截所有请求 |
(2)注册过滤器(若不使用注解)
在 web.xml 中配置过滤器:
1 | <filter> |
- 作用:全局统一设置请求 / 响应编码,简化代码,推荐在实际项目中使用。
响应中文乱码解决方案
若服务器返回的响应包含中文,需确保响应编码正确,否则客户端会乱码:
1 |
|
- 原理:通过
Content-Type头通知客户端用 UTF-8 解码响应内容; - 注意:
setContentType()需在getWriter()前调用,否则编码设置无效