`
yaojialing
  • 浏览: 255433 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

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="登录" onclick="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="发  送" onclick="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 onload="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 onload="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

 

 

  • chat.rar (870.7 KB)
  • 描述: 两个例子reverse ajax的实现
  • 下载次数: 373
  • ichat.rar (1.6 MB)
  • 描述: 本人参照上面写的群聊天例子
  • 下载次数: 509
  • 描述: 主界面
  • 大小: 28.5 KB
分享到:
评论
3 楼 allanpoe 2011-08-12  
我使用的AOM框架,这是基于jsf的,我在里面使用
WebContext context = WebContextFactory.get();
   Collection<ScriptSession> sessions = context.getScriptSessionsByPage("/dwrpush/index.jsp");
总是报空指针错误

我看你的例子比如通过WebContext实现session与userid的绑定,怎么办呢?在jsf里怎么构造WebContext呢?
2 楼 caofackri 2011-07-14  
有demo真好!
1 楼 xuezhongde 2010-09-25  
非常好的例子
Thanks

相关推荐

    DWR2.0 中文手册

    DWR (Direct Web Remoting) 是一个开源的Java库,它允许Web应用程序在客户端JavaScript和服务器端Java代码之间进行实时通信,类似于Ajax技术,但提供了更强大的功能。DWR 2.0版本是在DWR 1.x基础上的升级,改进了...

    DWR2.0 整合Spring2.0

    DWR2.0可以通过Spring的AOP支持来实现这些功能,提升应用程序的安全性和可维护性。 3. **安全性**:DWR提供了安全机制,如白名单和签名,以防止跨站脚本攻击(XSS)和跨站请求伪造(CSRF)。整合Spring后,可以通过...

    即时通讯DWR Reverse Ajax

    DWR(Direct Web Remoting)是实现这种功能的一种技术,尤其以其独特的Reverse Ajax特性在服务器推送(Server-Sent Events, SSE,也常被称为Comet技术)领域中备受关注。下面我们将深入探讨DWR Reverse Ajax的工作...

    DWR2.0中文文档

    **DWR2.0中文文档**是一本由方佳玮编著的专业技术书籍,主要涵盖了Direct Web Remoting(DWR)2.0版本的相关知识。...通过深入阅读和实践,你将能更好地利用DWR2.0实现高效的、用户友好的Web应用。

    dwr2.0 dwr3.0 jar包

    DWR(Direct Web Remoting)是一个开源的Java库,它为Web应用程序提供了强大的Ajax功能。通过DWR,前端JavaScript可以直接调用后端Java方法,从而实现动态、实时的Web交互,提升用户体验。这个主题主要围绕DWR的两个...

    使用dwr2.0实现服务器推客户端

    总的来说,通过DWR 2.0和Socket服务器的结合,我们可以构建一个高效、实时的服务器推系统,实现在Web应用中向客户端实时推送数据。这个过程涉及到Web应用的多个层面,包括服务器端的Java接口、客户端的JavaScript...

    dwr3ReverseAjax示例

    在这个“dwr3ReverseAjax示例”中,我们将深入探讨如何利用DWR 3.x版本来构建一个基于Ajax的简单Web聊天应用。 首先,DWR的核心功能是通过HTTP协议实现在客户端JavaScript和服务器端Java之间的远程方法调用(Remote...

    dwr2.0学习例子

    **DWR 2.0 学习例子** ...这个"Dwr2.0学习例子"提供了实践DWR功能的机会,对于理解DWR的工作原理和提升Ajax开发技能非常有帮助。通过深入学习和实践,开发者能够更好地利用DWR的优势,提高Web应用的交互性和响应速度。

    DWR3.0.jar、DWR.war和DWR2.0中文说明文档

    Direct Web Remoting (DWR) 是一个开源的Java库,允许Web应用程序在浏览器和服务器之间进行实时通信,绕过传统的Ajax限制。这个压缩包包含了DWR的三个关键组件:DWR3.0.jar,DWR的实例war文件,以及DWR2.0的中文说明...

    dwr2.0最简单例子实用亲测试

    在“dwr2.0最简单例子实用亲测试”中,我们可以预期这是一个关于如何使用DWR 2.0版本的入门教程,包含了实际可运行的示例代码。下面将详细介绍DWR的基本概念和在这个实例中可能涉及的关键知识点: 1. **DWR的核心...

    dwr 2.0 的 dtd 和官方网站首页

    DWR (Direct Web Remoting) 是一个开源的Java库,它允许JavaScript在浏览器端与服务器端的Java对象进行直接交互,实现动态Web应用程序的功能。DWR 2.0 是DWR的一个版本,提供了许多增强的功能和改进,以适应不断发展...

    DWR2.jar + DWR.xml + DWR2.0.dtd + Web.xml

    DWR2.jar提供了核心功能,DWR.xml定制了DWR的行为,DWR2.0.dtd保证了配置文件的正确性,而Web.xml确保了DWRServlet的正确部署和配置。通过熟练掌握这些知识点,开发者可以有效地利用DWR构建动态、交互性强的Web应用...

    dwr2.0驱动 AJAX驱动

    Ajax dwr驱动包 开发异步要用的 dwr中文文档

    DWR dwr 2.0 dwr推 推 反转ajax 聊天系统 广播系统 字符串加密 历史记录 推技术 聊天系统源码 源码 注释

    这是,以上两个版本的升级版,在原有的基础上,增加了 清空聊天记录,上线通知,用户id,及登录的所在地(ip),聊天信息可选择颜色, ps: 测试的时候记得将 info.txt(聊天信息保存文件) 绝对路径覆盖源码中,以前的路径,

    Dwr3.0 与 Dwr2.0 区别

    DWR(Direct Web Remoting)是一种用于简化 AJAX 应用程序开发的技术。它允许客户端 JavaScript 直接调用服务器端 Java 方法,从而降低了 AJAX 编程的复杂度。DWR 的最新版本为 3.0,而其前身版本为 2.0。本文将详细...

    dwr2.0 spring 3.0 整合示例

    整合DWR 2.0 和Spring 3.0 可以极大地提升Web应用的交互体验,让开发者能够更轻松地实现复杂的Ajax功能,同时保持良好的结构和可维护性。通过上述步骤,你可以创建一个演示项目,理解如何将这两个强大的工具结合在...

Global site tag (gtag.js) - Google Analytics