DWR Server Push(服务器推技术) 实现即时聊天功能(WEB)`详解编程语言

当你有QQ消息时,QQ的小图标会晃动,我们甚至还可以设定QQ有消息时,自动弹出来!

这些在C/S模式下很容易实现!如果要在B/S模式如何来实现呢?

我们的肯定会想到在客服端调用ajax在后台不断的查询服务器.看是否有关于自己的消息.如果有则查询返回.这种做法肯定会大量的占用系统的资源!不可取!

现在DWR的反转AJAX功能.允许我们从服务器端来控制客服端.而不需要客户端来请求.服务器可以自动把消息发给指定的客户端!

我不能把公司的代码贴出来,所以我自己写了一个DEMO,已经实现了对指定用户发送消息的功能,并且即时显示在指定的用户界面上面.当然你可以修改这些,让它弹出来显示,或者像QQ一样在你页面的某个角落让消息的图标闪动:)

下面我做一个简单的说明:

用户的JAVABEAN User.java

 package com.lhq; 
 
/** 
 * 用户类 
 *  
 * @author 廖瀚卿 
 *  
 */ 
public class User { 
 
	private String userid; 
 
	private String username; 
 
	public String getUserid() { 
		return userid; 
	} 
 
	public void setUserid(String userid) { 
		this.userid = userid; 
	} 
 
	public String getUsername() { 
		return username; 
	} 
 
	public void setUsername(String username) { 
		this.username = username; 
	} 
 
	public User(String userid, String username) { 
		super(); 
		this.userid = userid; 
		this.username = username; 
	} 
 
}

聊天处理类 ChatManager.java

 package com.lhq; 
 
import java.util.ArrayList; 
import java.util.Collection; 
import java.util.HashSet; 
import java.util.List; 
 
import javax.servlet.ServletContext; 
import javax.servlet.http.HttpServletRequest; 
 
import org.directwebremoting.ScriptSession; 
import org.directwebremoting.ServerContext; 
import org.directwebremoting.ServerContextFactory; 
import org.directwebremoting.WebContextFactory; 
import org.directwebremoting.proxy.dwr.Util; 
 
/** 
 * 处理聊天相关 
 *  
 * @author 廖瀚卿 
 *  
 */ 
public class ChatManager { 
 
	/** 保存当前在线用户列表 */ 
	public static List<User> users = new ArrayList<User>(); 
 
	/** 
	 * 更新在线用户列表 
	 * @param username 待添加到列表的用户名 
	 * @param flag 是添加用户到列表,还是只获得当前列表 
	 * @param request 
	 * @return 用户userid 
	 */ 
	public String updateUsersList(String username, boolean flag, HttpServletRequest request) { 
		User user = null; 
		if (flag) {	 
			// 这里取会话(HttpSession)的id为用户id  
			user = new User(request.getSession().getId(), username); 
			//保存用户到列表 
			users.add(user);	 
			//将用户id和页面脚本session绑定 
			this.setScriptSessionFlag(user.getUserid()); 
		} 
		//获得DWR上下文 
		ServletContext sc = request.getSession().getServletContext(); 
		ServerContext sctx = ServerContextFactory.get(sc); 
		//获得当前浏览 index.jsp 页面的所有脚本session 
		Collection sessions = sctx.getScriptSessionsByPage("/chat/index.jsp"); 
		Util util = new Util(sessions); 
		//处理这些页面中的一些元素 
		util.removeAllOptions("users"); 
		util.addOptions("users", users, "username"); 
		util.removeAllOptions("receiver"); 
		util.addOptions("receiver", users,"userid","username"); 
		if(!flag){ 
			return null; 
		} 
		return user.getUserid(); 
	} 
 
	/** 
	 * 将用户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 receiverid 接收者id 
	 * @param msg 消息内容 
	 * @param request 
	 */ 
	public void send(String sender,String receiverid,String msg,HttpServletRequest request){ 
		ScriptSession session = this.getScriptSession(receiverid, request); 
		Util util = new Util(session); 
		util.setStyle("showMessage", "display", ""); 
		util.setValue("sender", sender); 
		util.setValue("msg", msg); 
	} 
}

聊天主页面 index.jsp

 <%@ page language="java" pageEncoding="GBK"%> 
<html> 
	<head> 
		<title>chat</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='/chat/dwr/interface/ChatManager.js'></script> 
		<script type='text/javascript' src='/chat/dwr/engine.js'></script> 
		<script type='text/javascript' src='/chat/dwr/util.js'></script> 
		<script type="text/javascript" src="/chat/chat.js"></script> 
	</head> 
	<body> 
		<input type="hidden" name="userid" /> 
		<br> 
		昵称: 
		<input type="text" name="username" /> 
		<input type="button" value="注册" onclick="register(this);" /> 
		<br /> 
		<br /> 
		我要对 
		<select name="receiver" id="receiver" disabled=true" > 
		</select> 
		说: 
		<input type="text" name="message" id="message" disabled="true" /> 
		<input type="button" value="发送" id="send" name="send" disabled="true" 
			onclick="send();" /> 
		<br /> 
		<br /> 
		在线用户列表: 
		<ul id="users"> 
		</ul> 
 
		<div id="showMessage" style="display: none"> 
			<span id="sender">对你说: 
			<span id="msg"> 
		</div> 
	</body> 
</html>

JAVASCRIPT 文件 chat.js

 /** 
 * 注册帐号 
 */ 
function register(button) { 
	if ($('username').value == "" || $('username').value.length <= 0) { 
		alert("请输入昵称"); 
		return; 
	} 
 
	/* 下面是对一些按钮的禁用和激活操作 */ 
	$('username').disabled = true; 
	button.disabled = true; 
	$('message').disabled = false; 
	$('send').disabled = false; 
	$('receiver').disabled = false; 
 
	/* 把我输入的用户名注册到服务器,并获得用户id(这里用session id 代替) */ 
	ChatManager.updateUsersList($('username').value, true, function(data) { 
		if (data != null && data.length > 0) { 
			$('userid').value = data; // 注册成功,把userid放到当前页面 
		} 
	}); 
} 
 
/** 
 * 页面初始化 
 */ 
function init() { 
	dwr.engine.setActiveReverseAjax(true); // 激活反转 重要 
	ChatManager.updateUsersList(null, false); // 当你打开界面的时候,先获得在线用户列表. 
} 
 
/** 
 * 发送消息 
 */ 
function send() { 
	var sender = dwr.util.getValue('username'); // 获得发送者名字 
	var receiver = dwr.util.getValue('receiver'); // 获得接受者id 
	var msg = dwr.util.getValue('message'); // 获得消息内容 
	ChatManager.send(sender, receiver, msg); // 发送消息 
} 
 
window.onload = init;//页面加载完毕后执行初始化方法init

配置文件 web.xml

 <?xml version="1.0" encoding="UTF-8"?> 
<web-app 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"> 
	<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> 
	<servlet-mapping> 
		<servlet-name>dwr-invoker</servlet-name> 
		<url-pattern>/dwr/*</url-pattern> 
	</servlet-mapping> 
</web-app>

DWR配置文件 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.lhq.User"/> 
		<create creator="new" javascript="ChatManager"> 
			 <param name="class" value="com.lhq.ChatManager"/> 
		</create> 
	</allow> 
</dwr>

原创文章,作者:Maggie-Hunter,如若转载,请注明出处:https://blog.ytso.com/7951.html

(0)
上一篇 2021年7月18日
下一篇 2021年7月18日

相关推荐

发表回复

登录后才能评论