來寫個AJAX版的聊天室吧!先看看直接使用AJAX要如何做到,首先需要一個簡單的聊天室Servlet…
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
|
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<Message> messages = new LinkedList<Message>(); public ChatRoomServlet() { super (); } private List<Message> 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<Message> getMessages() { return messages; } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { List<Message> list = null ; if ( "send" .equals(request.getParameter( "task" ))) { list = addMessage(request.getParameter( "msg" )); } else if ( "query" .equals(request.getParameter( "task" ))) { list = getMessages(); } PrintWriter out = response.getWriter(); response.setContentType( "text/xml" ); response.setHeader( "Cache-Control" , "no-cache" ); out.println( "<response>" ); for ( int i = 0; i < list.size(); i++) { String msg = list.get(i).getText(); out.println( "<message>" + msg + "</message>" ); } out.println( "</response>" ); } } |
Message物件如下…
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
package onlyfun.caterpillar; public class Message { private long id = System.currentTimeMillis(); 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 long getId() { return id; } public String getText() { return text; } } |
Servlet接受訊息新增與查詢,判斷的方式是檢查請求參數task是send或query。
Servlet會以XML傳回目前List當中的訊息,客戶端可以查詢或插入新訊息時,取得目前List中的訊息,接著在web.xml中設定一下…
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
<?xml version= "1.0" encoding= "UTF-8" ?> <web-app id= "WebApp_ID" version= "2.4" xmlns= "http://java.sun.com/xml/ns/j2ee" xmlns:xsi= "http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation= "http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd" > <servlet> <description> </description> <display-name> ChatRoomServlet</display-name> <servlet-name>ChatRoomServlet</servlet-name> <servlet-class> onlyfun.caterpillar.ChatRoomServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>ChatRoomServlet</servlet-name> <url-pattern>/ChatRoomServlet</url-pattern> </servlet-mapping> <session-config> <session-timeout> 30 </session-timeout> </session-config> </web-app> |
在網頁中,使用者可以在輸入訊息後按下按鈕送出資訊,並在XML回應取得時,將訊息以一列一列的表格方式顯示出來,另外還設定了週期性的輪詢,即使不輸入新訊息,也可以週期性的取得新的聊天訊息…
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" > <html> <head> <meta http-equiv= "Content-Type" content= "text/html; charset=BIG5" > <title>Chat Room</title> <script type= "text/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; 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, true ); xmlHttp.setRequestHeader( "Content-Type" , "application/x-www-form-urlencoded;" ); xmlHttp.send(param); } function refreshMessage() { if (xmlHttp.readyState == 4) { if (xmlHttp.status == 200) { var messages = xmlHttp.responseXML.getElementsByTagName( "message" ); var table_body = document.getElementById( "dynamicUpdateArea" ); var length = table_body.childNodes.length; for (var i = 0; i < length; i++) { table_body.removeChild(table_body.childNodes[0]); } var length = messages.length; for (var i = length - 1; i >= 0 ; i--) { var message = messages[i].firstChild.data; var row = createRow(message); table_body.appendChild(row); } 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; } </script> </head> <body> <p> Your Message: <input id= "text" /> <input type= "button" value= "Send" onclick= "sendMessage()" /> </p> <p>Messages:</p> <table align= "left" > <tbody id= "dynamicUpdateArea" ></tbody> </table> </body> </html> |
簡單抓個畫面…

直接用AJAX,後端用JSP/Servlet,您要對請求參數做些判斷,看看是新增訊息或查詢,並要自行輸出XML,有的沒的…
改成DWR的話,就很簡單了,寫個簡單的Java物件…
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
package onlyfun.caterpillar; import java.util.LinkedList; import java.util.List; public class Chat { private static LinkedList<Message> messages = new LinkedList<Message>(); public List addMessage(String text) { if (text != null && text.trim().length() > 0) { messages.addFirst( new Message(text)); while (messages.size() > 10) { messages.removeLast(); } } return messages; } public List getMessages() { return messages; } } |
接著…在dwr.xml中開放一下…
1
2
3
4
5
6
7
8
9
10
11
12
13
|
<?xml version= "1.0" encoding= "UTF-8" ?> <!DOCTYPE dwr PUBLIC "-//GetAhead Limited//DTD Direct Web Remoting 1.0//EN" "http://www.getahead.ltd.uk/dwr/dwr10.dtd" > <dwr> <allow> <create creator= "new" javascript= "Chat" > <param name= "class" value= "onlyfun.caterpillar.Chat" /> </create> <convert converter= "bean" match= "onlyfun.caterpillar.Message" /> </allow> </dwr> |
使用者取得訊息時,是直接傳回List物件,而List中裝的是Message物件,Message物件是自訂物件,conterver設定為 bean,表示DWR會自動將Message的getter名稱轉換為傳回客戶端的JavaScript物件中的屬性,例如Message中有 getText(),則在客戶端可以用message.text這樣的方式來存取。
接著是簡單的客戶端網頁…
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" > <html> <head> <meta http-equiv= "Content-Type" content= "text/html; charset=BIG5" > <title>Insert title here</title> <script src= "dwr/interface/Chat.js" type= "text/javascript" ></script> <script src= "dwr/engine.js" type= "text/javascript" ></script> <script src= "dwr/util.js" type= "text/javascript" ></script> <script type= "text/javascript" > function sendMessage() { var text = DWRUtil.getValue( "text" ); DWRUtil.setValue( "text" , "" ); Chat.addMessage(text, gotMessages); } function gotMessages(messages) { var chatlog = "" ; for (var data in messages) { chatlog = "<div>" + messages[data].text + "</div>" + chatlog; } DWRUtil.setValue( "chatlog" , chatlog); setTimeout( "queryMessage()" , 2000); } function queryMessage() { Chat.getMessages(gotMessages); } </script> </head> <body> <p> Your Message: <input id= "text" /> <input type= "button" value= "Send" onclick= "sendMessage()" /> </p> <p>Messages:</p> <div id= "chatlog" ></div> </body> </html> |
當List物件傳回時,它成為gotMessages(messages)中的messages物件,而messages物件中包括 Message物件轉換後對應的JavaScript物件,由於我們已經設定了Converter,所以可以用messages[data].text來 取得傳回的訊息…
簡單抓個畫面…
