dwr 2.0(reverse ajax)實現推的web IM例子

根據網上一些reverse ajax例子,自己隨便寫了個羣內聊天的例子,只實現了羣聊天,其它一些雜七雜八的都沒實現,寫這麼個功能只是學習下reverse ajax而已,瞭解服務器推技術。

 

開發工具:eclipse 3.4 純淨版

環境:tomcat 6

技術:DWR

 

工程類說明:

ChatManager.java 聊天實現類

Message.java 消息封裝類

OnlineCounter.java 在線人數計算方法

OnlineCounterListener.java  統計在線人數

User.java  用戶bean

 

頁面:

index.jsp  --輸入http:127.0.0.1:8080/ichat自動訪問此頁面

ShowModel_Frames.jsp  --登錄之後羣聊天的主界面

example.jsp  --FCKEDIT編輯器頁面

excute_sent.jsp  -- 消息發送頁面

online_list.jsp  --在線列表頁面

show_msg.jsp  --顯示消息頁面

 

 

代碼:

 

ChatManager.java 聊天實現類:

package com.ccic.chat;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;

import javax.servlet.http.HttpServletRequest;

import org.directwebremoting.ScriptSession;
import org.directwebremoting.ServerContextFactory;
import org.directwebremoting.WebContext;
import org.directwebremoting.WebContextFactory;
import org.directwebremoting.proxy.dwr.Util;

/**
 * 處理聊天相關
 * 
 * 
 * 
 */
public class ChatManager {

	/** 保存當前在線用戶列表 */
	public static List<User> users = new ArrayList<User>();

	/**
	 * 更新在線用戶列表
	 * @param request
	 */
	public void updateUsersList(HttpServletRequest request) {
		User user = null;
		String flag="0";//標識用戶,0:不存在  1:已存在
		String name= request.getSession().getAttribute("uname").toString();
		String pwd= request.getSession().getAttribute("pwd").toString();
		System.out.println("用戶ID="+name+"   用戶密碼="+pwd);
		user = new User(pwd, name);
		//保存用戶到列表
		//如果列表中無任何用戶則添加,否則循環查找列表中是否已存在該用戶,
		//如果不存在,則添加。如果存在,則不添加
		if(users.size() == 0){
			users.add(user);
		}else{
			for(int i=0;i<users.size();i++){
				User us =(User)users.get(i);
				if(us.getUsername().equals(name)){
					flag="1";
					break;	
				}
			}
			if(flag.equals("0")){
				users.add(user);
			}
		}
		
		/*//統計在線人數
		long count=OnlineCounter.getOnline();
		
		StringBuffer sb=new StringBuffer();
		sb.append("<script language='JavaScript' defer='defer'>");
		sb.append("d = new dTree(\'d\');");
		sb.append("d.add(0,-1,'在線用戶列表(當前"+count+"人)');");
		for(int i=0;i<users.size();i++){
			User us =(User)users.get(i);
			sb.append("d.add("+(i+1)+",0,'"+us.getUsername()+"','','','');");
		}
		sb.append("document.write(d);");
		sb.append("d.config.useCookies=false;");
		sb.append("d.config.closeSameLevel=true;");
		sb.append("</script");//注意這裏並不是好了“>”括號,而是在頁面另有處理
		
		System.out.println("dd="+sb.toString());*/
		//將用戶id和頁面腳本session綁定
		//this.setScriptSessionFlag(user.getUsername());
		
		// 獲得WEB上下文
        WebContext wctx = WebContextFactory.get();
		//獲得在線列表 頁面的所有腳本session
		Collection sessions = wctx.getScriptSessionsByPage("/ichat/pages/main/online_list.jsp");
		Util util = new Util(sessions);
		//處理這些頁面中的一些元素
		//util.addFunctionCall("cBack_list", sb.toString());
		util.removeAllOptions("users");
		util.addOptions("users", users, "username");
	}

	/**
	 * 將用戶id和頁面腳本session綁定
	 * @param userid
	 */
	public void setScriptSessionFlag(String userid) {
		WebContextFactory.get().getScriptSession().setAttribute("userid", userid);
	}

	/**
	 * 根據用戶id獲得指定用戶的頁面腳本session
	 * @param userid
	 * @param request
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public ScriptSession getScriptSession(String userid, HttpServletRequest request) {
		ScriptSession scriptSessions = null;
		Collection<ScriptSession> sessions = new HashSet<ScriptSession>();
		sessions.addAll(ServerContextFactory.get(request.getSession().getServletContext())
				.getScriptSessionsByPage("/chat/index.jsp"));
		for (ScriptSession session : sessions) {
			String xuserid = (String) session.getAttribute("userid");
			if (xuserid != null && xuserid.equals(userid)) {
				scriptSessions = session;
			}
		}
		return scriptSessions;
	}
	
	/**
	 * 發送消息
	 * @param sender 發送人
	 * @param msg 發送內容
	 * @param request 發送請求
	 */
	public void send(String sender,String msg,HttpServletRequest request){
		System.out.println("sender="+sender+" msg="+msg);
        LinkedList<Message> messages = new LinkedList<Message>();
        if (msg != null && msg.trim().length() > 0) {
        	//AA 說(2010-07-13): <br/>你好!
            messages.addFirst(new Message(sender,msg));
            while (messages.size() > 3) {
                messages.removeLast();
            }
        }
		
		// 獲得WEB上下文
        WebContext wctx = WebContextFactory.get();
        //向指定頁面推送消息
        Collection sessions = wctx.getScriptSessionsByPage("/ichat/pages/main/show_msg.jsp");
        Util utilAll = new Util(sessions);
        utilAll.addFunctionCall("callBack", messages);
	}
	
	//獲得離線消息,思路:當A發消息給B時,將A用戶發送的消息保存到B用戶的ScriptSession中,
	//當B用戶上線時把已經保持在B的ScriptSession中的消息讀取處理並全部推送到頁面。
	public void getOfflineMsg(){
		
	}
}

 

 

Message.java 消息封裝類

package com.ccic.chat;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;

import org.directwebremoting.Security;
public class Message {
	DateFormat df = new SimpleDateFormat("HH:mm:ss");    
	private String serverTime = df.format(new Date());
    private String text;
    private String online;
    public String getOnline() {
		return online;
	}
	public void setOnline(String online) {
		this.online = online;
	}
	public Message(String sender,String newtext) {
        text = newtext;
        if (text.length() > 256) {
            text = text.substring(0, 256);
        }
        text = sender+" 說 "+"("+serverTime+"):<br/>"+text;
    }
    public String getText() {
        return text;
    }
    
    
}

 

 

OnlineCounter.java 在線人數計算方法

 

package com.ccic.chat;

public class OnlineCounter {
	private static long online = 0;

	public static long getOnline() {
		return online;
	}

	public static void raise() {
		online++;
	}

	public static void reduce() {
		online--;
	}
}

 

 

OnlineCounterListener.java  統計在線人數

 

package com.ccic.chat;

import javax.servlet.http.HttpSessionEvent;   
import javax.servlet.http.HttpSessionListener;   
/**
 * 統計在線用戶數量  
 * 
 */
public class OnlineCounterListener implements HttpSessionListener{   
	/**
	 * 當SESSION創建時,自動增加
	 */
    public void sessionCreated(HttpSessionEvent hse) {    
        OnlineCounter.raise();     
    }    
    /**
	 * 當SESSION銷燬時,自動減少
	 */
   public void sessionDestroyed(HttpSessionEvent hse){     
        OnlineCounter.reduce();   
    }    
}    

 

 

User.java  用戶bean

 

 

package com.ccic.chat;

/**
 * 用戶
 * 
 * 
 * 
 */
public class User {

	private String password;

	private String username;

	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	public String getUsername() {
		return username;
	}

	public void setUsername(String username) {
		this.username = username;
	}

	public User(String password, String username) {
		super();
		this.password = password;
		this.username = username;
	}
	

}

 

 

index.jsp  --輸入http:127.0.0.1:8080/ichat自動訪問此頁面

 

<%@ page language="java" contentType="text/html; charset=GBK"
    pageEncoding="GBK"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<title>Insert title here</title>
<script language="javascript" type="text/javascript"> 
	function subm(){
		var uname=document.form1.username.value;
		var pwd=document.form1.password.value;
		if (uname == "") {
			alert("請輸入用戶ID");
			return;
		}
		
		window.location="<%=request.getContextPath() %>/pages/frames/ShowModel_Frames.jsp?uname="+uname+"&pwd="+pwd;  
	}
</script>
</head>

<body>
<form id="ff" name="form1">
<fieldset>
<legend>登錄</legend>
	<table align="center">
		<tr>
			<td>username:</td>
			<td><input type="text" name="username"></td>
		</tr>
		<tr>
			<td>password:</td>
			<td><input type="text" name="password"></td>
		</tr>
		<tr align="center">
			<td colspan="2"><input type="button" name="sub" value="登錄" οnclick="subm();"><input type="reset" name="res" value="重置"></td>
		</tr>
	</table>
</fieldset>
</form>
</body>
</html>

 

 

ShowModel_Frames.jsp  --登錄之後羣聊天的主界面

 

<%@ page language="java" pageEncoding="GB2312"%>
<%
	//(模擬)獲取登錄的唯一用戶ID,放到SESSION供online_list.jsp加載在線用戶列表
	String uname = request.getParameter("uname");
	uname=new String(uname.getBytes("ISO-8859-1"),"gbk");
	String pwd = request.getParameter("pwd");
	request.getSession().setAttribute("uname",uname);
	request.getSession().setAttribute("pwd",pwd);
%>

<html>
<head>
<meta HTTP-EQUIV="Pragma" CONTENT="no-cache">
<title>聊天主界面框架</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
</head>
<frameset cols="*,230" frameborder="yes" border="0" framespacing="0">
	<frameset rows="400,*" frameborder=yes border="5" framespacing="5">
	  <frame src="<%=request.getContextPath() %>/pages/main/show_msg.jsp" name="main_one" scrolling=yes noresize>
	  <frame src="<%=request.getContextPath() %>/pages/main/excute_sent.jsp" name="main_two" scrolling=yes noresize>
	</frameset>
	<frame src="<%=request.getContextPath() %>/pages/main/online_list.jsp" name="main_top" scrolling=no noresize>
</frameset>
<noframes>
<body>
很抱謙,您使用的瀏覽器不支持框架功能,請採用新版本的瀏覽器。
</body>
</noframes>

</html>

 

 

example.jsp  --FCKEDIT編輯器頁面

excute_sent.jsp  -- 消息發送頁面

<%@ page language="java" contentType="text/html; charset=GBK"
    pageEncoding="GBK"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Insert title here</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<script type="text/javascript" src="<%=request.getContextPath() %>/fckeditor/fckeditor.js"></script>
<script type='text/javascript' src='/ichat/dwr/interface/ChatManager.js'></script>
<script type='text/javascript' src='/ichat/dwr/engine.js'></script>
<script type='text/javascript' src='/ichat/dwr/util.js'></script>
<script language="javascript">
	/**
 * 發送消息
 */
function send() {
	var sender = '<%=request.getSession().getAttribute("uname").toString() %>'; // 獲得發送者名字
	//var receiver = dwr.util.getValue('receiver'); // 獲得接受者id
	var msg = getEditorHTMLContents('edt1'); // 獲得消息內容
	ChatManager.send(sender, msg); // 發送消息
	SetEditorContents('edt1','');//清空編輯器中發送的消息
}
//獲取編輯器中HTML內容
function getEditorHTMLContents(EditorName)
{ 
    var oEditor = FCKeditorAPI.GetInstance(EditorName);
    return oEditor.GetXHTML(true); 
}
//設置編輯器中內容
function SetEditorContents(EditorName, ContentStr)
{ 
    var oEditor = FCKeditorAPI.GetInstance(EditorName) ; 
    oEditor.SetHTML(ContentStr) ; 
}

</script>
</head>
<body style="margin: 0px;">
<form method="post" name="frm1">
    <script type="text/javascript">
        var oFCKeditor = new FCKeditor("edt1");
        oFCKeditor.BasePath = "<%=request.getContextPath() %>/fckeditor/";
        oFCKeditor.ToolbarSet="ichat";
        oFCKeditor.Height='160';
        oFCKeditor.Value="";
        oFCKeditor.Create();
    </script>
    <input type="button" value="發  送" οnclick="send();">
</form>
</body>
</html>

 

 

online_list.jsp  --在線列表頁面

<%@ page language="java" contentType="text/html; charset=GBK"
    pageEncoding="GBK" import="com.ccic.chat.OnlineCounter" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Insert title here</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<link rel="stylesheet" href="<%=request.getContextPath()%>/include/css/dtree.css" type="text/css">
<script src="<%=request.getContextPath()%>/include/js/dtree.js"></script>
<script type='text/javascript' src='/ichat/dwr/interface/ChatManager.js'></script>
<script type='text/javascript' src='/ichat/dwr/engine.js'></script>
<script type='text/javascript' src='/ichat/dwr/util.js'></script>
</head>
<script language="javascript">
	function register() {
		//把我輸入的用戶名註冊到服務器
		ChatManager.updateUsersList();
	}
		
	//頁面初始化
	function init() {
		dwr.engine.setActiveReverseAjax(true); // 激活反轉 重要
		register();
	}
	//回調函數
	//function cBack_list(data){
		//document.getElementById("online_list").insertAdjacentHTML("afterBegin","");
		//var str="aa"+data+">";
		//document.getElementById("online_list").insertAdjacentHTML("afterBegin",str);
    //}
	
</script>
<body οnlοad="init();">
	在線用戶列表(當前<%=OnlineCounter.getOnline() %>人):
		<ul id="users">
		</ul>
		<!--<div id="online_list">
			
		</div>
		-->
</body>
</html>

 

 

show_msg.jsp  --顯示消息頁面

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Insert title here</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<script type='text/javascript' src='/ichat/dwr/interface/ChatManager.js'></script>
<script type='text/javascript' src='/ichat/dwr/engine.js'></script>
<script type='text/javascript' src='/ichat/dwr/util.js'></script>
</head>
<script language="javascript"> 
		
	//頁面初始化
	function init() {
		dwr.engine.setActiveReverseAjax(true); // 激活反轉 重要
	}
	function callBack(data){
            DWRUtil.addRows("tbodyId", data, cellFunctions,{escapeHtml:false}); 
        }
    var cellFunctions = [
        function(item) { 
           return item.text;
        }
    ];
</script>
<body οnlοad="init();">
	<table>
		<tbody id="tbodyId">
		</tbody>
	</table>
</body>
</html>

 

 dwr.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE dwr PUBLIC "-//GetAhead Limited//DTD Direct Web Remoting 2.0//EN" "http://getahead.org/dwr/dwr20.dtd">
<dwr>
	<allow>
		<convert converter="bean" match="com.ccic.chat.User"/>
		<create creator="new" javascript="ChatManager">
			 <param name="class" value="com.ccic.chat.ChatManager"/>
		</create>
		
		<convert converter="bean" match="com.ccic.chat.Message"/>
	</allow>
</dwr>

 

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
  <display-name>ichat</display-name>
  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>
  <servlet>
		<servlet-name>dwr-invoker</servlet-name>
		<servlet-class>
			org.directwebremoting.servlet.DwrServlet
		</servlet-class>
		<init-param>
			<description>調試DWR,發佈系統時應將其設爲false</description>
			<param-name>debug</param-name>
			<param-value>true</param-value>
		</init-param>
		<init-param>
			<description>使用服務器推技術(反轉AJAX)</description>
			<param-name>activeReverseAjaxEnabled</param-name>
			<param-value>true</param-value>
		</init-param>
		<init-param>
			<param-name>
				initApplicationScopeCreatorsAtStartup
			</param-name>
			<param-value>true</param-value>
		</init-param>
		<init-param>
			<param-name>maxWaitAfterWrite</param-name>
			<param-value>100</param-value>
		</init-param>
		<load-on-startup>4</load-on-startup>
	</servlet>
	<listener>
		<listener-class>
			com.ccic.chat.OnlineCounterListener
		</listener-class>
	</listener>
	<servlet-mapping>
		<servlet-name>dwr-invoker</servlet-name>
		<url-pattern>/dwr/*</url-pattern>
	</servlet-mapping>
</web-app>

 

關於FCKEDIT編輯器,我已經刪除多餘的一些東西了,收集:

----------------------FCKEDIT HTML在線編輯器------------------------------
配置:http://blog.csdn.net/xiaokuang513204/archive/2010/07/06/5715029.aspx

插件開發:http://blog.csdn.net/flying_huang/archive/2007/03/23/1539206.aspx

火狐 兼容fckedt:http://www.wangzhanweb.com/html/2010-05/231.html

FCKEditor的賦值和取值操作 :http://www.blogjava.net/feingto/archive/2008/01/09/173963.html

 

我參考的網上兩個例子,見附件!名稱“chat”

一個是所有對象間聊天的,訪問時對應得頁面是index.jsp.

一個是點對點對象聊天的,訪問時對應得頁面是sample.jsp.

兩者都只是簡單的例子實現。

 

自己實現的羣聊天簡單例子,見附件!名稱“ichat”

運行:輸入http://127.0.0.1:8080/ichat/ 進入登錄界面,輸入“AA” 或者別的就行了。

 

 

參考:

開源的comet實現:pushlet,dwr 2.0的reverse ajax和dojo的io.bind(),

簡單例子(reverse ajax):http://blog.sina.com.cn/s/blog_5bd96d520100gau4.html

 

談談webIM :http://akalius.iteye.com/blog/192727

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章