Java POST数据到mySQL UTF-8编码问题

Java POST数据到mySQL UTF-8编码问题,java,mysql,post,encoding,utf-8,Java,Mysql,Post,Encoding,Utf 8,我有包含日文字符串AKB48的POST数据ネ申テレビ シーズン3,在jQuery中定义为数据 $("#some_div").load("someurl", { data : "AKB48 ネ申テレビ シーズン3"}) post数据被发送到Java Servlet: String data = new String(this.request.getParameter("data").getBytes("ISO-8859-1"), "UTF-8"); 我的程序将其保存到MySQL,但数据保存到

我有包含日文字符串AKB48的POST数据ネ申テレビ シーズン3,在jQuery中定义为
数据

$("#some_div").load("someurl", { data : "AKB48 ネ申テレビ シーズン3"}) 
post数据被发送到Java Servlet:

String data = new String(this.request.getParameter("data").getBytes("ISO-8859-1"), "UTF-8");
我的程序将其保存到MySQL,但数据保存到数据库后,它将变成:

AKB48 u30CDu7533u30C6u30ECu30D3 u30B7u30FCu30BAu30F33

如果我想将其保存为UTF-8中的状态,该怎么办?我所有的文件都是UTF-8格式的

MySQL编码是utf8,下面是代码

String sql = "INSERT INTO Inventory (uid, item_id, item_data, ctime) VALUES ("
                + inventory.getUid() + ",'"
                + inventory.getItemId() + "','"
                + StringEscapeUtils.escapeJava(inventory.getItemData()) + "',CURRENT_TIMESTAMP)";
    Statement stmt = con.createStatement();
    int cnt = stmt.executeUpdate(sql);

为什么不像this.request.getParameter(“数据”)那样提取参数值呢


使用URL编码正确发送数据,其中每个unicode字符由其代码替换。然后你必须得到参数的值。当您使用
ISO-8859-1
请求字节时,实际上是在破坏您的数据,因为字符串以文本形式表示为序列if代码

这条线的意义是什么

String data = new String(this.request.getParameter("data").getBytes("ISO-8859-1"), "UTF-8");
您正在使用ISO-8859-1编码将中文(或至少非西方)字符转换为字节。当然这是行不通的,因为ISO-8859-1编码不支持汉字。然后使用UTF-8编码,从应该表示ISO-8859-1编码字符的字节构造一个新字符串。这再一次没有任何意义。UTF-8和ISO-8859-1不是一回事,只有一小部分字符在这两种格式中具有相同的编码

只用

String data = this.request.getParameter("data");
如果MySQL表中的列使用支持这些字符的编码,那么一切都应该正常

编辑:

现在您已经向我们展示了用于在数据库中插入数据的代码,我知道所有这些都来自何处(尽管前面的几点仍然有效)。你在干什么

StringEscapeUtils.escapeJava(inventory.getItemData())
重点是什么
escapeJava
用于获取字符串并转义特殊字符,以使其成为有效的Java字符串文字。它与SQL无关。使用事先准备好的陈述:

String sql = "INSERT INTO Inventory (uid, item_id, item_data, ctime) VALUES (?, ?, ?, CURRENT_TIMESTAMP);
PreparedStatement stmt = con.prepareStatement();
stmt.setInteger(1, inventory.getUid()); // or setLong, depending on the type
stmt.setString(2, inventory.getItemId());
stmt.setString(inventory.getItemData());
int cnt = stmt.executeUpdate();

PreparedStatement将负责正确转义特殊SQL字符。它们是抵御SQL注入攻击的最佳工具,当查询具有参数时,尤其是当参数来自最终用户时,应始终使用它们。请参阅。

Java字符串存储在UTF-16中。所以,这个代码:

String data = new String(this.request.getParameter("data").getBytes("ISO-8859-1"), "UTF-8");
使用ISO-8859-1字符集将UTF-16字符串(已在HTTP协议中从UTF-8重新编码)解码为二进制数组,并使用UTF-8字符集对二进制数组重新编码。这几乎肯定不是你想要的

当你使用这个时会发生什么

String data = this.request.getParameter("data");
System.out.println(data);
如果第二行生成了错误的数据,那么您的问题可能出现在jQuery中。确定您在jQuery请求中确实获得了unicode:

System.out.println(this.request.getHeader("Content-Encoding"));

如果它没有生成坏数据,但是数据没有正确地存储在mySQL中,那么问题就出在数据库级别。确保列类型支持unicode字符串

从上面的示例中,我可以验证日语字符串是否正确保存到MySQL数据库中,但如下所示

我会按顺序检查这些项目:

  • 表和列是否都设置为具有utf8的字符集和排序规则?即。,
    字符集utf8校对utf8\u常规\u ci
  • 是否在POST之前显式设置字符集编码<代码>请求.setCharacterEncoding(“UTF-8”)
  • 您正在为数据库连接设置字符编码吗?即,
    jdbc:mysql://localhost:3306/YOURDB?useUnicode=true&characterEncoding=UTF8
  • 正如其他人所指出的,您不应该使用那种
    getBytes
    技巧。这肯定会弄乱公布的价值观

    编辑


    不要使用
    StringEscapeUtils.escapeJava
    ,因为这会将字符串转换为转义Unicode。这就是改变AKB48的原因ネ申テレビ シーズン3into
    AKB48 u30CDu7533u30C6u30ECu30D3 u30B7u30FCu30BAu30F33

    您的mysql数据库是否在utf8中?你是如何坚持mysql、straight SQL或hibernate等的?而且,由于它正确地保存了代码点,如果我只使用String data=this.request.getParameter(“数据”);它变得有些不同,比如:AKB48 u00E3u0083u008Du00E7u0094u00B3u00E3u0083u0086u00E3u0083u00ACu00E3u0083u0093 U00E3U0082U00B7U00E3U0083U00BCU00E3U0082U00BAU00E3U0083U00B33告诉我们MySQL列的编码,并向我们显示用于在数据库中保存字符串的代码。虽然它会损坏一些数据,他的角色超出了当前角色的范围。所以这不是这个例子中的问题。他正在将正确的代码点保存到他的MYSQL中,这样我们就可以看到它被正确地解释了。但是我同意alex的观点,您应该在tomcat设置中使用
    URIEncoding=“UTF-8”
    ,让它处理参数编码。我不知道jquery load使用了post
    URIEncoding=“UTF-8”
    不是必需的。我执行了步骤1和2,但没有执行步骤3,因为我使用的是DataSource dc=(DataSource)ctx.lookup(“java:comp/env/jdbc/databasename”);有点connection@bn.,我的第3点是为数据库连接显式设置字符集编码。如果不这样做,则可能会使用不正确的编码将数据保存到数据库中<代码>(数据源)ctx.lookup用于定位数据源,这是一个完全不同的问题。我强烈建议您重新检查数据库连接的创建方式。您需要在数据源配置中将它们设置为连接属性。哦,请去掉所有
    新字符串(字符串,字符集)
    字符串.getBytes(字符集)
    胡说。这是因为转义字符串问题,我还需要使用preparedStatementSystem.out.println(this.request.getHeader(“内容编码”);返回空值