本文共 7144 字,大约阅读时间需要 23 分钟。
網頁聊天的基本原理很簡單,在使用者發送訊息給伺服端時,同時取回新的聊天訊息,在使用者沒有發送訊息,同時查詢伺服端是否有新的訊息,並顯示在頁面中。 不過重點就在於取得訊息或重新取得訊息的方式,在過去,是在讓瀏覽器定時重新整理網頁,每一次除了新的訊息之外,往往伴隨著大量重複的HTML標籤等內容。 如果使用非同步請求,取得XML回應訊息,並動態更新頁面中顯示聊天訊息的部份,這麼一來,就可以節省掉下載重複頁面內容的頻寬,使用者的畫面也會更穩定,不會因為重新整理而發生閃爍的感覺。 例如,您可以寫一個簡單的聊天頁面:
PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> 聊天室 輸入訊息: οnclick="sendMessage()"/> 聊天室訊息:您可以在這個頁面中的欄位中輸入文字,而下方會有個顯示訊息的區域,每次的新訊息將只在該區域更新,頁面中其餘的部份不用變動,所以不用重複下載,來看一下JavaScript的部份:
var xmlHttp; function createXMLHttpRequest() { if (window.ActiveXObject) { xmlHttp = new ActiveXObject("Microsoft.XMLHTTP"); } else if (window.XMLHttpRequest) { xmlHttp = new XMLHttpRequest(); } } function sendMessage() { var msg = document.getElementById("text").value; // 使用者只是隨意按下傳送鈕,但文字欄位中沒有文字 if(msg === "") { // 那就重新整理訊息區好了 refreshMessage(); return; } // 傳送訊息 var param = "task=send&msg=" + msg; // ajax請求 ajaxRequest(param); // 清空文字欄位 document.getElementById("text").value = ""; } // 定時查詢用這個 function queryMessage() { var param = "task=query"; ajaxRequest(param); } function ajaxRequest(param) { var url = "ChatRoomServlet?timeStamp=" + new Date().getTime(); createXMLHttpRequest(); xmlHttp.onreadystatechange = refreshMessage; xmlHttp.open("POST", url); xmlHttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded;"); xmlHttp.send(param); } function refreshMessage() { if(xmlHttp.readyState == 4) { if(xmlHttp.status == 200) { // 處理顯示訊息的表格區域 var table_body = document.getElementById("dynamicUpdateArea"); var length = table_body.childNodes.length; var i; for (i = 0; i < length; i++) { // 先移除原有的列(row) table_body.removeChild(table_body.childNodes[0]); } // 處理取回的訊息 var messages = xmlHttp.responseXML.getElementsByTagName("message"); length = messages.length; for(i = length - 1; i >= 0 ; i--) { var message = messages[i].firstChild.data; // 在表格中新增一列來排列訊息 var row = createRow(message); table_body.appendChild(row); } // 下次2秒後會再查詢一下有無新訊息 setTimeout(queryMessage, 2000); } } } function createRow(message) { var row = document.createElement("tr"); var cell = document.createElement("td"); var cell_data = document.createTextNode(message); cell.appendChild(cell_data); row.appendChild(cell); return row; }伺服端必須傳回以下的XML格式,表示目前伺服端所管理的聊天室中可取得的訊息: 聊天訊息一 聊天訊息二 聊天訊息三
package onlyfun.caterpillar; import java.io.IOException; import java.io.PrintWriter; import java.util.LinkedList; import java.util.List; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class ChatRoomServlet extends javax.servlet.http.HttpServlet implements javax.servlet.Servlet { private static LinkedList messages = new LinkedList (); private List addMessage(String text) { if (text != null && text.trim().length() > 0) { messages.addFirst(new Message(text)); while (messages.size() > 10) { messages.removeLast(); } } return messages; } private List getMessages() { return messages; } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { List list = null; if("send".equals(request.getParameter("task"))) { String msg = request.getParameter("msg"); // 中文處理 msg = new String(msg.getBytes("ISO-8859-1"), "UTF8"); list = addMessage(msg); } else if("query".equals(request.getParameter("task"))){ list = getMessages(); } response.setContentType("text/xml"); response.setHeader("Cache-Control", "no-cache"); response.setCharacterEncoding("UTF8"); PrintWriter out = response.getWriter(); out.println(" "); for(int i = 0; i < list.size(); i++) { String msg = list.get(i).getText(); out.println(" " + msg + " "); } out.println(" "); out.close(); } }
package onlyfun.caterpillar; public class Message { private String text; public Message(String newtext) { text = newtext; if (text.length() > 256) { text = text.substring(0, 256); } text = text.replace('<', '['); text = text.replace('&', '_'); } public String getText() { return text; } } | <script type="text/javascript"> </script> <script src="http://pagead2.googlesyndication.com/pagead/show_ads.js" type="text/javascript"> </script> width="160" scrolling="no" height="600" frameborder="0" allowtransparency="true" hspace="0" vspace="0" marginheight="0" marginwidth="0" src="http://pagead2.googlesyndication.com/pagead/ads?client=ca-pub-9750319131714390&dt=1179111675171&lmt=1177046893&format=160x600_as&output=html&url=http%3A%2F%2Fcaterpillar.onlyfun.net%2FGossip%2FAjaxGossip%2FChatRoom.html&ad_type=text_image&ref=http%3A%2F%2Fcaterpillar.onlyfun.net%2FGossip%2FAjaxGossip%2FAjaxGossip.html&cc=15&flash=9&u_h=768&u_w=1024&u_ah=740&u_aw=1024&u_cd=16&u_tz=480&u_his=2&u_java=true&u_nplug=18&u_nmime=58" name="google_ads_frame"> <script type="text/javascript"> </script> <script src="http://pagead2.googlesyndication.com/pagead/show_ads.js" type="text/javascript"> </script> width="160" scrolling="no" height="600" frameborder="0" allowtransparency="true" hspace="0" vspace="0" marginheight="0" marginwidth="0" src="http://pagead2.googlesyndication.com/pagead/ads?client=ca-pub-9750319131714390&dt=1179111675187&lmt=1177046893&prev_fmts=160x600_as&format=160x600_as&output=html&url=http%3A%2F%2Fcaterpillar.onlyfun.net%2FGossip%2FAjaxGossip%2FChatRoom.html&ad_type=text_image&ref=http%3A%2F%2Fcaterpillar.onlyfun.net%2FGossip%2FAjaxGossip%2FAjaxGossip.html&cc=15&flash=9&u_h=768&u_w=1024&u_ah=740&u_aw=1024&u_cd=16&u_tz=480&u_his=2&u_java=true&u_nplug=18&u_nmime=58" name="google_ads_frame"> |
Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=1607905