zoukankan      html  css  js  c++  java
  • MySQL解决中文编码问题

    近日在使用Java(Servlet)+MySQL实现微信小程序的后台的时候,遇到了一个问题:微信小程序传过来的中文字符在入数据库的时候会变成“???”,这个问题的解决耗费了我七八个小时左右的时间,特意开篇博客来记录一下我的解决思路和流程。

    1. 首先检查微信小程序发送请求时的Header是怎么写的:

    header: {
            'content-type':'application/x-www-form-urlencoded',
          },

    我们的小程序仅设置了一个application/x-www-form-urlencoded,并未对字符编码格式(charset)进行设置,因此不知道微信小程序发过来的请求到底是什么编码格式的……

    先来人工尝试一下……用微信小程序向服务器发起一个插入数据的请求后,在tomcat服务器的日志中找到了如下内容:

    GET /dailyLife/api/habit/updatehabit?id=0&name=%E6%B5%8B%E8%AF%95Aa3&icon=4&category=1&weekday=4&token=0a6fff2b9ec2058eee0d26df51846497 HTTP/1.1

    其中name参数是我在小程序端输入的中文,可以看到在未指定编码格式的时候,name参数被urlencode了……而我的Java后台的代码是把字符串按照utf-8来处理的……这就造成了编码格式的不统一(要解决这个问题,也可以通过修改小程序端来完成,即在发送请求时在头部加上charset = utf8,可参见Ya_豆芽的博客https://www.cnblogs.com/i-douya/p/8245359.html),不过我这里遇到的情况是尽量不修改小程序端代码,因此只能在服务器端来调整

    2. 服务器端的Java代码调整

    如果从服务器端进行调整,那么我们只需要在获取到参数之后立刻对它进行一次urldecode即可,这里可以使用Java的URLDecoder来完成,参见风漫宇的博客https://blog.csdn.net/xiazhiyu_whu/article/details/79708431

    在Servlet中的体现:

    String name = req.getParameter("name");
    name = URLDecoder.decode(name, "UTF-8");

    这样处理之后的name就是utf-8的格式了,并且不会影响到后续代码的执行(只是修改了一下变量的值而已嘛,又没改变量名字之类的……)

    这里顺带一提:由Java官方文档可知,URLDecoder的decode方法的第二参数是可以用标准字符集类的UTF-8作为参数的,这应该是现在最正规的调用方法,如下所示:

    String name = req.getParameter("name");
    name = URLDecoder.decode(name, StandardCharsets.UTF_8);

    (标准字符集类需要JDK10以上才能解释,我的服务器的JDK版本是8,因此我这里没有采用标准字符集类的UTF-8来作为decode函数的第二参数,而是直接用的字符串“UTF-8”)

    3. 修改Servlet之后问题仍然没有解决,我当时怀疑是我的Servlet逻辑有问题(解码不彻底或者什么其他毛病之类的),而tomcat的日志似乎有点问题,在我清了一次日志之后就再也不写日志了,该问题暂时没有解决。于是我决定在Java层面人工加入日志来进行debug

    在Servlet中加入日志添加功能的方法参见Jquery中文网:http://www.jquerycn.cn/a_18338

    标准Logger的使用可以参见该篇博客:https://blog.csdn.net/gruhgd/article/details/84026217

    这里我采用的是创建一个LogUtil工具类,在其中实现如下静态方法:

    public static void print(String message) {
        PrintWriter out = null;
        try {
            out = new PrintWriter(new FileOutputStream("/root/log.txt", true));
            out.println(message);
            out.close();
        } catch (FileNotFoundException e){
            e.printStackTrace();
        }
    }

    然后对获取参数name的代码加入了一些日志来方便debug(注:事实上如果会用的话,这里的debug也可以用Intellij Idea的远程debug来进行,会比我这样用日志去debug方便很多,但是我不太会,所以没办法了emmmmmm)

    代码修改如下:

    String name = req.getParameter("name");
    LogUtil.print("param:" + name + "
    ");
    name = URLDecoder.decode(name, StandardCharsets.UTF_8);
    LogUtil.print("after:" + name + "
    ");

    更新了服务端代码之后,通过浏览器调用接口,进行了一些添加操作,然后我的日志文件里面的内容……竟然是这个样子的……????!!!

    param:测试

    after:测试

    param:测试2

    after:测试2

    param:不想测了

    after:不想测了

     我惊了……这什么情况……我觉得可能是浏览器自动把我输入的urlencode帮我转码了(这么想的我大概是疯了emmmmm)……

    然而我直接在Java中把name写死成“%e6%b5%8b%e8%af%952”,结果从日志来看,程序还是正常运行的……

    于是我费了很大力气……又跑到windows系统下用微信小程序发了几次添加请求,结果也还是一样的……

    这啥情况啊……

    4. 思来想去……觉得可能是MYSQL的编码格式的锅……

    以下开始正文.jpg

    正文全都是引用其他人的链接.png

    如何解决MySQL的字符编码格式问题呢?这么一些方案吧……各大的步骤都做一遍大概就好了……

    一、创建数据库时修改字符编码格式为utf8

    查看数据库编码格式:

    mysql> show variables like 'character_set_database';

    创建数据库时指定编码格式:

    mysql>create database <数据库名> character set utf8;

    修改数据库编码格式:

     

    mysql>alter database <数据库名> character set utf8;

     

    二、创建表时修改字符串编码格式为utf8

    查看表编码格式:

    mysql> show create table <表名>;

    创建表时指定编码格式:

     create table <表名> (BLABLABLABLABLA……) default charset = utf8;

    修改表的编码格式:

    mysql>alter table <表名> character set utf8;

    三、修改MySQL中的charset设置

    我想我遇到的问题大概跟这篇博客一样?https://www.cnblogs.com/slow/p/3222933.html

    我也跑了一下这个命令……确实里面是有latin的……

    MySQL中的各项charset的含义可以参照博客:https://blog.csdn.net/sun8112133/article/details/79921734

    但修改charset的方法请不要学习……直接set charset这种方法亲测不可行……退出mysql再登陆刚改的就没了……

    修改charset的方法请参见https://blog.csdn.net/mynamepg/article/details/81044957

    (不过大概是因为我的服务器是个centos的缘故,我的服务器的my.cnf文件路径与博客中的不同……用find命令找一下会发现my.cnf就直接在etc文件夹里放着……)

    四、将涉及到中文的字段的编码格式手动改成utf-8

    参见百度经验https://jingyan.baidu.com/article/17bd8e527b9b5785ab2bb892.html

    我的服务器没有可视化界面,因此采用的是该篇经验最后的执行SQL语句的方案

    第四步执行完成后……我的……中文……编码……问题……终于……解决了……(趴)


    碎碎念:

    至于为什么折腾了快八个小时呢?

    我的Java后台在Ubuntu的Idea上写……但是微信小程序开发工具和xshell、xftp都在Windows上……

    所以每次修改完后台以后都要发布war包然后挂到服务器上,然后切换到windows系统上进行检验,有不对的地方再切回Ubuntu

    我这一下午重启了10+次吧……电脑启动还很慢……太痛苦了!!!!!!!

    简直了!!!!简直了!!!简直了!!简直了!

    这个环境等我闲下来我一定整合一下……

     
  • 相关阅读:
    Dynamically allocated memory 动态分配内存【malloc】Memory leaks 内存泄漏
    const pointers
    heap是堆,stack是栈
    Java中使用Cookie
    Postman注册、登录、导出、导入
    HttpServletRequest get post 入参
    判断设置的时间是否大于当前时间
    JS回车登录
    一个普通的Ajax
    Java工具类
  • 原文地址:https://www.cnblogs.com/Briddle-ch/p/10987450.html
Copyright © 2011-2022 走看看