JSP+ MySQL中文亂碼問題post提交亂碼解決方案轉(zhuǎn)載 更新時間:2013年08月01日 16:45:34 作者: 我要評論 當(dāng)提交的數(shù)據(jù)中含有中文(比如變量姓名的值為中文)時,mysql_insert.jsp頁面上顯示新增的那條記錄中的相應(yīng)中文(姓名的值)亂碼
寫了兩個jsp頁面index.jsp和mysql_insert.jsp。數(shù)據(jù)處理流程為:在瀏覽器(chrome)上訪問index.jsp后在其表單上輸入數(shù)據(jù),提交至mysql_insert.jsp,mysql_insert.jsp首先將接收到的數(shù)據(jù)按變量存入MySQL的html_db數(shù)據(jù)庫的person_tb中(該表原有部分?jǐn)?shù)據(jù)),然后mysql_insert.jsp再拿出該表中所有數(shù)據(jù)顯示在mysql_insert.jsp頁面上。
現(xiàn)在發(fā)現(xiàn),當(dāng)提交的數(shù)據(jù)中含有中文(比如變量姓名的值為中文)時,mysql_insert.jsp頁面上顯示新增的那條記錄中的相應(yīng)中文(姓名的值)亂碼,其他數(shù)據(jù)都顯示正常,查看數(shù)據(jù)庫,發(fā)現(xiàn)也是相應(yīng)的含有中文的變量值(姓名的值)亂碼。亂碼情況如下圖: index.jsp中第一行有語句:<%@ page contentType="text/html;charset=gb2312"%> ,在瀏覽器(chrome)中訪問此頁面時無亂碼(主要指中文亂碼,英文亂碼現(xiàn)象還沒遇見過)。(試過將gb2312換成utf-8,訪問后中文亂碼) mysql_insert.jsp中第一行有語句:<%@page language="java" pageEncoding="UTF-8"%>,在瀏覽器中直接訪問此頁面時無亂碼。 mysql_insert.jsp頁面的代碼如下: 復(fù)制代碼 代碼如下: <%@page language="java" pageEncoding="UTF-8"%> <%@ page import="java.sql.*" %> <HTML> <HEAD> <TITLE>add message into table </TITLE> </HEAD> <BODY> <% String id=request.getParameter("id"); //從表單獲得 String name=request.getParameter("name"); //從表單獲得 String sex=request.getParameter("sex"); //從表單獲得 String age=request.getParameter("age"); //從表單獲得 try { /** 連接數(shù)據(jù)庫參數(shù) **/ String driverName = "com.mysql.jdbc.Driver"; //驅(qū)動名稱 String DBUser = "root"; //mysql用戶名 String DBPasswd = "123456"; //mysql密碼 String DBName = "html_db"; //數(shù)據(jù)庫名 String connUrl = "jdbc:mysql://localhost/" + DBName + "?user=" + DBUser + "&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"; try { stmt.execute(insert_sql); }catch(Exception e) { e.printStackTrace(); } try { ResultSet rs = stmt.executeQuery(query_sql); while(rs.next()) { %> ID:<%=rs.getString("id")%> </br> 姓名:<%=rs.getString("name")%> </br> 性別:<%=rs.getString("sex")%> </br> 年齡:<%=rs.getString("age")%> </br> </br> <% } }catch(Exception e) { e.printStackTrace(); } //rs.close(); stmt.close(); conn.close(); }catch (Exception e) { e.printStackTrace(); } %> </body> </html> 我的數(shù)據(jù)庫設(shè)置的是全部使用UTF-8編碼,如下圖: 我的虛擬目錄下的web.xml內(nèi)容如下: tomcat/conf目錄下的server.xml文件的內(nèi)容如下: 復(fù)制代碼 代碼如下: <U><?xml version='1.0' encoding='utf-8'?></U> <Server port="8005" shutdown="SHUTDOWN"> <Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" /> <Listener className="org.apache.catalina.core.JasperListener" /> <Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" /> <Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" /> <Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" /> <GlobalNamingResources> <Resource name="UserDatabase" auth="Container" 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" /> </GlobalNamingResources> <Service name="Catalina"> <Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" /> <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" /> <Engine name="Catalina" defaultHost="localhost"> <Realm className="org.apache.catalina.realm.LockOutRealm"> <Realm className="org.apache.catalina.realm.UserDatabaseRealm" resourceName="UserDatabase"/> </Realm> <Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="true"> <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs" prefix="localhost_access_log." suffix=".txt" pattern="%h %l %u %t "%r" %s %b" /> </Host> </Engine> </Service> </Server> tomcat/conf目錄下web.xml文件的主要內(nèi)容如下: 復(fù)制代碼 代碼如下: <U><?xml version="1.0" encoding="UTF-8"?></U> <web-app xmlns="http://java./xml/ns/javaee" xmlns:xsi="http://www./2001/XMLSchema-instance" xsi:schemaLocation="http://java./xml/ns/javaee http://java./xml/ns/javaee/web-app_3_0.xsd" version="3.0"> <servlet> <servlet-name>default</servlet-name> <servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class> <init-param> <param-name>debug</param-name> <param-value>0</param-value> </init-param> <init-param> <param-name>listings</param-name> <param-value>false</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet> <servlet-name>jsp</servlet-name> <servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class> <init-param> <param-name>fork</param-name> <param-value>false</param-value> </init-param> <init-param> <param-name>xpoweredBy</param-name> <param-value>false</param-value> </init-param> <load-on-startup>3</load-on-startup> </servlet> <servlet-mapping> <servlet-name>default</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> <!-- The mappings for the JSP servlet --> <servlet-mapping> <servlet-name>jsp</servlet-name> <url-pattern>*.jsp</url-pattern> <url-pattern>*.jspx</url-pattern> </servlet-mapping> <session-config> <session-timeout>30</session-timeout> </session-config> <此處省略了mime-mapping的內(nèi)容> <welcome-file-list> <welcome-file>index.html</welcome-file> <welcome-file>index.htm</welcome-file> <welcome-file>index.jsp</welcome-file> </welcome-file-list> </web-app> 現(xiàn)在我能想到的設(shè)置編碼的地方也就只有這么多了,其他還有哪里需要設(shè)置編碼?懇求指導(dǎo)。 哈哈哈,經(jīng)過我的一番苦苦探索,終于找到亂碼的原因了,當(dāng)然亂碼問題也被解決了。師兄對我建議所有編碼全部使用UTF-8,因此我也建議讀者也這樣做,好處很多。 下面我介紹下我的解決過程: 第一步:在我發(fā)現(xiàn)有亂碼后,我首先想到的就是是不是我在某個地方設(shè)置的編碼錯誤導(dǎo)致的,而MysQL里的設(shè)置是正確的(my.ini里設(shè)置),就是全部設(shè)置為utf8。所以MySQL下的設(shè)置我不需要修改。 第二步:然后就是tomcat了,這東西要對我提交的數(shù)據(jù)進行處理,網(wǎng)上有許多人提出需要設(shè)置web.xml和server.xml里面的編碼,其中主要是在server.xml里添加URIEncoding="UTF-8",具體設(shè)置為:<Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" URIEncoding="UTF-8" />。在我完成這一步的設(shè)置之后再次測試,發(fā)現(xiàn)還是亂碼。保留這一步的修改,進行下一步。 第三步:再次回到.jsp頁面,我試著將所有涉及到編碼和字符集的地方都設(shè)置為UTF-8(我之前在index.jsp中首行寫的是<%@page language="java" contentType="text/html; charset=gb2312" %> ,現(xiàn)在使用dreamweaver打開index.jsp將其修改為charset=utf-8),然后在瀏覽器直接訪問index.jsp發(fā)現(xiàn)中文有亂碼,于是關(guān)閉dreamweaver,使用myeclipse重新打開index.jsp文件,發(fā)現(xiàn)代碼中的中文就是亂碼,果斷修改成正確的中文字符,同時保留剛才對charset的修改,即仍然使用charset=utf-8,然后重新在瀏覽器訪問index.jsp,終于中文字符正常顯示了。(以后從此告別dreamweaver,害我饒了好多路)然后我在index.jsp頁面上輸入中文數(shù)據(jù)并提交,依然是中文亂碼。做了這一步的修改后,我的兩個.jsp文件的頭部均有如下兩句: <%@ page language="java" pageEncoding="utf-8"%> <%@ page contentType="text/html;charset=utf-8"%> 第四步:我剛才在想,到底是往數(shù)據(jù)庫存數(shù)據(jù)時導(dǎo)致的亂碼還是從數(shù)據(jù)庫取數(shù)據(jù)時導(dǎo)致的亂碼呢?再或者是在提交后傳輸數(shù)據(jù)到mysql_insert.jsp頁面時導(dǎo)致的亂碼?然后我直接在數(shù)據(jù)庫中插入一條含有中文字符的數(shù)據(jù),然后在瀏覽器直接訪問mysql_insert.jsp,發(fā)現(xiàn)中文字符能正常顯示。那就是說,是在存數(shù)據(jù),或者傳輸數(shù)據(jù)時亂碼的了。那么該怎么設(shè)置才能不至于傳數(shù)據(jù)、存數(shù)據(jù)不亂碼呢? 第五步:網(wǎng)上找了下,找到如下內(nèi)容,非常有用: 1、jsp頁面的編碼方式有兩個地方需要設(shè)置: 復(fù)制代碼 代碼如下: <%@ page language="java" import="java.util.*" pageEncoding="utf-8"%> <%@ page contentType="text/html;charset=utf-8"%> 其中:pageEncoding 指的是jsp文件本身在本地保存時的編碼方式。contentType的charset是指服務(wù)器發(fā)送網(wǎng)頁內(nèi)容給客戶端時所使用的編碼。 從第一次訪問一個jsp頁面開始,到這個頁面被發(fā)送到客戶端,這個Jsp頁面要經(jīng)過三次編碼轉(zhuǎn)換: 第一階段是jsp編譯成.java,它會根據(jù)pageEncoding的設(shè)定讀取jsp,結(jié)果是由指定的編碼方案翻譯成統(tǒng)一的UTF-8 JAVA源碼(即.java),如果pageEncoding設(shè)定錯了,或沒有設(shè)定,出來的就是中文亂碼。 第二階段是由JAVAC的JAVA源碼至java byteCode的編譯,不論JSP編寫時候用的是什么編碼方案,經(jīng)過這個階段的結(jié)果全部是UTF-8的encoding的java源碼。 JAVAC用UTF-8的encoding讀取java源碼,編譯成UTF-8 encoding的二進制碼(即.class),這是JVM對常數(shù)字串在二進制碼(java encoding)內(nèi)表達(dá)的規(guī)范。 第三階段是Tomcat(或其的application container)載入和執(zhí)行階段二的來的JAVA二進制碼,輸出的結(jié)果,也就是在客戶端見到的,這時隱藏在階段一和階段二的參數(shù)contentType就發(fā)揮了功效 所以最終的解決方法為: 在jsp頁面設(shè)置pageEncoding或者contentType的其中一個為支持中文的編碼格式(如utf-8,gbk,gb2312)。因為設(shè)置一個的話,另一個默認(rèn)會和它一樣。 如果兩個都設(shè)置的話,必須保證兩個都是支持中文編碼(不一定要一樣)。 最佳建議設(shè)置如下: <%@ page language="java" import="java.util.*" pageEncoding="utf-8"%> <%@ page contentType="text/html;charset=utf-8"%> 2、post方式傳值亂碼: 由于post方式傳值是通過request存儲的,在另一個頁面也是通過request.getParameter(String name)來提取信息,所以這種情況下的亂碼主要是因為request存儲信息的編碼設(shè)置導(dǎo)致的。post提交時,如果沒有設(shè)置提交的編碼格式,則會以iso8859-1方式進行提交,接受的jsp卻以utf-8的方式接受。所以使用如下語句即可得到單個正確的中文字符串:String str = new String(request.getParameter("something").getBytes("ISO-8859-1"),"utf-8") ; 解決方法: 一、在接收頁面設(shè)置request.setCharacterEncoding("UTF-8")。 二、最好通過過濾器實現(xiàn)每個頁面都設(shè)置為request.setCharacterEncoding("UTF-8")。 三、在發(fā)送數(shù)據(jù)的頁面使用語句指定使用UTF-8格式發(fā)送數(shù)據(jù)。 3、get方式傳值亂碼: get方式傳值有兩種,一種是表單get傳值,另一種是url地址傳值(實質(zhì)上這兩種方式都是通過url參數(shù)的方式傳值)。 表單方式get傳值: 表單方式get傳值的編碼過程為,首先瀏覽器根據(jù)頁面的charset編碼方式對傳值進行編碼,然后提交至服務(wù)器交給tomcat,tomcat對這些信息進行解碼時,采用的解碼方式是由server.xml文件中的URIEncoding設(shè)置決定的,也就是說,當(dāng)我們使用命令request.getParameter("")獲取表單參數(shù)值時,得到的字符串,經(jīng)過了charset的編碼和URIEncoding的解碼。 由上所知,只要charset的編碼和URIEncoding的解碼一致,并且支持中文,就能保證沒有亂碼。 設(shè)置URIEncoding的方法如下: 方法一: 修改$TOMCAT/conf/server.xml文件,在HTTP Connector或者AJP Connector的配置加上URIEncoding="UTF-8" 復(fù)制代碼 代碼如下: <... maxThreads="150" minSpareThreads="25" maxSpareThreads="75" enableLookups="false" redirectPort="8443" acceptCount="100" connectionTimeout="20000" disableUploadTimeout="true" URIEncoding="UTF-8" /> 方法二: 使用useBodyEncodingForURI="true". 這個方法適合你的TOMCAT實例下需要跑多個不同Encoding的程序時。 復(fù)制代碼 代碼如下: <... 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" /> 在Tomcat配置中,連接器(HTTP Connector)屬性中有一個URIEncoding和 useBodyEncodingForURI屬性,這兩個屬性設(shè)置對URL后的附加參數(shù)進行URL解碼時該如何選擇 字符集編碼。URIEncoding用于制定URL后的附加參數(shù)的字符集編碼,useBodyEncodingForURI 則說明是否采用實體內(nèi)容的字符集編碼設(shè)置來替代URIEncoding的設(shè)置,也就是說當(dāng) useBodyEncodingForURI屬性設(shè)置為true時ServletRequest.setCharacterEncoding方法設(shè)置的字符集編碼也影響getParameter等方法對URL地址后的參數(shù)進行URL解碼的結(jié)果。(在/%TomCat_Home%/ conf\server.xml文件中找到 <Connector>標(biāo)記,然后在后面加上useBodyEncodingForURI=true) url方式get傳值亂碼: 于這種方式,瀏覽器不會采用頁面的charset方式對URL中的中文進行編碼后提交至服務(wù)器(IE,F(xiàn)ireFox都一樣),而是采用系統(tǒng)的GBK轉(zhuǎn)碼為ISO-8859-1之后提交至服務(wù)器tomcat,所以這個過程為: 首先,url地址中的中文被從gbk轉(zhuǎn)換成ISO-8859-1,交給tomcat后,又被tomcat根據(jù)URLEcoding解碼,這種情況,只有把URLEcoding設(shè)置為gbk才能在request.getParameter("")時不出現(xiàn)亂碼。但是這樣就會影響到上面的配置,所以一個好的解決方法是,使用java.net.URLEcoder和URLDecoder對地址中的中文進行手動編碼和解碼。 所以一個萬全的解決方法為: 1)所有頁面的charset設(shè)置為UTF-8。 2)Tomcat的URIEncoding默認(rèn)是ISO-8859-1,而我設(shè)置為UTF-8,主要是想解決中文命名的文件以及請求以get方式提交有可能出現(xiàn)的亂碼問題。 3)添加過濾器,調(diào)用request.setCharacterEncoding("utf-8")方法將request的字符集設(shè)定為utf-8,解決請求以post方式提交的亂碼問題。 4)url地址中存在中文參數(shù)時,首先對中文參數(shù)使用URLEcoder編碼為utf-8,然后在request.getParameter("")接收到參數(shù)后再使用URLDecoder還原。例如: from.jsp頁面: 復(fù)制代碼 代碼如下: <%String username = "張某某" ; username = URLEncoder.encode(username,"utf-8"); %> <a href="to.jsp?param=<%=username %>">轉(zhuǎn)入</a> to.jsp頁面 復(fù)制代碼 代碼如下: <%=URLDecoder.decode(request.getParameter("param"),"utf-8")%> 總之 ,亂碼的解決方案如下: post傳值亂碼時,在接收端設(shè)置request.setCharacterEncoding("UTF-8") get傳值或者url亂碼時,手動設(shè)置接收的參數(shù)String str = new String(request.getParameter("something").getBytes("ISO-8859-1"),"utf-8") ; 由上可見get,post傳值在tomcat5中是不一樣的. 看完了上面紅字部分的內(nèi)容,我決定在提交數(shù)據(jù)的頁面設(shè)置以UTF-8的格式提交數(shù)據(jù),而同時在接收數(shù)據(jù)的頁面設(shè)置也以UTF-8接收數(shù)據(jù),于是我在兩個頁面的首部都添加了如下語句: <% request.setCharacterEncoding("UTF-8"); response.setCharacterEncoding("UTF-8"); response.setContentType("text/html; charset=utf-8"); %> 然后測試,OK了!沒有亂碼了! 現(xiàn)在,index.jsp頁面的代碼如下: 復(fù)制代碼 代碼如下: <%@ page language="java" pageEncoding="utf-8"%> <%@ page contentType="text/html;charset=utf-8"%> <% request.setCharacterEncoding("UTF-8"); response.setCharacterEncoding("UTF-8"); response.setContentType("text/html; charset=utf-8"); %> <html> <head> </head> <body> <form action="mysql_insert.jsp" method="post"> ID :<input type = "text" name="id" value="0"/> 姓名 :<input type = "text" name="name" value="aaa"/> 性別 :<input type = "text" name="sex" value="female"/> 年齡:<input type = "text" name="age" value="20"/> </br> <input type = "submit" value="提交"/> </form> </body> </html> |
|