來源:http://blog.csdn.net/zhangzikui/article/details/6169978
??????? http://www.iteye.com/topic/300656
?
第一 ?java 源代碼文件編碼
保存文件必須以一種編碼存;讀文件也必須以一種編碼讀,如不特別設(shè)置,去系統(tǒng)默認的編碼,中文windows為GBK編碼。
???? 從.java->.class過程是,先編寫.java文件并按某種編碼方式保存,然后用javac方法編譯此文件,注意如.java沒按系統(tǒng)默認編碼保存則要帶encoding參數(shù)指明實際編碼,否則出錯,生成的.class文件存為系統(tǒng)默認編碼。
???? 從.jsp->.java->.class,先存為某種編碼的.jsp文件,然后tomcat根據(jù)pageEncoding讀取并轉(zhuǎn)化為servlet存為系統(tǒng)默認編碼,然后同上面.java->.class過程。
第二
eclipse
開發(fā)環(huán)境對源代碼文件編碼的影響
IDE的encoding為對系統(tǒng)下文件打開的解碼方式或保存的編碼方式。特例:如果.jsp文件有<%@ page language="java" pageEncoding="UTF-8"%>,則eclipse會自動存為UTF-8方式,不管eclipse的encoding是什么,這也是eclipse的聰明之處。
第三
jsp
源代碼文件編碼
pageEncoding="UTF-8"表示此文件的編碼方式,必須與此文件存儲方式一致(所以eclipse會首選根據(jù)它來存文件),
<%@ page language="java" pageEncoding="UTF-8"%>? 表示JSP文件編碼方式,web容器tomcat根據(jù)這個來讀此.jsp文件并編譯為servlet。
第四? servlet生成html文件編碼方式
<%@ page contentType="text/html;charset= “UTF-8"%>
contentType="text/html;charset=UTF-8"表示當瀏覽器得到此文件時以什么方式解碼。例:
?
<% @ page language = " java " pageEncoding = " UTF-8 " %> <% @ page contentType = " text/html;charset=iso8859-1 " %> < html > < head > < title > test </ title > </ head > < body > 我是個好人 </ body > </ html >
會產(chǎn)生亂碼,因為存為UTF-8的文件被解碼為iso8859-1,這樣 如有中文肯定出亂碼。
至此,頁面應(yīng)為:
?
<% @ 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 >
第四,
request
與
response
編碼設(shè)置方式
request.setCharacterEncoding("UTF-8")是把提交內(nèi)容的字符集設(shè)為UTF-8
response.setCharacterEncoding("UTF-8")可以把頁面中的<%@ page contentType="text/html;charset=iso8859-1"%>
第五,
java
連接數(shù)據(jù)庫編碼
?
1、mysql配置文件:
修改mysql在windows/my.ini里default-character-set=utf-8
2、mysql里數(shù)據(jù)庫和表也都設(shè)為utf8_unicode_ci
3、數(shù)據(jù)庫連結(jié):jdbc:mysql://localhost/mydb?useUnicode=true&characterEncoding=utf-8
注意,關(guān)鍵就在于此:此句中間是'&'不是'&'這是因為數(shù)據(jù)庫連結(jié)時,在.jsp和.java文件中應(yīng)該用&號,而XML文件中需要用&
對于Web容器來說,如果你不設(shè)置,默認是ISO8859-1
String des = new String(s.getBytes("iso8859-1"),"UTF-8");都可以使用這個 不論哪里,有亂碼就是用
第六 頁面請求的編碼( 表單的get提交、表單的post提交、頁面鏈接傳遞中文參數(shù)、地址欄中參數(shù)直接輸入中文提交 ) ?
請求響應(yīng)的全過程:
瀏覽器 IE/FireFox ----------->Servlet容器------------------------>顯示頁面
?????? 編碼?????????????????????????? 使用容器的URIEncoding轉(zhuǎn)碼 ???????????? 解碼
換為charset=UTF-8,是給告訴瀏覽器我這個文件的編碼方式。
一共四種方式:表單的get提交、表單的post提交、頁面鏈接傳遞中文參數(shù)、地址欄中參數(shù)直接輸入中文提交。
無論何種表單提交都可以在后臺的java文件中通過String des = new String(s.getBytes("iso8859-1"),"UTF-8");來轉(zhuǎn)換成你想要的UTF-8編碼方式。
1.???? 表單 get 方式提交
???????? 瀏覽器根據(jù)頁面的charset編碼方式對頁面進行編碼,然后提交至服務(wù)器,首先進入對應(yīng)的字符編碼過濾器(如果有的話),不過Tomcat6.0對于get提交方式采用的是server.xml文件中的URIEncoding編碼方式,而并不會采用過濾器中設(shè)置的編碼,那么根據(jù)我的環(huán)境設(shè)置,jsp頁面都使用UTF-8的編碼,Servlet容器的URIEncoding也設(shè)置為UTF-8,則servlet不用進行轉(zhuǎn)碼即可正確解碼,獲得正常的中文字符串。那么,響應(yīng)頁面的中文因為頁面的統(tǒng)一編碼(UTF-8)自然也會正常顯示。當然,如果我們Tomcat的URIEncoding設(shè)置為其他非UTF-8的編碼方式時,頁面的內(nèi)容進入Tomcat解析時,因為Tomcat和頁面的編碼不統(tǒng)一,就需要轉(zhuǎn)碼。例如,如果我們采用Tomcat默認的ISO-8859-1,那么當我們使用request.getParameter("yourVariable ")獲取表單參數(shù)值時其實Servlet就進行了轉(zhuǎn)碼,方式為UTF-8-->ISO-58859-1(我的頁面charset都是UTF-8),類似于這樣
new
String(變量值.getBytes("UTF-8"),"ISO-8859-1");
例如表單的username屬性以字符串"編輯"提交,那么進入容器后,F(xiàn)ormBean中的這個變量會亂碼,request.getParameter(username)一樣的效果,s1就是request返回的結(jié)果,下面是內(nèi)存快照。
??
不過即使這樣,我們依然可以使用不恰當?shù)姆椒@示正常的中文,即逆向轉(zhuǎn)碼,例如上面的亂碼,我們可以通過ISO8859-1-->UTF-8這種方式還原我們提交時的中文。以下是GBK,UTF-8,ISO-8859-1三者之間互相轉(zhuǎn)換的內(nèi)存快照:
???
我們可以看到,偶數(shù)漢字可以在UTF-8,GBK兩者中互相轉(zhuǎn)換,而奇數(shù)個漢字則不能。綜上看來,貌似Tomcat的URIEncoding設(shè)置為UTF-8是最好的解決辦法,不過這樣的設(shè)置依然無法解決上面我所說的第三、第四種情況。大家繼續(xù)向下看。(這里有一點我不確定,就是頁面提交至Servlet容器時,是以頁面的charset方式編碼后直接進入容器,還是以charset轉(zhuǎn)碼為ISO-8859-1方式進入,大家有什么見解?)
2.
表單的
post
提交
對于這種方式的請求,request.setCharacterEncoding("一般來自于web.xml中過濾器設(shè)置的參數(shù)")方法進行編碼設(shè)置將會產(chǎn)生作用,struts的表單提交方式默認為post方式,那么按照上面我的環(huán)境設(shè)置,頁面,容器,都采用UTF-8編碼方式,就不會產(chǎn)生中文亂碼問題。
程序加上org.springframework.web.filter.CharacterEncodingFilter過濾器.?
< 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 >
因為規(guī)范要求瀏覽器提交數(shù)據(jù)都要用utf8編碼,所以這里設(shè)置編碼方式為UTF8.?
特別注意:?
a,這個過濾器只是簡單的調(diào)用:request.setCharacterEncoding(this.encoding);?
在這個語句之前不能調(diào)用任何的request.getParameter()方法,否則會設(shè)置tomcat的缺省字符集為"ISO-8859-1",并且使setCharacterEncoding的調(diào)用失效.所以在這個過濾器之前的過濾器中不能有對getParameter這類方法的調(diào)用,比較安全的做法就是把這個過濾器盡量靠前放.?
b,在server.xml中不能加上<Valve className="org.apache.catalina.valves.RequestDumperValve"/>?
這個value也設(shè)置tomcat的缺省字符集為"ISO-8859-1",使setCharacterEncoding的調(diào)用失效.可能其他的value也有這個問題,我沒有測試過.?
如果要觀察http請求參數(shù),可以考慮用抓包工具,例如ethereal或者wireshark
3.
頁面鏈接中傳遞中文參數(shù)
我虛擬一個這樣的場景,請求頁面中有如下代碼
Html代碼
<% String username = " 編輯 " ; %> < a href ="hello.do?username=<%=username%>" > 頁面中鏈接傳遞中文 </ a >
對于這種方式,我們需要先將參數(shù)使用統(tǒng)一的編碼方式編碼,將編碼后的字符放入鏈接,這里我對參數(shù)以UTF-8方式編碼,如下
<% String username = java.net.URLEncoder.encode("編輯","UTF-8"); %>
那么這樣我們也不會產(chǎn)生中文亂碼問題
如果是頁面超連接連接中帶的漢字,則編碼根據(jù)頁面編碼的不同而不同,如果頁面的?
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取出正確內(nèi)容.?
如果content="text/html; charset=GBK",需用?
new String(request.getParameter("something").getBytes("ISO-8859-1"),"GBK")?
取出,其他情況類似
4.???? 地址欄中參數(shù)直接輸入中文提交
???? 從地址欄直接輸入漢字,則一般編碼為"GBK",需要用?
new String(request.getParameter("something").getBytes("ISO-8859-1"),"GBK")?取出?
例如瀏覽器地址欄中輸入"http://localhost:8080/helloapp.do?username=編輯"提交,對于這種方式,瀏覽器不會采用頁面的charset方式對URL中的中文進行編碼后提交至服務(wù)器(IE,FireFox都一樣),而是采用系統(tǒng)的GBK轉(zhuǎn)碼為ISO-8859-1之后提交至Servlet容器,那么,如果對于前三種方式我們所做的設(shè)置,在這里就有問題了,因為進入容器時中文進行了GBK至ISO-8859-1的轉(zhuǎn)碼,而之前我們的Servlet容器URIEncoding設(shè)置為UTF-8,當我們使用request.getParameter("username")時,相當于又進行了這樣的流程GBK-->ISO-8859-1-->UTF-8,按照以上我們使用的測試中文,“編輯”,使用request.getParameter("username")則會得到這樣的結(jié)果??,下圖是進行轉(zhuǎn)碼的內(nèi)存快照:
我們可以看到“編輯”經(jīng)過從GBK-->ISO-8859-1-->UTF-8的過程后得到的就是??這樣的結(jié)果,這里我們還會想到那進行2次逆向轉(zhuǎn)碼看看,不過可惜的是,結(jié)果為“錕潔輯”。對于這種情況,我們的解決辦法就是,Tomcat的URIEncoding采用默認的ISO-8859-1字符集,那么我們可以在程序中通過ISO-8859-1-->GBK這樣不恰當?shù)哪嫦蜣D(zhuǎn)碼方式得到正常的中文“編輯”,但這樣的結(jié)果是,我們get請求方式的中文處理解決辦法就需要改變。如,在我的環(huán)境下就需要進行ISO-8859-1-->UTF-8的轉(zhuǎn)碼,挺不爽。
綜上,對于亂碼問題,前三種方式是一般用戶的請求方式,第四種屬于非正常途徑的請求方式,對于這種方式產(chǎn)生的問題我認為無法很好的解決,也不需要解決。我看到j(luò)avaeye對于這樣的情況就沒有處理,不知道大家在自己的項目中是如何處理的?我的實驗是,IE6的設(shè)置會影響應(yīng)用路徑的編碼方式,例如地址欄中請求一個中文JSP頁面,如:http://localhost:8080/helloapp/編輯.jsp,IE默認是勾選"以UTF-8發(fā)送URL"項的,那么按照我上面總結(jié)的處理方式,這個請求可以正常顯示頁面,如圖:
?
如果取消IE的這個選項,那么瀏覽器會以GBK編碼應(yīng)用路徑的中文,得到的結(jié)果如圖:
??
按照我上面的設(shè)置,這里如果將Tomcat的URIEncoding設(shè)置為GBK,則也可以正常顯示頁面。對于FireFox3.0,則是以UTF-8編碼。
總結(jié)
:?
1,所有頁面使用utf8編碼,?
2,服務(wù)器加上過濾器,?
3,server.xml中不要使用?
<Valve className="org.apache.catalina.valves.RequestDumperValve"/>?
4,server.xml文件加上useBodyEncodingForURI="true"?
這樣應(yīng)該可以搞定大多數(shù)前臺的中文問題.至于地址欄輸入中文,不支持也罷,一般的程序很少要求?
從這里輸入.
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯(lián)系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
