b/s模式下的即时通讯,使用ajax框架dwr实现
b/s模式下的即時通訊,使用ajax框架dwr實現(xiàn)
?
了解java的發(fā)展史可以知道,客戶端編程在基于瀏覽器的編程方面,以前的做法是用applet實現(xiàn)客戶端編程,在當時算是流行的做法,但是隨著IE的不一致,尤其是微軟的不支持,
Applet沒有發(fā)展起來,還有一個原因就是在瀏覽器中要下載java運行時插件,這幾M的大小,對于以前網(wǎng)速就慢的網(wǎng)絡,無疑斷送了它的性命。現(xiàn)在應用與客戶端瀏覽器的技術主要為一些牛人自己開發(fā)的插件,通過下載實現(xiàn)自己的功能?,F(xiàn)在最通用最新的做法是利用XmlHttpRequext,異步實現(xiàn)客戶端請求,也就是通常所說的ajax(異步的JavaScript和xml)技術,可以使用封裝好的dwr框架簡化開發(fā),另一種方式就是使用Flex技術,就是Flash腳本編程,只是聽說,自己還沒有用過。
?
自己寫了一個使用ajax框架dwr實現(xiàn)簡易的即時通信程序。
首先什么是dwr呢?DWR是一個框架,簡單的說就是能夠在javascript直接調(diào)用java方法,而不必去寫一大堆的javascript代碼。它的實現(xiàn)是基于ajax的,可以實現(xiàn)無刷新效果。
一、?????????? dwr配置篇
1.web.xml
<servlet>
?????? <servlet-name>dwr-invoker</servlet-name>
?????? <servlet-class>
?????????? org.directwebremoting.servlet.DwrServlet
?????? </servlet-class>
?????? <init-param>
?????????? <description>調(diào)試DWR,發(fā)布系統(tǒng)時應將其設為false</description>
?????????? <param-name>debug</param-name>
?????????? <param-value>true</param-value>
?????? </init-param>
?????? <init-param>
?????????? <description>使用服務器推技術(反轉(zhuǎn)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>
這個參數(shù)DWR默認是false。如果選擇true,我們可以通過http://localhost:port/app/dwr看到你部署的每個DWR class。并且可以測試java代碼的每個方法是否運行正常。為了安全考慮,在正式環(huán)境下你一定把這個參數(shù)設為false。
2.使用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>
二.Dwr使用篇
實例:b/s模式下的即時通訊,使用ajax框架dwr實現(xiàn)
1.?????? 首先把dwr.jar包放在項目lib目錄下。
2.?????? 進行上述web.xml相關配置,上述配置就是本實例的配置。
3.?????? 為實現(xiàn)功能寫的javabean,可能還有servlet,但本實例沒有牽涉到servlet。代碼如下:
package com.lhq;
?
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
?
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
?
import org.directwebremoting.ScriptBuffer;
import org.directwebremoting.ScriptSession;
import org.directwebremoting.ServerContext;
import org.directwebremoting.ServerContextFactory;
import org.directwebremoting.WebContextFactory;
import org.directwebremoting.proxy.dwr.Util;
?
/**
?*處理聊天相關
?*
?*@authorlhq
?*
?*/
publicclass ChatManager {
?
??? /**保存當前在線用戶列表*/
??? publicstatic List<User> users = new ArrayList<User>();
?
??? /**
??? ?*更新在線用戶列表
??? ?*
??? ?*@paramusername
??? ?*??????????? 待添加到列表的用戶名
??? ?*@paramflag
??? ?*??????????? 是添加用戶到列表,還是只獲得當前列表
??? ?*@paramrequest
??? ?*@return用戶userid
??? ?*/
??? public String updateUsersList(String username, boolean flag,
?????????? HttpServletRequest request) {
?????? User user = null;
?????? if (flag) {
?????????? // 這里取會話(HttpSession)的id為用戶id
?????????? System.out.println("aauserid:" + request.getSession().getId());
?????????? 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("/BalanceCenter/index.jsp");
?????? System.out.println("session的記錄數(shù):" + sessions.size());
?????? // 消除不存在的頁面session
?????? System.out.println("session的記錄數(shù)(消除后):" + sessions.size());
?????? Util util = new Util(sessions);
?????? // 處理這些頁面中的一些元素
?????? util.removeAllOptions("users");
?????? util.addOptions("users", users, "username");
?????? util.removeAllOptions("receiver");
?????? util.addOptions("receiver", users, "userid", "username");
?????? if (!flag) {
?????????? returnnull;
?????? }
?????? return user.getUserid();
??? }
?
??? /**
??? ?*
??? ?*當退出時更新user
??? ?*
??? ?*
??? ?*/
??? publicvoid delUser(HttpServletRequest request) {
?????? String userid = request.getSession().getId();// 與userid相等,呵呵
?????? System.out.println("userIdaa:" + userid);
?????? Iterator it = users.iterator();
?????? while (it.hasNext()) {
?????????? User user = (User) it.next();
?????????? System.out.println(user.getUsername());
?????????? System.out.println("userId:" + user.getUserid());
?????????? if (user.getUserid().equals(userid)) {
????????????? users.remove(user);
????????????? break;
?????????? }
?????? }
?????? updateUsersList(null, false,request) ;
??? }
?
??? /**
??? ?*將用戶id和頁面腳本session綁定
??? ?*
??? ?*@paramuserid
??? ?*/
??? publicvoid setScriptSessionFlag(String userid) {
?????? WebContextFactory.get().getScriptSession().setAttribute("userid",
????????????? userid);
??? }
?
??? /**
??? ?*根據(jù)用戶id獲得指定用戶的頁面腳本session
??? ?*
??? ?*@paramuserid
??? ?*@paramrequest
??? ?*@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("/BalanceCenter/index.jsp"));
?????? for (ScriptSession session : sessions) {
?????????? String xuserid = (String) session.getAttribute("userid");
?????????? if (xuserid != null && xuserid.equals(userid)) {
????????????? scriptSessions = session;
?????????? }
?????? }
?????? return scriptSessions;
??? }
?
??? /**
??? ?*發(fā)送消息
??? ?*
??? ?*@paramsender
??? ?*??????????? 發(fā)送者
??? ?*@paramreceiverid
??? ?*??????????? 接收者id
??? ?*@parammsg
??? ?*??????????? 消息內(nèi)容
??? ?*@paramrequest
??? ?*/
??? publicvoid send(String sender, String receiverid, String msg,
?????????? HttpServletRequest request) {
?????? ScriptSession session = this.getScriptSession(receiverid, request);
?????? Util util = new Util(session);
?
?????? util.setStyle("showMessage", "display", "");
?????? ScriptBuffer script = new ScriptBuffer();
?????? script.appendScript("receiveMessages(").appendData(
????????????? sender + "說:" + msg + "/n").appendScript(");");
?????? session.addScript(script);
??? }
}
4.?????? 進行dwr.xml相對于javabean的相關配置,及提供客戶端JavaScript腳本對于java方法的可見性。上述代碼及為本實例代碼。
5.?????? 客戶端javascript中調(diào)用
自定義一個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;
??? $('send').disabled = false;
??? $('exit').disabled = false;
??? /*調(diào)用后臺ChatManager類的updateUsersList方法,并取得返回值元數(shù)據(jù)放在data中*/
??? ChatManager.updateUsersList($('username').value, true, function(data) {
?????? if (data != null && data.length > 0) {
?????????? $('userid').value = data; //??? 把當前sessionId放在隱藏表單
}
??? });
}
?
/**
?*初始化
?*/
function init() {
??? dwr.engine.setActiveReverseAjax(true); // 激活反轉(zhuǎn)
??? ChatManager.updateUsersList(null, false); //和上面那個方法一樣
}
function delUser(button) {
??? ChatManager.delUser(); //當退出是調(diào)用,消除該在線用戶
/**
?*并對相應按鈕進行相應處理
?*/
?
??? $('username').disabled = false;
??? $('register').disabled = false;
??? button.disabled=true;
??? $('receiver').disabled = true;
??? $('send').disabled = true;
??? $('areaMessage').innerHTML = "";
}
/**
?* 當發(fā)送信息是調(diào)用
?*/
function send() {
??? var sender = dwr.util.getValue('username'); //取得該用戶的名字
??? var receiver = dwr.util.getValue('receiver'); // 取得接收者
??? var msg = FCKeditorAPI.GetInstance("message").EditorDocument.body.innerHTML; // 取得文本編輯器的文本
??? ChatManager.send(sender, receiver, msg); //調(diào)用后臺方法
}
/**
*這是后臺推技術調(diào)用的方法,接受信息
*/
function receiveMessages(message) {
//取得聊天信息中文本
??? var messages=document.getElementById("areaMessage").innerHTML;
??? document.getElementById("areaMessage").innerHTML=message+"<hr/>"+messages;
???
}
?
window.onload = init;//頁面加載時
?
6.?????? html代碼
需要導入必須的js文件,在文本編輯時,我用了一個fckEditor文本編輯器,上網(wǎng)下一個就可以了,放在根目錄下,本人美感欠缺,頁面不太好看,請見諒!具體代碼如下:
<%@ page language="java" pageEncoding="GBK"%>
<% String context=request.getContextPath();
?? pageContext.setAttribute("ctx",context);
%>
<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='/BalanceCenter/dwr/interface/ChatManager.js'></script>
?????? <script type='text/javascript' src='/BalanceCenter/dwr/engine.js'></script>
?????? <script type='text/javascript' src='/BalanceCenter/dwr/util.js'></script>
?????? <script type="text/javascript" src="/BalanceCenter/chat.js"></script>
?????? <script type="text/javascript" src="${ctx}/fckeditor/fckeditor.js"></script>
??? </head>
??? <body>
?????? <input type="hidden" name="userid" />
?????? <br>
?????? 昵稱:
?????? <input type="text" name="username" id="username" />
?????? <input type="button" value="注冊" onclick="register(this);" id="register"/>
?????? <input type="button" value="退出" onclick="delUser(this);" id="exit"/>
?????? <br />
?????? <br />
?????? 我要對
?????? <select name="receiver" id="receiver" disabled=true" >
?????? </select>
?????? 說:
?????? <script type="text/javascript">
????????????? var oFCKeditor = new FCKeditor("message");
????????????? oFCKeditor.BasePath? = '${ctx}/fckeditor/' ;
????????????? oFCKeditor.Height = 300 ;
????????????? oFCKeditor.ToolbarSet = 'Default';
????????????? oFCKeditor.Create() ;
????????????? </script>
??????
?????? <input type="button" value="發(fā)送" id="send" name="send" disabled="true"
?????????? onclick="send();" />
?????? <br />
?????? <br />
?????? 在線用戶列表:
??????
?????? <ul id="users">
?????? </ul>
??????
??????
?????? <div id="showMessage" style="display: none">
?
?????? <div id="areaMessage" style="position:absolute;
??? width:600px;
??? height:300px;
??? z-index:1;
??? border:solid;
??? overflow:auto;
??? ">
??? </div>
?????? </div>
??????
??? </body>
</html>
好了,終于寫完了,首先要說明一下,本程序不是很完善,具體在:用戶只有點擊“退出”按鈕才可以實現(xiàn)把該在線人員刪除掉,可能利用js也可以實現(xiàn)關閉頁面也可以把該在線人員刪除掉,但是如果用戶刷新了,怎么辦呢???就是怎么記錄有效地scriptsession呢?有人說用map保存。本人沒有試過,還望高手指點,不勝感激!!!
總結
以上是生活随笔為你收集整理的b/s模式下的即时通讯,使用ajax框架dwr实现的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ACCESS数据库连接字符串
- 下一篇: mysql锁机制总结