開(kāi)發(fā)過(guò)程中,經(jīng)常遇到中文亂碼問(wèn)題,以前總是解決就好,并沒(méi)有對(duì)該問(wèn)題總結(jié)一下,現(xiàn)在來(lái)總結(jié)一下開(kāi)發(fā)過(guò)程中常見(jiàn)的中文亂碼問(wèn)題。
一、有必要了解一些基本的編碼知識(shí):
這篇字符編碼筆記是必讀的
jsp的三次編碼
第一階段:JVM將.jsp文件編譯為.java文件。JVM先讀取pageEncoding的值,根據(jù)該值去讀取.jsp文件,然后由指定的編碼方案生成UTF-8的.java文件。
第二階段:JVM將.java文件轉(zhuǎn)換為.class文件,從UTF-8至UTF-8。這個(gè)過(guò)程就與任何編碼的設(shè)置都沒(méi)有關(guān)系了,經(jīng)過(guò)這個(gè)階段后.java文件就轉(zhuǎn)換成了統(tǒng)一的UTF-8編碼的.class文件了。
第三階段:服務(wù)器將處理的結(jié)果返回給瀏覽器,這個(gè)階段則依靠contentType的charset,如果設(shè)置了charset則瀏覽器就會(huì)使用指定的編碼格式進(jìn)行解碼,否則采用默認(rèn)的ISO-8859-1編碼格式進(jìn)行解碼處理。
jsp中的編碼設(shè)置
pageEncoding:<%@ page pageEncoding=”UTF-8”%>
上文中第一階段,使用該值去讀取jsp文件,為避免中文亂碼,跟jsp文件編碼一致;對(duì)服務(wù)器響應(yīng)進(jìn)行重新編碼,即jsp的輸出流在瀏覽器中顯示的編碼(不是主要作用)。
contentType: <%@ page contentType=”text/html;charset=UTF-8”%>
使用該值對(duì)服務(wù)器響應(yīng)進(jìn)行重新編碼,即jsp的輸出流在瀏覽器中顯示的編碼;對(duì)表單get和post請(qǐng)求數(shù)據(jù)編碼;上文中第一階段,使用該值去讀取jsp文件(不是主要作用)。
< META http-equiv=”Content-Type” content=”text/html;charset=UTF-8”>
網(wǎng)頁(yè)的編碼信息 ,說(shuō)明頁(yè)面制作所使用的編碼。
request.setCharacterEncoding()
可用在servlet和jsp頁(yè)面中,作用是設(shè)置對(duì)客戶端請(qǐng)求進(jìn)行重新編碼的編碼,即post方式提交的數(shù)據(jù)進(jìn)行編碼。
response.setCharacterEncoding()
與<%@ page contentType=”text/html;charset=UTF-8”%>一樣。
response.setContentType()
與<%@ page contentType=”text/html;charset=UTF-8”%>一樣。
response.setHeader(“Content-Type”,”text/html;charset=UTF-8”)
與< META http-equiv=”Content-Type” content=”text/html; charset=UTF-8”>一樣。
注意:上文1,2,3中有部分功能是一樣的,是有優(yōu)先級(jí)的,在讀取jsp文件時(shí),1>2;在對(duì)服務(wù)器響應(yīng)進(jìn)行編碼的時(shí)候,2>1>3,一般情況下,1,2都寫(xiě)。
http請(qǐng)求默認(rèn)以”ISO-8859-1”的編碼來(lái)傳送URL的。
二、中文亂碼的幾種情況及最簡(jiǎn)單的解決方案:
pageEncoding設(shè)置錯(cuò)誤
pageEncoding設(shè)置為jsp文件的編碼類(lèi)型。
查詢字符串包含中文
中文的編碼方式取決于瀏覽器,chrome為UTF-8,IE為GB2312,這是由于瀏覽器并沒(méi)有遵循URI編碼規(guī)范。有兩種解決方法:
開(kāi)發(fā)過(guò)程中,將查詢字符串提前編碼,
如:http://www.baidu.com/demo?demo=%D6%D0%B9%FA (UTF-8編碼)
在Servlet的doGet()方法中添加
1 | String value = new String(request.getParameter("parameterName").getBytes("ISO-8859-1"),"瀏覽器的編碼方式"); |
表單中的get和post數(shù)據(jù)包含中文
中文的編碼方式取決于上文的contentType中的charset,有兩種解決辦法:
在Servlet的doPost()方法中添加request.setCharacterEncoding(“charset的值”);(僅對(duì)post有用)
在Servlet的doPost()方法中添加
1 | String value = new String(request.getParameter("parameterName").getBytes("ISO-8859-1"),"charset的值"); |
三、原理
我們通過(guò)上面的方法可以解決亂碼問(wèn)題,下面講講原理:
客戶端發(fā)到服務(wù)器的數(shù)據(jù)需要在客戶端進(jìn)行編碼,類(lèi)似于:String parameterName = "中國(guó)".getBytes("UTF-8")
然后將編碼后的數(shù)據(jù)發(fā)到服務(wù)器。
客戶端接受數(shù)據(jù),request.getParameter(“”)的作用就是對(duì)接收到的數(shù)據(jù)進(jìn)行解碼,默認(rèn)使用ISO-8859-1進(jìn)行解碼,可以使用request.setCharacterEncoding(“”)進(jìn)行設(shè)置,但僅對(duì)post有用。假如我們使用默認(rèn)的ISO-8859-1,肯定亂碼,因?yàn)榫幋a跟解碼不一致,那此時(shí)怎么辦呢,引出了上文中的兩種解決方案:使用request.setCharacterEncoding(“”)改變r(jià)equest.getParameter(“”)的解碼方式或者new String(request.getParameter("parameterName").getBytes("ISO-8859-1"),"charset的值")
將request.getParameter(“”)解碼的數(shù)據(jù)重新編碼再解碼。
四、其他
在jsp中的頁(yè)面使用response.setContentType()等設(shè)置字符集會(huì)破壞jsp容器自身的頁(yè)面編碼,會(huì)引起html中字符亂碼,腳本不會(huì)亂,所以不建議設(shè)置。在開(kāi)發(fā)中多采用page指令設(shè)置字符集。
1234567891011121314151617 | <% response.setContentType("text/html;charset=UTF-8"); String str = new String("你好".getBytes("iso-8859-1"),"utf-8");%><!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"><html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>Insert title here</title></head><body><p>你好</p><br><%=str %></body></html> |
網(wǎng)頁(yè)測(cè)試
.NET6.0的MVC中,可以通過(guò)以下方式將參數(shù)傳遞給Partial View:
<partial name="_MyPartial" model='new { code=1,name="參數(shù)值" } ' />
但是這樣會(huì)出現(xiàn)中文亂碼問(wèn)題,使用下面的方式可以解決中文亂碼問(wèn)題:
<partial name="_MyPartial" model='new { code=1,name=@Html.Raw(System.Net.WebUtility.HtmlEncode("參數(shù)值")) } ' />
在上面的示例中,使用 System.Net.WebUtility.HtmlEncode 方法對(duì)參數(shù)進(jìn)行編碼,然后使用 Html.Raw 方法來(lái)解碼,以確保中文字符正確顯示。
通過(guò)這種方式,可以避免在 .NET 6.0的MVC中使用 <partial> 傳遞參數(shù)時(shí)出現(xiàn)中文亂碼的問(wèn)題。
在Partial View中獲取參數(shù)的值如下面示例代碼:
<div>
<p>@Model.code</p>
<p>@Model.name</p>
</div>
希望這個(gè)例子對(duì)您有所幫助。
面已經(jīng)介紹了HttpServletResponse響應(yīng)對(duì)象中的一些常用方法,這一小節(jié)介紹如何使用HttpServletResponse響應(yīng)對(duì)象,解決中文亂碼問(wèn)題。
使用HttpServletResponse響應(yīng)對(duì)象,發(fā)送數(shù)據(jù)給瀏覽器客戶端的時(shí)候,瀏覽器接收到中文,會(huì)出現(xiàn)亂碼情況,出現(xiàn)這個(gè)問(wèn)題的根本原因還是:瀏覽器和服務(wù)器之間的編碼字符集不一致。
默認(rèn)情況下,Servlet容器是采用ISO-8859-1的編碼將數(shù)據(jù)發(fā)送給瀏覽器客戶端的,但是客戶端采用何種編碼方式來(lái)解析是不一定的,有可能是UTF-8、也有可能是GBK,所以這就導(dǎo)致編碼不一致,從而造成中文亂碼問(wèn)題。
那么針對(duì)這種亂碼問(wèn)題???我們要如何解決呢???解決的辦法很簡(jiǎn)單:那就是主動(dòng)告訴Servlet容器采用哪種編碼方式,并且告訴瀏覽器客戶端采用哪種方式來(lái)解碼就可以啦。
解決方案:調(diào)用response響應(yīng)對(duì)象的【setContentType()】方法、或者調(diào)用【setCharacterEncoding()】方法來(lái)指定編碼即可。
// 方式一(推薦)
// 告訴Servlet容器采用UTF-8字符集進(jìn)行編碼
// 并且告訴瀏覽器,采用UTF-8字符集進(jìn)行解碼
response.setContentType("text/html;charset=UTF-8");
// 方式二
// 解決響應(yīng)亂碼問(wèn)題
// 并且告訴瀏覽器,采用UTF-8字符集進(jìn)行解碼
response.setCharacterEncoding("UTF-8");
通過(guò)以上兩種方式,就可以解決返回?cái)?shù)據(jù)的亂碼問(wèn)題啦。
今天就到這里,未完待續(xù)~~
*請(qǐng)認(rèn)真填寫(xiě)需求信息,我們會(huì)在24小時(shí)內(nèi)與您取得聯(lián)系。