在Web开发中经常会遇到中文乱码问题。
先系统地说明一下,主要从两个方面:原理,操作。
中文常用的编码格式:GBK 和 UTF-8
而一个完整的Web应用包括:数据库、持久层、控制层、页面显示层。
所以只有在保持四层中编码格式一致即可解决乱码问题。
数据库中,以MySQL为例。
安装时,系统默认编码为latin-1,将其更改为UTF-8。
在MySQL命令行中敲入命令:
mysql> show variables like 'character%';
+--------------------------+-------------------------------------------+
| Variable_name | Value |
+--------------------------+-------------------------------------------+
| character_set_client | utf8 |
| character_set_connection | utf8 |
| character_set_database | utf8 |
| character_set_filesystem | binary |
| character_set_results | utf8 |
| character_set_server | utf8 |
| character_set_system | utf8 |
| character_sets_dir | D:\MySQL\MySQL Server 5.0\share\charsets\ |
+--------------------------+-------------------------------------------+
8 rows in set (0.31 sec)
在linux下修改my.conf文件(/etc/my.conf Windows下是修改my.ini文件)
找到客户端配置[client],在下面添加:
default-character-set=uft8
找到服务器端配置[mysqld],在下面添加:
default-character-set=utf8
init_connect='SETNAMES utf8' (设定连接MySQL数据库时使用UTF-8编码,让MySQL数据库为UTF-8运行)。
修改好后,重新启动MySQL,查询对比一下变量:mysql> show variables like 'character%';
问题主要出在5个环节上:
1. 数据库客户端字符集
2. 数据库连接传输字符集
3. 数据库存储字符集
4. 数据库查询结果字符集
5. 数据库启动字符集
如果上述几个编码为latin-1,则修改为UTF-8。
mysql>set character_set_XXX ='utf8';
数据库建表:
Create database company DEFAULT character set utf8;
Drop TABLE IF EXISTS emp;
CREATE TABLE emp (
ID int(12) not null,
Author varchar(200) not null,
PRIMARY KEY (ID)
) ENGINE=InnoDB DEFAULT charset=utf8;
【说明】一般建表语句都写在SQL脚本中,在Linux系统中可直接在MySQL命令行输入source脚本路径。但当SQL脚本中含有中文时,在Windows系统下建议使用MyEclipse中的DB Browser插件。
持久层(JDBC/Hibernate):
URL=jdbc:mysql://127.0.0.1:3306/company?useUnicode=true;characterEncoding=utf8;
控制层:
request.setCharacterEncoding("utf8");
通过这行代码,在所有请求之前,使得request使用指定的编码方式来编码。
Tomcat容器:
在get请求时需要修改server.xml文件中的配置,给Connector添加一个URIEncoding=utf-8属性。
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8543"
maxHttpHeaderSize="8192"
maxThreads="150" minSpareThreads="25" maxSpareThreads="75"
enableLookups="false" acceptCount="100"
disableUploadTimeout="true"
URIEncoding="gbk"
/>
也可以通过过滤器来实现:
<--filter>
<filter-name>failedRequestFilter</filter-name>
<filter-class>
org.apache.catalina.filters.FailedRequestFilter
</filter-class>
<--/filter>
<filter>
<filter-name>OneFilter</filter-name>
<filter-class>
encoding.EncodeFilter
</filter-class>
</filter>
<filter-mapping>
<filter-name>OneFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
/*
**一般成熟的框架都有写好的编码过滤器
*/
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse resp = (HttpServletResponse) response;
req.setCharacterEncoding("utf-8");
//设置一个响应头,告诉浏览器,应该以什么形式的编码便是其返回的HTML
resp.setContentType("text/html;charset=utf-8");
resp.setCharacterEncoding("utf-8");
chain.doFilter(req,resp);
}
显示层(JSP):
<%@page pageEncoding="utf-8"%>
告诉JSP引擎,在将JSP转换成Servlet源文件时,该JSP文件的编码是什么
<%@page contentType="text/html;charset="utf-8"%>
相当于Servlet中的response.setContentType(),即设置HTTP响应头。
浏览器会依据该编码方式来显示页面。
保存JSP文件时,其真正的编码应该与设置的保持一致。
其他:
浏览器的编码设置为UTF-8。
MyEclipse中项目存储格式设置为UTF-8。