在 Web 开发中,前端通过表单提交用户输入内容,后端接收并保存数据,这是一个最常见的流程。但有时候我们会遇到一个恼人的问题:用户输入的原始字符在传输过程中被转义,导致数据库里存的并不是用户真实输入,而是 HTML 实体形式。
例如:
- 用户输入:
——
(全角破折号) - 数据库存的却是:
—
- 用户输入:
&
- 数据库存的却是:
&
这种情况不仅破坏了数据的完整性,还可能影响后续的展示和业务逻辑。
一、问题成因
常见原因之一是前端使用了 jQuery 的 .serialize()
方法来序列化表单数据:
var formData = $("#form-dict-add").serialize();
.serialize()
会把表单内容转成 application/x-www-form-urlencoded
格式的字符串,例如:
afterUnitName=%E2%80%94%E2%80%94&afterSocialCode=123
这一串数据会在传输和后端解析过程中,可能被全局过滤器、框架配置甚至前端拦截器做 HTML 转义。最终,数据库拿到的就不是原始字符,而是被转义后的 —
、&
等。
二、解决思路
1. 使用 FormData
代替 .serialize()
与 .serialize()
不同,FormData
会以 原始二进制流 的方式提交数据,而不是 URL 编码格式,可以避免大部分转义问题。
示例代码:
var formData = new FormData($("#form-dict-add")[0]);$.ajax({url: "/adminzy/agricultural/addUnitChange.do",type: "POST",data: formData,processData: false, // 阻止 jQuery 对数据的预处理contentType: false, // 让浏览器自动设置 Content-Typesuccess: function(res) {console.log("提交成功", res);},error: function() {alert("提交失败");}
});
2. 前端确认编码
在 HTML 中保证统一编码,避免字符集不一致导致乱码或意外转义:
<meta charset="UTF-8">
3. 后端确认编码与解析
在 Java/Spring 环境下,可以通过以下配置避免转义问题:
- 统一请求编码(
web.xml
):
<filter><filter-name>encodingFilter</filter-name><filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class><init-param><param-name>encoding</param-name><param-value>UTF-8</param-value></init-param><init-param><param-name>forceEncoding</param-name><param-value>true</param-value></init-param>
</filter>
<filter-mapping><filter-name>encodingFilter</filter-name><url-pattern>/*</url-pattern>
</filter-mapping>
- Tomcat Connector 配置(
server.xml
):
<Connector port="8080" protocol="HTTP/1.1"connectionTimeout="20000"redirectPort="8443"URIEncoding="UTF-8" />
三、调试方法
- 前端打印
console.log(formData.get("afterUnitName"));
- 后端打印
System.out.println("raw afterUnitName=" + request.getParameter("afterUnitName"));
如果这两步打印出来的字符和用户输入一致(全角/半角没变),说明已经解决。
四、总结
.serialize()
会对数据做 URL 编码,在某些情况下可能被转义,导致原始字符丢失。FormData
是更稳妥的选择,尤其是对需要保持原始输入的场景(例如全角/半角、特殊符号)。- 保证 前后端统一编码为 UTF-8,避免字符集差异带来的二次转义。
- 通过前后端打印日志,可以快速定位问题出在哪一环。
这样就能在保存时保留用户最原始的输入,避免数据库出现各种奇怪的转义符号。