來寫個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來 取得傳回的訊息…
簡單抓個畫面…

