JWorld@TW the best professional Java site in Taiwan
      註冊 | 登入 | 全文檢索 | 排行榜  

» JWorld@TW » AJAX討論區 » Java 與 Ajax  

按列印兼容模式列印這個話題 列印話題    把這個話題寄給朋友 寄給朋友    訂閱主題
reply to topicthreaded modego to previous topicgo to next topic
己加入精華區
by CMHuang at 2006-09-25 17:48
本主題所含的標籤
作者 DWR 入門與應用(三) [精華]
caterpillar

良葛格

版主

發文: 2613
積分: 70
於 2006-09-25 17:00 user profilesend a private message to userreply to postreply to postsearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
來寫個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>


簡單抓個畫面…


caterpillar edited on 2006-09-25 17:19
reply to postreply to post
良葛格學習筆記
作者 Re:DWR 入門與應用(三) [Re:caterpillar]
caterpillar

良葛格

版主

發文: 2613
積分: 70
於 2006-09-25 17:08 user profilesend a private message to userreply to postreply to postsearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
直接用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來取得傳回的訊息…

簡單抓個畫面…


caterpillar edited on 2006-09-25 17:18
reply to postreply to post
良葛格學習筆記
作者 Re:DWR 入門與應用(三) [Re:caterpillar]
zach14c





發文: 42
積分: 1
於 2006-09-25 21:17 user profilesend a private message to userreply to postreply to postsearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
很謝謝您, 用一個以手工寫script/servlet的方式實作AJAX與使用DWR的比較。
但有個疑問,不知道是沒看清楚,還是會錯意?在文中有提及
“另外還設定了週期性的輪詢,即使不輸入新訊息,也可以週期性的取得新的聊天訊息“
,可是沒有看到script有assign body onload的event,是否一定要送出訊息才會自動得到訊息?

還麻煩您解答,謝謝。

Smile


zach14c edited on 2006-09-25 21:38
reply to postreply to post
作者 Re:DWR 入門與應用(三) [Re:zach14c]
caterpillar

良葛格

版主

發文: 2613
積分: 70
於 2006-09-26 08:20 user profilesend a private message to userreply to postreply to postsearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
只是簡單的使用setTimeout()每兩秒自動去取得訊息…Big Smile

reply to postreply to post
良葛格學習筆記
作者 Re:DWR 入門與應用(三) [Re:caterpillar]
fjpan2002





發文: 3
積分: 0
於 2007-11-29 16:42 user profilesend a private message to userreply to postreply to postsearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
采用DWR2.0的reverse ajax技术,可以自动将服务器端的信息push到客户端,这样就不用使用setTimeout()去获取信息了。

reply to postreply to post
作者 Re:DWR 入門與應用(三) [Re:caterpillar]
kop00618





發文: 1
積分: 0
於 2010-10-14 11:42 user profilesend a private message to userreply to postreply to postsearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
請問一下大大~我照你這個範例做完之後~上傳到網路上...結果打中文字都是???這是為什麼呢??

reply to postreply to post
» JWorld@TW »  AJAX討論區 » Java 與 Ajax

reply to topicthreaded modego to previous topicgo to next topic
  已讀文章
  新的文章
  被刪除的文章
Jump to the top of page

JWorld@TW 本站商標資訊

Powered by Powerful JuteForum® Version Jute 1.5.8