來源:http://blog.csdn.net/zhangzikui/article/details/6169978
??????? http://www.iteye.com/topic/300656
?
第一 ?java 源代碼文件編碼
保存文件必須以一種編碼存;讀文件也必須以一種編碼讀,如不特別設置,去系統默認的編碼,中文windows為GBK編碼。
???? 從.java->.class過程是,先編寫.java文件并按某種編碼方式保存,然后用javac方法編譯此文件,注意如.java沒按系統默認編碼保存則要帶encoding參數指明實際編碼,否則出錯,生成的.class文件存為系統默認編碼。
???? 從.jsp->.java->.class,先存為某種編碼的.jsp文件,然后tomcat根據pageEncoding讀取并轉化為servlet存為系統默認編碼,然后同上面.java->.class過程。
第二
eclipse
開發環境對源代碼文件編碼的影響
IDE的encoding為對系統下文件打開的解碼方式或保存的編碼方式。特例:如果.jsp文件有<%@ page language="java" pageEncoding="UTF-8"%>,則eclipse會自動存為UTF-8方式,不管eclipse的encoding是什么,這也是eclipse的聰明之處。
第三
jsp
源代碼文件編碼
pageEncoding="UTF-8"表示此文件的編碼方式,必須與此文件存儲方式一致(所以eclipse會首選根據它來存文件),
<%@ page language="java" pageEncoding="UTF-8"%>? 表示JSP文件編碼方式,web容器tomcat根據這個來讀此.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 >
會產生亂碼,因為存為UTF-8的文件被解碼為iso8859-1,這樣 如有中文肯定出亂碼。
至此,頁面應為:
?
<% @ 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
編碼設置方式
request.setCharacterEncoding("UTF-8")是把提交內容的字符集設為UTF-8
response.setCharacterEncoding("UTF-8")可以把頁面中的<%@ page contentType="text/html;charset=iso8859-1"%>
第五,
java
連接數據庫編碼
?
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");都可以使用這個 不論哪里,有亂碼就是用
第六 頁面請求的編碼( 表單的get提交、表單的post提交、頁面鏈接傳遞中文參數、地址欄中參數直接輸入中文提交 ) ?
請求響應的全過程:
瀏覽器 IE/FireFox ----------->Servlet容器------------------------>顯示頁面
?????? 編碼?????????????????????????? 使用容器的URIEncoding轉碼 ???????????? 解碼
換為charset=UTF-8,是給告訴瀏覽器我這個文件的編碼方式。
一共四種方式:表單的get提交、表單的post提交、頁面鏈接傳遞中文參數、地址欄中參數直接輸入中文提交。
無論何種表單提交都可以在后臺的java文件中通過String des = new String(s.getBytes("iso8859-1"),"UTF-8");來轉換成你想要的UTF-8編碼方式。
1.???? 表單 get 方式提交
???????? 瀏覽器根據頁面的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),類似于這樣
new
String(變量值.getBytes("UTF-8"),"ISO-8859-1");
例如表單的username屬性以字符串"編輯"提交,那么進入容器后,FormBean中的這個變量會亂碼,request.getParameter(username)一樣的效果,s1就是request返回的結果,下面是內存快照。
??
不過即使這樣,我們依然可以使用不恰當的方法顯示正常的中文,即逆向轉碼,例如上面的亂碼,我們可以通過ISO8859-1-->UTF-8這種方式還原我們提交時的中文。以下是GBK,UTF-8,ISO-8859-1三者之間互相轉換的內存快照:
???
我們可以看到,偶數漢字可以在UTF-8,GBK兩者中互相轉換,而奇數個漢字則不能。綜上看來,貌似Tomcat的URIEncoding設置為UTF-8是最好的解決辦法,不過這樣的設置依然無法解決上面我所說的第三、第四種情況。大家繼續向下看。(這里有一點我不確定,就是頁面提交至Servlet容器時,是以頁面的charset方式編碼后直接進入容器,還是以charset轉碼為ISO-8859-1方式進入,大家有什么見解?)
2.
表單的
post
提交
對于這種方式的請求,request.setCharacterEncoding("一般來自于web.xml中過濾器設置的參數")方法進行編碼設置將會產生作用,struts的表單提交方式默認為post方式,那么按照上面我的環境設置,頁面,容器,都采用UTF-8編碼方式,就不會產生中文亂碼問題。
程序加上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 >
因為規范要求瀏覽器提交數據都要用utf8編碼,所以這里設置編碼方式為UTF8.?
特別注意:?
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.
頁面鏈接中傳遞中文參數
我虛擬一個這樣的場景,請求頁面中有如下代碼
Html代碼
<% String username = " 編輯 " ; %> < a href ="hello.do?username=<%=username%>" > 頁面中鏈接傳遞中文 </ a >
對于這種方式,我們需要先將參數使用統一的編碼方式編碼,將編碼后的字符放入鏈接,這里我對參數以UTF-8方式編碼,如下
<% 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")?取出?
例如瀏覽器地址欄中輸入"http://localhost:8080/helloapp.do?username=編輯"提交,對于這種方式,瀏覽器不會采用頁面的charset方式對URL中的中文進行編碼后提交至服務器(IE,FireFox都一樣),而是采用系統的GBK轉碼為ISO-8859-1之后提交至Servlet容器,那么,如果對于前三種方式我們所做的設置,在這里就有問題了,因為進入容器時中文進行了GBK至ISO-8859-1的轉碼,而之前我們的Servlet容器URIEncoding設置為UTF-8,當我們使用request.getParameter("username")時,相當于又進行了這樣的流程GBK-->ISO-8859-1-->UTF-8,按照以上我們使用的測試中文,“編輯”,使用request.getParameter("username")則會得到這樣的結果??,下圖是進行轉碼的內存快照:
我們可以看到“編輯”經過從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頁面,如:http://localhost:8080/helloapp/編輯.jsp,IE默認是勾選"以UTF-8發送URL"項的,那么按照我上面總結的處理方式,這個請求可以正常顯示頁面,如圖:
?
如果取消IE的這個選項,那么瀏覽器會以GBK編碼應用路徑的中文,得到的結果如圖:
??
按照我上面的設置,這里如果將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"?
這樣應該可以搞定大多數前臺的中文問題.至于地址欄輸入中文,不支持也罷,一般的程序很少要求?
從這里輸入.
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

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