在公司做的项目一般都是英文的,也就是默认的拉丁字符集 ISO-8859-1。在今天做的J+S+H应用中,我想插入保存一个中文的用户名,可是不管怎么样保存,都是问号形式的乱码。
乱码问题一直是个比较头疼而又常见的问题,困扰着我们这些实用Unicode的群众。在Java Web应用中,乱码一般会出现在页面JSP显示层或者数据库持久层。对于前者,我们一般是注意在页面的头部代码中加入
<%@page contentType="text/html;charset=GB2312"%>
或者
<%@page contentType="text/html"%>
<%@page pageEncoding="UTF-8"%>
如果依旧不行,考虑到对request中的数据进行一个ISO-8859到Unicode字符集的转换过程,一般都是通过一个Filter来实现,如下面的样例代码:
package com.array.dinner.utils;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
public class SetCharacterEncoding implements Filter {
protected String encoding = null;
protected FilterConfig filterConfig = null;
protected boolean ignore = true;
public void destroy() {
this.encoding = null;
this.filterConfig = null;
}
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
// Conditionally select and set the character encoding to be used
if (ignore || (request.getCharacterEncoding() == null)) {
String encoding = selectEncoding(request);
if (encoding != null)
request.setCharacterEncoding(encoding);
}
// Pass control on to the next filter
chain.doFilter(request, response);
}
public void init(FilterConfig filterConfig) throws ServletException {
this.filterConfig = filterConfig;
this.encoding = filterConfig.getInitParameter("encoding");
String value = filterConfig.getInitParameter("ignore");
if (value == null)
this.ignore = true;
else if (value.equalsIgnoreCase("true"))
this.ignore = true;
else if (value.equalsIgnoreCase("yes"))
this.ignore = true;
else
this.ignore = false;
}
protected String selectEncoding(ServletRequest request) {
return (this.encoding);
}
}
对应的web.xml的配置应该添加一下Filter声明:
<filter> <filter-name>setCharacterEncoding</filter-name> <filter-class>com.array.dinner.utils.SetCharacterEncodingFilter</filter-class> <init-param> <param-name>encoding</param-name> <param-value>gb2312</param-value> </init-param> </filter> <filter-mapping> <filter-name>setCharacterEncoding</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
但是,当我跟踪到JSF的后台bean中,又能完整地看到变量的完整地中文字符。很明显,是在数据库的持久层上出问题了。仔细检查一下了自己的MySQL数据库,发现所有的表都是建立在UTF-8之上的,数据库本身应该是没有问题的。
顺着想一想,结论马上就浮出水面了,我输入的是中文字符GBK的,而数据库接受的却是UTF-8,数据库方面默认用UTF-8来处理和保存一堆传过来的Unicode字符,但是数据库方面是不知道对方来的数据是什么编码的,所以只能用问号表示“抗议”。所以,这里只需要让数据库了解你的数据包的性质,沟通自然就无问题了。废话少说,你只需要在数据库连接url中这样声明一下,多加两个参数useUnicode和characterEncoding:
jdbc:mysql://localhost:3306/dinner?useUnicode=true&characterEncoding=UTF-8