由 XMLHttpRequest 送出中文資料給 Tomcat
The following examples had been tested on Mozilla's Firefox and Microsoft's IE. The document is provided as is. You are welcomed to use it for non-commercial purpose.Written by: 國立中興大學資管系呂瑞麟
請勿轉貼
看其他教材
在嘗試 Dojo 和 Yahoo! User Interface Library (YUI) 的時候,才突然發現之前的
AJAX 範例都沒有從 XMLHttpRequest 傳送中文的資料給遠端的 Tomcat servlet。
而發現的原因在於為 Dojo 和 YUI 所寫的程式中,其中一個範例是由 browser 送出
一個中文的(Big5)欄位資料到遠端的 Tomcat servlet 處理,而處理的結果
卻是亂碼。這樣子一來就打亂了我的休假,連續兩個晚上測到凌晨一、兩點
(對一個老人來說,是很大的折磨)。這兩天找了不少資料,目前以
- John O'Conner, Character Conversions from Browser to Database, Sun Devloper Network, 01/2006.
- Greg Murray, AJAX I18n with Java, Greg Murray's Blog, 03/2006.
- 由 XMLHttpRequest 送出去的 URL:如果 URL 包含 Big5 的資料,XMLHttpRequest 會不會 encode,而且又是以何種方式 encode?
- server 是如何解讀收到的 URL:目前知道 Tomcat (我的主要 servlet 開發 平台)是採用 ISO-8859-1 編碼方式來接收,因此解碼的方式可以用 ISO-8859-1 來進行。但是,如果 browser 送過來的資料是以 UTF-8 編碼,那要怎麼辦呢?
- IE 6.x/7.x:
- 若 Javascript 對中文資料 encodeURIComponent(),則 servlet 需要對接收到的資料先以 ISO-8859-1 解出來之後,以 UTF-8 編碼出來。
- 若 Javascript 不對中文資料進行 encodeURIComponent(),則 servlet 需要對接收到的資料先以 ISO-8859-1 解出來之後,以 Big5 編碼出來。
- Firefox 1.5.x 或者新版本:不論 browser 是否對中文資料 encodeURIComponent(),servlet 需要對接收到的資料 先以 ISO-8859-1 解出來之後,以 UTF-8 編碼出來。
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=Big5">
<script type="text/javascript" language="javascript">
function makeRequest(url) {
var http_request = false;
if (window.XMLHttpRequest) { // Mozilla, Safari,...
http_request = new XMLHttpRequest();
} else if (window.ActiveXObject) { // IE
try {
http_request = new ActiveXObject("Msxml2.XMLHTTP");
} catch (e) {
try {
http_request = new ActiveXObject("Microsoft.XMLHTTP");
} catch (e) {}
}
}
if (!http_request) {
alert('Giving up :( Cannot create an XMLHTTP instance');
return false;
}
// 定義事件處理函數為 alterContents()
http_request.onreadystatechange = function() {
alertContents(http_request); };
// IE 6.x 和 Firefox 1.5.x 皆要 encodeURI()
url = url + "?name=" +
encodeURIComponent(document.myform.elements[0].value);
http_request.open('GET', url, true);
http_request.send(null);
}
function alertContents(http_request) {
if (http_request.readyState == 4) {
if (http_request.status == 200) {
var mesg = http_request.responseText;
alert(mesg);
} else {
alert('There was a problem with the request.');
}
}
}
</script>
</head>
<body>
<form name="myform">
姓名: <input type="text" name="name"></input>
<input type="button" value="OK" onClick="makeRequest('適當的 servlet URL');"></input>
</form>
</body>
</html>
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;
public class Hello extends HttpServlet {
public void doGet(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException
{
res.setContentType("text/plain;charset=UTF-8");
PrintWriter output = res.getWriter();
String msg = req.getParameter("name");
msg = new String(msg.getBytes("ISO-8859-1"), "UTF-8");
StringBuffer buf = new StringBuffer();
buf.append("Hello " + msg);
buf.append(" , 歡迎使用 AJAX");
output.println(buf.toString());
output.close();
}
}
瀏覽器中的中文 --經過 encodeURIComponent() 轉碼(這部份的程式碼是為了執行跟所有瀏覽器預設的動作)
--經過 Tomcat 編碼 --> ISO-8859-1 (Tomcat 無法知道客戶端送過來的編碼為何,因此它會先 decodeURI() 然後把資料以 ISO-8859-1 編碼)
--經過 servlet 的 getBytes("ISO-8859-1") 以 ISO8859-1 的方式解讀 URL 的資料
--再經過 new String(..., "需要的編碼") 將資料從 ISO-8859-1 的編碼轉換成需要的編碼;在這個範例中,由於程式碼中的中文是以
UTF-8 編碼(我在最近一次升級伺服器之後,將系統預設編碼設定成 UTF-8),所以回傳的資料編碼為 UTF-8(程式碼中的
setContentType() 可以看得出來)。
個人心得: 雖然非常多的專家都認為應該將 Linux 的預設編碼設定為
UTF-8 (也就是 zh_TW.UTF-8),但是經過一段時間的使用之後,我還真的
有點後悔,原因很簡單:我的客戶端作業系統是 XP Professional 繁體中文版,
而且之前開發的一些程式(內含中文)都是以 XP 的預設編碼來做的,也就是
大五碼(Big5),在這樣的環境下,不斷的注意編碼的一致性實在很痛苦,所以
我個人建議還是將 Linux 的預設編碼設定為 Big5 (也就是 zh_TW.Big5)
會比較方便。
Written by: 國立中興大學資管系呂瑞麟
沒有留言:
張貼留言