澳门新葡萄京娱乐场 8

澳门新葡萄京娱乐场JSP+ MySQL中文乱码问题post提交乱码解决方案

写了两个jsp页面index.jsp和mysql_insert.jsp。数据处理流程为:在浏览器(chrome)上访问index.jsp后在其表单上输入数据,提交至mysql_insert.jsp,mysql_insert.jsp首先将接收到的数据按变量存入MySQL的html_db数据库的person_tb中(该表原有部分数据),然后mysql_insert.jsp再拿出该表中所有数据显示在mysql_insert.jsp页面上。

来源:

现在发现,当提交的数据中含有中文(比如变量姓名的值为中文)时,mysql_insert.jsp页面上显示新增的那条记录中的相应中文(姓名的值)乱码,其他数据都显示正常,查看数据库,发现也是相应的含有中文的变量值(姓名的值)乱码。乱码情况如下图:
澳门新葡萄京娱乐场 1 
index.jsp中第一行有语句:
,在浏览器(chrome)中访问此页面时无乱码(主要指中文乱码,英文乱码现象还没遇见过)。(试过将gb2312换成utf-8,访问后中文乱码)
mysql_insert.jsp中第一行有语句:,在浏览器中直接访问此页面时无乱码。
mysql_insert.jsp页面的代码如下:
复制代码 代码如下:

       

add message into table

 

String id=request.getParameter(“id”); //从表单获得
String name=request.getParameter(“name”); //从表单获得
String sex=request.getParameter(“sex”); //从表单获得
String age=request.getParameter(“age”); //从表单获得
try
{
/** 连接数据库参数 **/
String driverName = “com.mysql.jdbc.Driver”; //驱动名称
String DBUser = “root”; //mysql用户名
String DBPasswd = “123456”; //mysql密码
String DBName = “html_db”; //数据库名

第一  java源代码文件编码

String connUrl = “jdbc:mysql://localhost/” + DBName + “?user=” + DBUser

保存文件必须以一种编码存;读文件也必须以一种编码读,如不特别设置,去系统默认的编码,中文windows为GBK编码。
    
从.java->.class过程是,先编写.java文件并按某种编码方式保存,然后用javac方法编译此文件,注意如.java没按系统默认编码保存则要带encoding参数指明实际编码,否则出错,生成的.class文件存为系统默认编码。
    
从.jsp->.java->.class,先存为某种编码的.jsp文件,然后tomcat根据pageEncoding读取并转化为servlet存为系统默认编码,然后同上面.java->.class过程。
第二eclipse开发环境对源代码文件编码的影响

  • “&password=” + DBPasswd;
    Class.forName(driverName).newInstance();
    Connection conn = DriverManager.getConnection(connUrl);
    Statement stmt = conn.createStatement();
    stmt.executeQuery(“SET NAMES UTF8”);
    String insert_sql = “insert into person_tb values(‘” + id + “‘,'” +
    name + “‘,'” + sex + “‘,'” + age + “‘)”;
    String query_sql = “select * from person_tb”;

IDE的encoding为对系统下文件打开的解码方式或保存的编码方式。特例:如果.jsp文件有<%@
page language=”java”
pageEncoding=”UTF-8″%>,则eclipse会自动存为UTF-8方式,不管eclipse的encoding是什么,这也是eclipse的聪明之处。
第三 jsp源代码文件编码
pageEncoding=”UTF-8″表示此文件的编码方式,必须与此文件存储方式一致(所以eclipse会首选根据它来存文件),

try {
stmt.execute(insert_sql);
}catch(Exception e) {
e.printStackTrace();
}
try {
ResultSet rs = stmt.executeQuery(query_sql);
while(rs.next()) {
%>
ID:
姓名:
性别:
年龄:
}
}catch(Exception e) {
e.printStackTrace();
}
//rs.close();
stmt.close();
conn.close();
}catch (Exception e) {
e.printStackTrace();
}
%>

<%@ page language=”java” pageEncoding=”UTF-8″%> 
表示JSP文件编码方式,web容器tomcat根据这个来读此.jsp文件并编译为servlet。

我的数据库设置的是全部使用UTF-8编码,如下图:
澳门新葡萄京娱乐场 2 
我的虚拟目录下的web.xml内容如下:
澳门新葡萄京娱乐场 3 
tomcat/conf目录下的server.xml文件的内容如下:
复制代码 代码如下:

第四  servlet生成html文件编码方式

type=”org.apache.catalina.UserDatabase”
description=”User database that can be updated and saved”
factory=”org.apache.catalina.users.MemoryUserDatabaseFactory”
pathname=”conf/tomcat-users.xml” />

<%@ page contentType=”text/html;charset= “UTF-8″%>
contentType=”text/html;charset=UTF-8″表示当浏览器得到此文件时以什么方式解码。例:

connectionTimeout=”20000″
redirectPort=”8443″ />

 

resourceName=”UserDatabase”/>

<%@ page language="java" pageEncoding="UTF-8"%>
<%@ page contentType="text/html;charset=iso8859-1"%>
<html>
<head>
<title>test</title>
</head>
<body>
我是个好人
</body>
</html>

prefix=”localhost_access_log.” suffix=”.txt”
pattern=”%h %l %u %t “%r” %s %b” />

会产生乱码,因为存为UTF-8的文件被解码为iso8859-1,这样
如有中文肯定出乱码。
至此,页面应为:
 

tomcat/conf目录下web.xml文件的主要内容如下:
复制代码 代码如下:

<%@ page language="java" pageEncoding="UTF-8"%>
<%@ page contentType="text/html;charset=UTF-8"%>
<html>
<head>
<title>中文问题</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
</head>
<body>
我是个好人
</body>
</html>

xmlns:xsi=””
xsi:schemaLocation=”

version=”3.0″>

第四,request与response编码设置方式
request.setCharacterEncoding(“UTF-8”)是把提交内容的字符集设为UTF-8
response.setCharacterEncoding(“UTF-8”)可以把页面中的<%@ page
contentType=”text/html;charset=iso8859-1″%>

default
org.apache.catalina.servlets.DefaultServlet

第五,java连接数据库编码 

debug
0

1、mysql配置文件:
修改mysql在windows/my.ini里default-character-set=utf-8
2、mysql里数据库和表也都设为utf8_unicode_ci
3、数据库连结:jdbc:mysql://localhost/mydb?useUnicode=true&characterEncoding=utf-8
注意,关键就在于此:此句中间是’&’不是’&’这是因为数据库连结时,在.jsp和.java文件中应该用&号,而XML文件中需要用&
对于Web容器来说,如果你不设置,默认是ISO8859-1
String des = new String(s.getBytes(“iso8859-1″),”UTF-8”);都可以使用这个
不论哪里,有乱码就是用

listings
false

第六页面请求的编码(表单的get提交、表单的post提交、页面链接传递中文参数、地址栏中参数直接输入中文提交) 

1

请求响应的全过程:

jsp
org.apache.jasper.servlet.JspServlet

浏览器 IE/FireFox
———–>Servlet容器————————>显示页面

fork
false

       编码                           使用容器的URIEncoding转码
             解码

xpoweredBy
false

换为charset=UTF-8,是给告诉浏览器我这个文件的编码方式。
一共四种方式:表单的get提交、表单的post提交、页面链接传递中文参数、地址栏中参数直接输入中文提交。

3

无论何种表单提交都可以在后台的java文件中通过String des = new
String(s.getBytes(“iso8859-1″),”UTF-8”);来转换成你想要的UTF-8编码方式。

default
/

1.     表单get方式提交

jsp
*.jsp
*.jspx

        
浏览器根据页面的charset编码方式对页面进行编码,然后提交至服务器,首先进入对应的字符编码过滤器(如果有的话),不过Tomcat6.0对于get提交方式采用的是server.xml文件中的URIEncoding编码方式,而并不会采用过滤器中设置的编码,那么根据我的环境设置,jsp页面都使用UTF-8的编码,Servlet容器的URIEncoding也设置为UTF-8,则servlet不用进行转码即可正确解码,获得正常的中文字符串。那么,响应页面的中文因为页面的统一编码(UTF-8)自然也会正常显示。当然,如果我们Tomcat的URIEncoding设置为其他非UTF-8的编码方式时,页面的内容进入Tomcat解析时,因为Tomcat和页面的编码不统一,就需要转码。例如,如果我们采用Tomcat默认的ISO-8859-1,那么当我们使用request.getParameter(“yourVariable
“)获取表单参数值时其实Servlet就进行了转码,方式为UTF-8–>ISO-58859-1(我的页面charset都是UTF-8),类似于这样

30

new String(变量值.getBytes("UTF-8"),"ISO-8859-1");  

index.html
index.htm
index.jsp

例如表单的username属性以字符串”编辑”提交,那么进入容器后,FormBean中的这个变量会乱码,request.getParameter(username)一样的效果,s1就是request返回的结果,下面是内存快照。
   澳门新葡萄京娱乐场 4

现在我能想到的设置编码的地方也就只有这么多了,其他还有哪里需要设置编码?恳求指导。
哈哈哈,经过我的一番苦苦探索,终于找到乱码的原因了,当然乱码问题也被解决了。师兄对我建议所有编码全部使用UTF-8,因此我也建议读者也这样做,好处很多。
下面我介绍下我的解决过程:
第一步:在我发现有乱码后,我首先想到的就是是不是我在某个地方设置的编码错误导致的,而MysQL里的设置是正确的(my.ini里设置),就是全部设置为utf8。所以MySQL下的设置我不需要修改。
第二步:然后就是tomcat了,这东西要对我提交的数据进行处理,网上有许多人提出需要设置web.xml和server.xml里面的编码,其中主要是在server.xml里添加URIEncoding=”UTF-8″,具体设置为:。在我完成这一步的设置之后再次测试,发现还是乱码。保留这一步的修改,进行下一步。
第三步:再次回到.jsp页面,我试着将所有涉及到编码和字符集的地方都设置为UTF-8(我之前在index.jsp中首行写的是
,现在使用dreamweaver打开index.jsp将其修改为charset=utf-8),然后在浏览器直接访问index.jsp发现中文有乱码,于是关闭dreamweaver,使用myeclipse重新打开index.jsp文件,发现代码中的中文就是乱码,果断修改成正确的中文字符,同时保留刚才对charset的修改,即仍然使用charset=utf-8,然后重新在浏览器访问index.jsp,终于中文字符正常显示了。(以后从此告别dreamweaver,害我饶了好多路)然后我在index.jsp页面上输入中文数据并提交,依然是中文乱码。做了这一步的修改后,我的两个.jsp文件的头部均有如下两句:

不过即使这样,我们依然可以使用不恰当的方法显示正常的中文,即逆向转码,例如上面的乱码,我们可以通过ISO8859-1–>UTF-8这种方式还原我们提交时的中文。以下是GBK,UTF-8,ISO-8859-1三者之间互相转换的内存快照:
    澳门新葡萄京娱乐场 5

第四步:我刚才在想,到底是往数据库存数据时导致的乱码还是从数据库取数据时导致的乱码呢?再或者是在提交后传输数据到mysql_insert.jsp页面时导致的乱码?然后我直接在数据库中插入一条含有中文字符的数据,然后在浏览器直接访问mysql_insert.jsp,发现中文字符能正常显示。那就是说,是在存数据,或者传输数据时乱码的了。那么该怎么设置才能不至于传数据、存数据不乱码呢?
第五步:网上找了下,找到如下内容,非常有用:
1、jsp页面的编码方式有两个地方需要设置:
复制代码 代码如下:

我们可以看到,偶数汉字可以在UTF-8,GBK两者中互相转换,而奇数个汉字则不能。综上看来,貌似Tomcat的URIEncoding设置为UTF-8是最好的解决办法,不过这样的设置依然无法解决上面我所说的第三、第四种情况。大家继续向下看。(这里有一点我不确定,就是页面提交至Servlet容器时,是以页面的charset方式编码后直接进入容器,还是以charset转码为ISO-8859-1方式进入,大家有什么见解?)
2.表单的post提交

其中:pageEncoding
指的是jsp文件本身在本地保存时的编码方式。contentType的charset是指服务器发送网页内容给客户端时所使用的编码。
从第一次访问一个jsp页面开始,到这个页面被发送到客户端,这个Jsp页面要经过三次编码转换:
第一阶段是jsp编译成.java,它会根据pageEncoding的设定读取jsp,结果是由指定的编码方案翻译成统一的UTF-8
JAVA源码(即.java),如果pageEncoding设定错了,或没有设定,出来的就是中文乱码。
第二阶段是由JAVAC的JAVA源码至java
byteCode的编译,不论JSP编写时候用的是什么编码方案,经过这个阶段的结果全部是UTF-8的encoding的java源码。
JAVAC用UTF-8的encoding读取java源码,编译成UTF-8
encoding的二进制码(即.class),这是JVM对常数字串在二进制码(java
encoding)内表达的规范。
第三阶段是Tomcat(或其的application
container)载入和执行阶段二的来的JAVA二进制码,输出的结果,也就是在客户端见到的,这时隐藏在阶段一和阶段二的参数contentType就发挥了功效
所以最终的解决方法为:
在jsp页面设置pageEncoding或者contentType的其中一个为支持中文的编码格式(如utf-8,gbk,gb2312)。因为设置一个的话,另一个默认会和它一样。
如果两个都设置的话,必须保证两个都是支持中文编码(不一定要一样)。
最佳建议设置如下:

对于这种方式的请求,request.setCharacterEncoding(“一般来自于web.xml中过滤器设置的参数”)方法进行编码设置将会产生作用,struts的表单提交方式默认为post方式,那么按照上面我的环境设置,页面,容器,都采用UTF-8编码方式,就不会产生中文乱码问题。

2、post方式传值乱码:
由于post方式传值是通过request存储的,在另一个页面也是通过request.getParameter(String
name)来提取信息,所以这种情况下的乱码主要是因为request存储信息的编码设置导致的。post提交时,如果没有设置提交的编码格式,则会以iso8859-1方式进行提交,接受的jsp却以utf-8的方式接受。所以使用如下语句即可得到单个正确的中文字符串:String
str = new
String(request.getParameter(“something”).getBytes(“ISO-8859-1″),”utf-8”)
;
解决方法:
一、在接收页面设置request.setCharacterEncoding(“UTF-8”)。
二、最好通过过滤器实现每个页面都设置为request.setCharacterEncoding(“UTF-8”)。
三、在发送数据的页面使用语句指定使用UTF-8格式发送数据。
3、get方式传值乱码:
get方式传值有两种,一种是表单get传值,另一种是url地址传值(实质上这两种方式都是通过url参数的方式传值)。
表单方式get传值:
表单方式get传值的编码过程为,首先浏览器根据页面的charset编码方式对传值进行编码,然后提交至服务器交给tomcat,tomcat对这些信息进行解码时,采用的解码方式是由server.xml文件中的URIEncoding设置决定的,也就是说,当我们使用命令request.getParameter(“”)获取表单参数值时,得到的字符串,经过了charset的编码和URIEncoding的解码。

程序加上org.springframework.web.filter.CharacterEncodingFilter过滤器. 

由上所知,只要charset的编码和URIEncoding的解码一致,并且支持中文,就能保证没有乱码。
  设置URIEncoding的方法如下:
  方法一:
  修改$TOMCAT/conf/server.xml文件,在HTTP Connector或者AJP
Connector的配置加上URIEncoding=”UTF-8″
复制代码 代码如下:
<… maxthreads=”150″ minsparethreads=”25″
maxsparethreads=”75″>enableLookups=”false” redirectPort=”8443″
acceptCount=”100″
connectionTimeout=”20000″ disableUploadTimeout=”true”
URIEncoding=”UTF-8″ />

<filter> 
<filter-name>encodingFilter</filter-name> 
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> 
<init-param> 
<param-name>encoding</param-name> 
<param-value>UTF8</param-value> 
</init-param> 
<init-param> 
<param-name>forceEncoding</param-name> 
<param-value>true</param-value> 
</init-param> 
</filter> 
<filter-mapping> 
<filter-name>encodingFilter</filter-name> 
<url-pattern>*.html</url-pattern> 
</filter-mapping> 
<filter-mapping> 
<filter-name>encodingFilter</filter-name> 
<url-pattern>*.jsp</url-pattern> 
</filter-mapping> 

 方法二:
  使用useBodyEncodingForURI=”true”.
这个方法适合你的TOMCAT实例下需要跑多个不同Encoding的程序时。
复制代码 代码如下:
<… maxthreads=”150″ minsparethreads=”25″
maxsparethreads=”75″>enableLookups=”false” redirectPort=”8443″
acceptCount=”100″
connectionTimeout=”20000″ disableUploadTimeout=”true”
useBodyEncodingForURI=”true” />
enableLookups=”false” redirectPort=”8443″ protocol=”AJP/1.3″
useBodyEncodingForURI=”true” />

因为规范要求浏览器提交数据都要用utf8编码,所以这里设置编码方式为UTF8. 

在Tomcat配置中,连接器(HTTP Connector)属性中有一个URIEncoding和
  useBodyEncodingForURI属性,这两个属性设置对URL后的附加参数进行URL解码时该如何选择
字符集编码。URIEncoding用于制定URL后的附加参数的字符集编码,useBodyEncodingForURI
则说明是否采用实体内容的字符集编码设置来替代URIEncoding的设置,也就是说当
useBodyEncodingForURI属性设置为true时ServletRequest.setCharacterEncoding方法设置的字符集编码也影响getParameter等方法对URL地址后的参数进行URL解码的结果。(在/%TomCat_Home%/
confserver.xml文件中找到
标记,然后在后面加上useBodyEncodingForURI=true)
  url方式get传值乱码:
  于这种方式,浏览器不会采用页面的charset方式对URL中的中文进行编码后提交至服务器(IE,FireFox都一样),而是采用系统的GBK转码为ISO-8859-1之后提交至服务器tomcat,所以这个过程为:
  首先,url地址中的中文被从gbk转换成ISO-8859-1,交给tomcat后,又被tomcat根据URLEcoding解码,这种情况,只有把URLEcoding设置为gbk才能在request.getParameter(“”)时不出现乱码。但是这样就会影响到上面的配置,所以一个好的解决方法是,使用java.net.URLEcoder和URLDecoder对地址中的中文进行手动编码和解码。
  所以一个万全的解决方法为:
  1)所有页面的charset设置为UTF-8。
  2)Tomcat的URIEncoding默认是ISO-8859-1,而我设置为UTF-8,主要是想解决中文命名的文件以及请求以get方式提交有可能出现的乱码问题。
  3)添加过滤器,调用request.setCharacterEncoding(“utf-8”)方法将request的字符集设定为utf-8,解决请求以post方式提交的乱码问题。
  4)url地址中存在中文参数时,首先对中文参数使用URLEcoder编码为utf-8,然后在request.getParameter(“”)接收到参数后再使用URLDecoder还原。例如:
  from.jsp页面:
复制代码 代码如下:
username = URLEncoder.encode(username,”utf-8″);
%>
转入

特别注意: 
a,这个过滤器只是简单的调用:request.setCharacterEncoding(this.encoding); 
在这个语句之前不能调用任何的request.getParameter()方法,否则会设置tomcat的缺省字符集为”ISO-8859-1″,并且使setCharacterEncoding的调用失效.所以在这个过滤器之前的过滤器中不能有对getParameter这类方法的调用,比较安全的做法就是把这个过滤器尽量靠前放. 
b,在server.xml中不能加上<Valve
className=”org.apache.catalina.valves.RequestDumperValve”/> 
这个value也设置tomcat的缺省字符集为”ISO-8859-1″,使setCharacterEncoding的调用失效.可能其他的value也有这个问题,我没有测试过. 
如果要观察http请求参数,可以考虑用抓包工具,例如ethereal或者wireshark
3.页面链接中传递中文参数

to.jsp页面
复制代码 代码如下:

我虚拟一个这样的场景,请求页面中有如下代码

总之 ,乱码的解决方案如下:
  post传值乱码时,在接收端设置request.setCharacterEncoding(“UTF-8”)
  get传值或者url乱码时,手动设置接收的参数String str = new
String(request.getParameter(“something”).getBytes(“ISO-8859-1″),”utf-8”)
;
  由上可见get,post传值在tomcat5中是不一样的.
看完了上面红字部分的内容,我决定在提交数据的页面设置以UTF-8的格式提交数据,而同时在接收数据的页面设置也以UTF-8接收数据,于是我在两个页面的首部都添加了如下语句:
request.setCharacterEncoding(“UTF-8”);
response.setCharacterEncoding(“UTF-8”);
response.setContentType(“text/html; charset=utf-8”);
%>

Html代码

然后测试,OK了!没有乱码了!
现在,index.jsp页面的代码如下:
复制代码 代码如下:

<%   
String username = "编辑";   
%>  
<a href="hello.do?username=<%=username%>">页面中链接传递中文</a>  

request.setCharacterEncoding(“UTF-8”);
response.setCharacterEncoding(“UTF-8”);
response.setContentType(“text/html; charset=utf-8”);
%>

对于这种方式,我们需要先将参数使用统一的编码方式编码,将编码后的字符放入链接,这里我对参数以UTF-8方式编码,如下

ID :
姓名 :
性别 :
年龄:

<%   String username = java.net.URLEncoder.encode("编辑","UTF-8");   %>  

那么这样我们也不会产生中文乱码问题

如果是页面超连接连接中带的汉字,则编码根据页面编码的不同而不同,如果页面的 
content=”text/html;
charset=utf-8″,则在tomcat/conf/server.xml中的配置文件中: 

<!-- Define a non-SSL Coyote HTTP/1.1 Connector on port 8080 --> 
<Connector port="8080" 
maxThreads="150" minSpareThreads="25" maxSpareThreads="75" 
enableLookups="false" redirectPort="8443" acceptCount="100" 
debug="0" connectionTimeout="20000" useBodyEncodingForURI="true" 
disableUploadTimeout="true" /> 

加上:useBodyEncodingForURI=”true”即可正常使用getParameter取出正确内容. 
如果content=”text/html; charset=GBK”,需用 
new
String(request.getParameter(“something”).getBytes(“ISO-8859-1″),”GBK”) 
取出,其他情况类似

4.     地址栏中参数直接输入中文提交

     从地址栏直接输入汉字,则一般编码为”GBK”,需要用 
new
String(request.getParameter(“something”).getBytes(“ISO-8859-1″),”GBK”) 取出 
例如浏览器地址栏中输入”

澳门新葡萄京娱乐场 6

我们可以看到“编辑”经过从GBK–>ISO-8859-1–>UTF-8的过程后得到的就是�༭这样的结果,这里我们还会想到那进行2次逆向转码看看,不过可惜的是,结果为“锟洁辑”。对于这种情况,我们的解决办法就是,Tomcat的URIEncoding采用默认的ISO-8859-1字符集,那么我们可以在程序中通过ISO-8859-1–>GBK这样不恰当的逆向转码方式得到正常的中文“编辑”,但这样的结果是,我们get请求方式的中文处理解决办法就需要改变。如,在我的环境下就需要进行ISO-8859-1–>UTF-8的转码,挺不爽。

综上,对于乱码问题,前三种方式是一般用户的请求方式,第四种属于非正常途径的请求方式,对于这种方式产生的问题我认为无法很好的解决,也不需要解决。我看到javaeye对于这样的情况就没有处理,不知道大家在自己的项目中是如何处理的?我的实验是,IE6的设置会影响应用路径的编码方式,例如地址栏中请求一个中文JSP页面,如:

  澳门新葡萄京娱乐场 7

如果取消IE的这个选项,那么浏览器会以GBK编码应用路径的中文,得到的结果如图:
   澳门新葡萄京娱乐场 8

按照我上面的设置,这里如果将Tomcat的URIEncoding设置为GBK,则也可以正常显示页面。对于FireFox3.0,则是以UTF-8编码。
总结: 
1,所有页面使用utf8编码, 
2,服务器加上过滤器, 
3,server.xml中不要使用 
<Valve
className=”org.apache.catalina.valves.RequestDumperValve”/> 
4,server.xml文件加上useBodyEncodingForURI=”true” 
这样应该可以搞定大多数前台的中文问题.至于地址栏输入中文,不支持也罢,一般的程序很少要求 
从这里输入.

发表评论

电子邮件地址不会被公开。 必填项已用*标注