原理介绍:
一:
常见字符集简介
字符集就是字符内码到字符的表现形式之间的映射的集合。ASCII字符A是就内码0x41的表现形式,所以在很多程序语言中,字符变量和整型变量仅在一念之差。
1. ISO8859系列
ISO8859包括诸如ISO8859-1,ISO8859-2之类的一系列字符集,它们都是8位的字符集,0~0x7F仍与ASCII字符集保持兼容,大于0x7F的是各种拉丁字符或欧洲字符的扩展。
2. GB2312字符集
如果像ISO8859系列一样,大于0x7F的字符用来表示汉字,则最多表示128个,这显然不够,于是就有了GB2312标准所产生的字符集,如果当前字节(8 bit)小于0X80,则仍当它为英文字符;如果它大于等于0x80,则它和紧接着它的下一个字节构成一个汉字字符,这样,GB2312字符集可包含大约4000多个常用简体汉字和其他汉字中的特殊符号(如①㈠之类)。其他类似的汉字字符集还有GBK(GB2312的扩展),GB18030,Big5(繁,台湾省用),详细规范介绍可参考:http://www.unihan.com.cn/cjk/ana17.htm
3. Unicode字符集
Unicode字符最初是16位的(出于需要,后来增加了代用对),它和7位的US-ASCII保持兼容,MS的Windows NT/2000/XP和Sun的Java都用它作为默认的字符集,它最初是美国商务联盟的事实上的标准,它遵循国际通用字符(UCS)集标准:ISO/IEC 10646。Unicode的主要目标是提供一个“通用字符集”,这个通用字符集包括世界上所有的语言,字母和文字,所以在Unicode字符集中,不光“I”是字母,“我”也是字母,在写Java时也可以“int 我是中国人 = 0xff;”。毕竟16位的Unicode字符集最多只有216= 65536个字符,还不足以在实际应用中表示所有的字符,而且在以英文为主要信息的互联网时代,它的使用、存储与传输,都极其浪费空间,所以在此基础上出现了UTF-8(Unicode Transformation Form 8-bit form)和UTF-16这两种对Unicode字符编码的规范,在UTF-8中,属于US-ASCII中的字符,仍用一个字节表示,且和US-ASCII兼容,编码其他的字符,则用1(大于0x7F部分)到3个字节。UTF-8的变长性和复杂性,对非ASCII的字符,就不大友好了,也开始违背了Unicode的初衷。而UTF-16则是很简单的编码方式,它完全遵循Unicode标准,用16位的定长空间来表示部分Unicode字符集。关于Unicode的更多规范,请访问Unicode联盟站点:http://www.unicode.org,UTF-8和UTF-16分别定义在IETF的RFC 2279和RFC 2781中,可以通过http://www.ietf.org/rfc2279.txt或http://www.ietf.org/rfc2781.txt访问它们。
一般情况下,字符集名称是大小写不敏感的,所以GB2312也可以写作gb2312或Gb2312。
pageEncoding及contentType的作用:
jsp头部的charset是response的编码方式,也就是响应的编码方式,而request.setCharacterEncoding("GB2312");是请求的编码方式,一个是从客户端到server,一个是server响应给客户端
pageEncoding属性存在,那么JSP页面的字符编码方式就由pageEncoding决定,
否则就由contentType属性中的charset决定,都没有的话默认是ISO-8859-1。
pageEncoding 在JSP标准的语法中,如果pageEncoding属性存在,那么JSP页面的字符编码方式就由pageEncoding决定,否则就由contentType属性中的charset决定,如果charset也不存在,JSP页面的字符编码方式就采用默认的ISO-8859-1。
ContentType
ContentType属性指定了MIME类型和JSP页面回应时的字符编码方式。MIME类型的默认值是“text/html”; 字符编码方式的默认值是“ISO-8859-1”. MIME类型和字符编码方式由分号隔开pageEncoding的内容只是用于jsp输出时的编码,不会作为header发出去的。pageEncoding 是通知web server jsp的编码如果ContentType中指定charset为GBK,而pageEncoding指定UTF-8,这样header中会发送什么数据呢?发送的数据是UTF-8
一个项目全部用的UTF-8编码,好处是再也不用转码了。
资料库输出到jsp出现乱码:
第一,检查一下你database里的资料是否乱码.
如果database里的资料是乱码,检查一下再进入资料库时request接收後资料是否是乱码.
即忘了加入request.setCharacterEncoding(String charset);
request.setCharacterEncoding(String charset)把表单传送过来的资料以charset的字型来encoding.
如果接收时是正常的.但资料库是乱码,
那就检查一下database的编码设定.
如果资料库的资料正常.但输出到jsp的资料是乱码.
以mysql为例:
String connect = "jdbc:mysql://localhost/dbname?user=%26amp;password=%26amp;useUnicode=true%26amp;characterEncoding=GBK";
就上面的mysql的例子.
需要设定useUnicode为true.
而characterEncoding=GBK必须与contentType的charset一样.
mysql的设定档my.ini:
[client] default-character-set=GBK
[mysqld] default-character-set=GBK
二:
在使用JSP的过程中,最使人头疼的一个问题就是中文乱码问题,以下是我在软件开发中遇到的乱码问题以及解决方法。
1、数据库乱码
这种乱码会使你插入数据库的中文变成乱码,或者读出显示时也是乱码,解决方法如下:
在数据库连接字符串中加入编码字符集
String Url="jdbc:mysql://localhost/digitgulf? user=root&password=root&useUnicode=true&characterEncoding=GB2312";
并在页面中使用如下代码:
response.setContentType("text/html;charset=gb2312");
request.setCharacterEncoding("gb2312");
2、JSP页面乱码
这种乱码的原因是应为没有在页面里指定使用的字符集编码,解决方法:只要在页面开始地方用下面代码指定字符集编码即可,<%@ page contentType="text/html; charset=gb2312" language="java" import="java.sql.*" errorPage="" %>
3、中文作为参数传递乱码
当我们把一段中文字符作为参数传递个另一页面时,也会出现乱码情况,解决方法如下:
在参数传递时对参数编码,比如
RearshRes.jsp?keywords=" + java.net.URLEncoder.encode(keywords)
然后在接收参数页面使用如下语句接收
keywords=new String(request.getParameter("keywords").getBytes("8859_1"));
三:Struts 中文乱码问题 Filter解决
原理很简单就是使用Filter处理设置的请求的 CharacterEncoding
具体实现Filter
1、
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;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class SetCharacterEncodingFilter implements Filter {
protected FilterConfig filterConfig;
protected String encodingName;
protected boolean enable;
public SetCharacterEncodingFilter()
{
this.encodingName = "UTF-8";
this.enable = false;
}
public void init(FilterConfig filterConfig) throws ServletException
{
this.filterConfig = filterConfig;
loadConfigParams();
}
private void loadConfigParams()
{
// encoding
this.encodingName = this.filterConfig.getInitParameter("encoding");
// filter enable flag...
String strIgnoreFlag = this.filterConfig.getInitParameter("enable");
if (strIgnoreFlag.equalsIgnoreCase("true"))
{
this.enable = true;
} else {
this.enable = false;
}
}
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) request;
HttpServletResponse httpResponse = (HttpServletResponse) response;
if (this.enable) {
httpRequest.setCharacterEncoding(this.encodingName);
}
chain.doFilter(httpRequest, httpResponse);
}
public void destroy() {
}
}
2、在web.xml里的配置是:
<filter>
<filter-name>Set Character Encoding</filter-name>
<filter-class>filter.SetCharacterEncodingFilter</filter-class >
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>enable</param-name >
<param-value>true</param-value >
</init-param>
</filter>
<filter-mapping>
<filter-name>Set Character Encoding</filter-name >
<servlet-name>action</servlet-name >
</filter-mapping>
apache整合tomcat 中文问题:
apache+tomcat+JK2集成时,http的请求是通过jk2的ajp13转到tomcat的8009端口处理的,
所以要修改tomcat/conf/server.xml中的以下两项
1 <Connector port="8080" …… URIEncoding="GBK" >
2 <Connector port="8009" …… URIEncoding="GBK" >
都加上URIEncoding="GBK"。