天突然想到之前的一个项目,是和另一个公司合作,我提供后台,对方写小程序调用我的接口,我本地测试好接口后,是没有问题的,然后部署到对方服务器(windows系统),接着就是出先各种各样的乱码问题,在这里汇总记录下,以便后面学习。
java乱码出现的问题有很多,这里主要记录下tomcat,log4j,mysql,jsp,html,http(get,post请求乱码处理)。常见的问题可能是tomcat,http请求乱码问题了,至于jsp和html的乱码问题就很简单了,相信大家也知道,我也就不多说了,首先来说下tomcat的乱码问题,
一个是程序需要发送http GET请求到服务器,请求的参数中包含了中文字符。程序中参数为UTF-8格式,且经过了UTF-8 URL编码再发送。使用的tomcat服务器,但服务器端后台程序中取到的参数的中文是乱码。
解决办法:修改Tomcat的Server.xml,在Connector标签中加上URLEncoding参数。
<Connector port="8080" maxThreads="150" minSpareThreads="25" maxSpareThreads="75" enableLookups="false" redirectPort="8443" acceptCount="100" debug="99" connectionTimeout="20000" disableUploadTimeout="true" URIEncoding="UTF-8"/>
另一个是tomcat控制台打印乱码,程序中输出到tomcat控制台的中文信息乱码了,
解决办法:打开文件/tomcat/bin/catalina.bat,然后设置set JAVA_OPTS=的内容中添加选项-Dfile.encoding=UTF-8即可,当然,我不敢包证,但是我的就是这么处理然后就可以了。
然后是log4j的日志打印乱码,这个乱码也是打印在tomcat控制台的时候乱码,但是日志文件却不会,而且我本地测试的时候打印也不会乱码
而且我配置的也是utf-8,这个曾经让我恼火好久,后面我偶然在一篇博客上发现,说有些服务器你配utf-8是不行的,他的是编码就是GBK,我就权当试试,没想到还真是这个问题,这也是让我很无语,,,,
然后就是http请求的乱码,我这个乱码问题是我在shiro判断是否登录的时候,因为我是前后端分离,所以我shiro判断未登录的时候,是返回状态码和提示信息,而不是跳转登录页面,我用response返回中文提示信息是,结果返回的是乱码,可是我明明设置了
res.setCharacterEncoding("utf-8");
可是到前端页面的时候还是乱码了,这让我很费解,后面我仔细想了下,我服务端是设置了返回utf-8的编码,但是浏览器是用utf-8去解析的吗?后面去查了下还要加一条配置,
res.setContentType("text/html;charset=utf-8");
之前知道有这个配置,但是一直不知道有什么区别,今天算是明白了一点,这个就是告诉浏览器,你要用什么编码去解析这个数据。
最后一个是mysql 中文的乱码了,这个着实让我烦恼了好久,我去网上查了,说建表的时候要设置utf-8的编码,可是我在新建数据库的时候就设置了默认就是utf-8的编码,然后我说要配置数据库的默认编码,修改mysql配置文件/etc/my.cnf。
[mysqld] character-set-server=utf8 [client] default-character-set=utf8 [mysql] default-character-set=utf8
我设置好这个以后,终于不会乱了,但是,,保存进去的中文居然全部变成了???号,于是又去奔波了,
通过这个命令,我们可以看到,我们服务端居然还不是utf-8???
这让我很伤,终于,寻的良方,
只要在数据库properties文件的连接信息里加两个参数
?useUnicode=true&characterEncoding=utf-8
就可以了,唉,真是一波三折啊,
真是与服务器斗,其乐无穷;与数据库斗,其乐无穷;与浏览器斗,其乐无穷啊
pache Derby 是一个开源的完全使用 Java 语言实现的嵌入式关系型数据库。JDK历史版本中曾经包含了 Derby 版本,叫做 Java DB,但目前 JDK 中已经不再默认包含了。
官网主页:https://db.apache.org/derby/
在更新JDK到21/22版本后,同样也是出现使用控制台执行SQL脚本出现汉字乱码。
D:\db-derby-10\bin>sysinfo
------------------ Java 信息 ------------------
Java 版本: 21.0.2
Java 供应商: Oracle Corporation
Java 主目录: D:\JDK21
Java 类路径: D:\db-derby-10/lib/derbyshared.jar;D:\db-derby-10/lib/derby.jar;D:\db-derby-10/lib/de
rbynet.jar;D:\db-derby-10/lib/derbyclient.jar;D:\db-derby-10/lib/derbytools.jar;D:\db-derby-10/lib/derby
optionaltools.jar
OS 名: Windows 10
OS 体系结构: amd64
OS 版本: 10.0
Java 用户名: chenxd
Java 用户主目录:C:\Users\chenxd
Java 用户目录: D:\db-derby-10\bin
java.specification.name: Java Platform API Specification
java.specification.version: 21
java.runtime.version: 21.0.2+13-LTS-58
--------- Derby 信息 --------
[D:\db-derby-10\lib\derby.jar] 10.17.1.0 - (1913217)
[D:\db-derby-10\lib\derbytools.jar] 10.17.1.0 - (1913217)
[D:\db-derby-10\lib\derbynet.jar] 10.17.1.0 - (1913217)
[D:\db-derby-10\lib\derbyclient.jar] 10.17.1.0 - (1913217)
[D:\db-derby-10\lib\derbyshared.jar] 10.17.1.0 - (1913217)
D:\db-derby-10\bin>startNetworkServer
Tue May 14 10:47:20 CST 2024 : Apache Derby 网络服务器 - 10.17.1.0 - (1913217) 已启动并准备接受端口 1527
上的连接
运行ij,插入记录,出现乱码(JDK19及之前未曾出现这个问题):
D:\db-derby-10\bin>ij -p ij.properties
ij>connect 'chendb';
ij> drop table zipcodes;
ij> create table zipcodes(zipcode varchar(6), university varchar(20), city varchar(10));
ij> insert into zipcodes values ('100044', '北京交通大学', '北京');
ij> insert into zipcodes values ('200030', '上海交通大学', '上海');
ij> select * from zipcodes;
ZIPCO&|UNIVERSITY |CITY
--------------------------------------
100044|?????????? |????
200030|????????? |???
基于上回Java输入输出文件乱码的经验,基本确定就是控制台字符集(GBK)和数据库字符集(UTF-8)编码不一致,需要修改ij运行时的字符集为GBK。由于ij运行时,实际是用java命令指定类名运行的,可以使用运行时指定 ”-Dderby.ui.codeset=GBK“ 来修改字符集为“GBK”。为了方便使用,直接使用配置文件ij.propertis,在其中加入字符集相关的属性定义:
ij.driver=org.apache.derby.jdbc.ClientDriver
ij.protocol=jdbc:derby://localhost:1527/
#解决JDK21后,命令行汉字输入乱码问题
#默认命令行字符集为GBK(代码页936)而非UTF-8(代码页 65001)
#https://www.rfc-editor.org/rfc/rfc5646.html
derby.ui.locale=zh-Hans
derby.ui.codeset=GBK
重新运行ij:
D:\db-derby-10\bin>ij -p ij.properties
ij 版本 10.17
ij> connect 'chendb';
ij> insert into zipcodes values ('100044', '北京交通大学', '北京');
已插入/更新/删除 1 行
ij> select * from zipcodes;
ZIPCO&|UNIVERSITY |CITY
--------------------------------------
100044|?????????? |????
200030|????????? |???
100044|北京交通大学 |北京
已选择 3行
ij>
至此成功解决乱码问题。
14_HttpRunner中文乱码问题_01_悟空CRM 断言中文失败显示乱码_原因分析
测试目的:
通过浏览器登录成功后,进入系统首页,查看源代码,准备把标题文字作为断言用例执行是否成功的标志。
编写测试用例如下:
- config:
name: 悟空CRM
- test:
name: 登录
request:
url: http://192.168.1.102/72crm/index.html#/workbench/index
method: POST
data:
username: 13888888888
password: 123456
validate:
- eq: [status_code, 200]
- eq: [<title>(.*)CRM</title>, 悟空]
执行测试用例,直接失败 :(
看看错误提示,发现是第二个断言,即标题的断言失败了。
再仔细看输出,实际结果提取出来的是乱码,到这里就基本清楚了,字符编码问题!!
我们编写用例使用的是 UTF-8 字符编码方式,这种方式下对常见中文的编码规律是,每个汉字被编码为三个字节,“悟空”是两个汉字,编码后对应六个字节,数数乱码的字符数量,正好也是六个。
这六个乱码是什么鬼。别着急,我们详细分析一下。
这里我使用的常见的 EditPlus 文本编辑工具,新建一个空白文本文件,输入“悟空”二字,并保存为“UTF-8”编码方式(注意:这是重点! 重点!)
保存成功后,直接查看文件内容的十六进制编码。
“悟空”二字的 UTF-8 编码是: E6 82 9F E7 A9 BA 共六个字节
正常情况下,用UTF-8方式进行编码,则解码也必须是UTF-8方式,即编码和解码一致,否则就会出现乱码。我们通过HttpRunner执行测试用例,返回的HTTP响应数据(即HTML文件)中,标题位置直接就输出了乱码(见截图中划绿线的红色错误提示部分)。那么HttpRunner到底用的什么方式进行解码呢?一般情况下,尤其是英文的软件,都默认习惯使用ISO8859-1的字符编码方式。
我们知道最早的字符编码是 ASCII 码,共表示128个字符,每个字符占用1B(1个字节)的大小,但实际只使用了其中的7位,高位补了0,如字符 'A'的编码是 '0100 0001',最高位是一个0来占位的。
后续有些国家和地区对 ASCII 码进行了扩展,即把最高位的0给使用了,这样就可以表示256个字符。但是这些扩展互相间不兼容。
在 Windows 中运行命令:charmap ,打开字符映射工具,字符集分别选中“Windows 西欧”和“Windows中欧”,可以清楚的看到,从 0X80 编码以后(即扩展出来的字符内容),二者出现很大的不同,西欧字符集中的一些字符,在中欧字符集中就根本没有出现。也就是说,同样的编码如果使用不同的字符集解码,可能产生不同的字符显示,这就是乱码形成的很大根源,说白了就是一句话:编码和解码不一致。
于是大牛出现了- ISO(国际标准化组织),他制定了一套统一的标准,即 ISO8859 字符集系列,分别把西欧、东欧、南欧、北欧等字符集分别编号为 ISO8859-1、ISO8859-2、ISO8859-3、ISO8859-4等。其中,最常用的就是 ISO8859-1 西欧这个标准,也称Latin-1。
由于“悟空”二字的 UTF-8 编码是: E6 82 9F E7 A9 BA ,这六个字节如果用西欧的 ISO8859-1来一个字节一个字节的解码,每个字节就对应了一个西欧的字符。这些字符就是我们从错误提示信息中所看到的乱码了。
*请认真填写需求信息,我们会在24小时内与您取得联系。