b/s模式下的即时通讯,使用ajax框架dwr实现

了解java的发展史可以知道,客户端编程在基于浏览器的编程方面,以前的做法是用applet实现客户端编程,在当时算是流行的做法,但是随着IE的不一致,尤其是微软的不支持,

Applet没有发展起来,还有一个原因就是在浏览器中要下载java运行时插件,这几M的大小,对于以前网速就慢的网络,无疑断送了它的性命。现在应用与客户端浏览器的技术主要为一些牛人自己开发的插件,通过下载实现自己的功能。现在最通用最新的做法是利用XmlHttpRequext,异步实现客户端请求,也就是通常所说的ajax(异步的JavaScript和xml)技术,可以使用封装好的dwr框架简化开发,另一种方式就是使用Flex技术,就是Flash脚本编程,只是听说,自己还没有用过。

自己写了一个使用ajax框架dwr实现简易的即时通信程序。

首先什么是dwr呢?DWR是一个框架,简单的说就是能够在javascript直接调用java方法,而不必去写一大堆的javascript代码。它的实现是基于ajax的,可以实现无刷新效果。

一、 dwr配置篇

1.web.xml

<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>

这个参数DWR默认是false。如果选择true,我们可以通过http://localhost:port/app/dwr看到你部署的每个DWR class。并且可以测试java代码的每个方法是否运行正常。为了安全考虑,在正式环境下你一定把这个参数设为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实现

1. 首先把dwr.jar包放在项目lib目录下。

2. 进行上述web.xml相关配置,上述配置就是本实例的配置。

3. 为实现功能写的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的记录数:" + sessions.size());

// 消除不存在的页面session

System.out.println("session的记录数(消除后):" + sessions.size());

Util util = new Util(sessions);

// 处理这些页面中的一些元素

util.removeAllOptions("users");

util.addOptions("users",users,"username");

util.removeAllOptions("receiver");

util.addOptions("receiver","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);

}

/**

*根据用户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;

}

/**

*发送消息

*

*@paramsender

* 发送者

*@paramreceiverid

* 接收者id

*@parammsg

* 消息内容

*@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中调用

自定义一个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;

/*调用后台ChatManager类的updateUsersList方法,并取得返回值元数据放在data*/

ChatManager.updateUsersList($('username').value,true, function(data) {

if (data != null && data.length > 0) {

$('userid').value = data; // 把当前sessionId放在隐藏表单

}

});

}

/**

*初始化

*/

function init() {

dwr.engine.setActiveReverseAjax(true); // 激活反转

ChatManager.updateUsersList(null,false); //和上面那个方法一样

}

function delUser(button) {

ChatManager.delUser(); //当退出是调用,消除该在线用户

/**

*并对相应按钮进行相应处理

*/

$('username').disabled = false;

$('register').disabled = false;

button.disabled=true;

$('receiver').disabled = true;

$('send').disabled = true;

$('areaMessage').innerHTML = "";

}

/**

* 当发送信息是调用

*/

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); //调用后台方法

}

/**

*这是后台推技术调用的方法,接受信息

*/

function receiveMessages(message) {

//取得聊天信息中文本

var messages=document.getElementById("areaMessage").innerHTML;

document.getElementById("areaMessage").innerHTML=message+"<hr/>"+messages;

}

window.onload = init;//页面加载时

6. HTML代码

需要导入必须的js文件,在文本编辑时,我用了一个fckEditor文本编辑器,上网下一个就可以了,放在根目录下,本人美感欠缺,页面不太好看,请见谅!具体代码如下:

<%@ 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="发送" 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>

好了,终于写完了,首先要说明一下,本程序不是很完善,具体在:用户只有点击“退出”按钮才可以实现把该在线人员删除掉,可能利用js也可以实现关闭页面也可以把该在线人员删除掉,但是如果用户刷新了,怎么办呢???就是怎么记录有效地scriptsession呢?有人说用map保存。本人没有试过,还望高手指点,不胜感激!!!

b/s模式下的即时通讯,使用ajax框架dwr实现的更多相关文章

  1. 基于JavaScript编写一个图片转PDF转换器

    本文为大家介绍了一个简单的 JavaScript 项目,可以将图片转换为 PDF 文件。你可以从本地选择任何一张图片,只需点击一下即可将其转换为 PDF 文件,感兴趣的可以动手尝试一下

  2. HTML5数字输入仅接受整数的实现代码

    这篇文章主要介绍了HTML5数字输入仅接受整数的实现代码,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

  3. amaze ui 的使用详细教程

    这篇文章主要介绍了amaze ui 的使用详细教程,本文通过多种方法给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

  4. HTML5 Web缓存和运用程序缓存(cookie,session)

    这篇文章主要介绍了HTML5 Web缓存和运用程序缓存(cookie,session),小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

  5. HTML5 WebSocket实现点对点聊天的示例代码

    这篇文章主要介绍了HTML5 WebSocket实现点对点聊天的示例代码的相关资料,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

  6. html5简介_动力节点Java学院整理

    这篇文章主要介绍了html5简介,用于指定构建网页的元素,这些元素中的大多数都用于描述网页内容,有兴趣的可以了解一下

  7. iOS Swift上弃用后Twitter.sharedInstance().session()?. userName的替代方案

    解决方法如果您仍在寻找解决方案,请参阅以下内容:

  8. 使用Fabric SDK iOS访问Twitter用户时间线

    我试图在这个问题上挣扎两天.我正在使用FabricSDK和Rest工具包,试图为Twitter使用不同的RestAPIWeb服务.我可以使用具有authTokenSecret,authToken和其他值的会话对象的TWTRLogInButton成功登录.当我尝试获取用户时间线时,我总是得到失败的响应,作为:{“errors”:[{“code”:215,“message”:“BadAuthentic

  9. ios – 如何从Apple Watch调用iPhone上定义的方法

    有没有办法从Watchkit扩展中调用iPhone上的类中定义的方法?根据我的理解,目前在Watchkit和iPhone之间进行本地通信的方法之一是使用NSUserDefaults,但还有其他方法吗?

  10. ios 8 Homescreen webapp,关闭和打开iPad停止javascript

    我有一个适用于iPad的全屏HTML5网络应用程序,并且刚刚安装了IOS8来试用它,它一切正常,直到你关闭并重新启动iPad.一旦web应用程序重新启动javascript就会停止并加载新页面不会重新启动它.在iPad上的Safari中打开同一页面时,关闭和打开iPad会继续按预期工作.其他人注意到了这个或想出了一个解决方案吗?解决方法这似乎是我在iOS8.1.1更新中解决的.

随机推荐

  1. xe-ajax-mock 前端虚拟服务

    最新版本见Github,点击查看历史版本基于XEAjax扩展的Mock虚拟服务插件;对于前后端分离的开发模式,ajax+mock使前端不再依赖后端接口开发效率更高。CDN使用script方式安装,XEAjaxMock会定义为全局变量生产环境请使用xe-ajax-mock.min.js,更小的压缩版本,可以带来更快的速度体验。

  2. vue 使用 xe-ajax

    安装完成后自动挂载在vue实例this.$ajaxCDN安装使用script方式安装,VXEAjax会定义为全局变量生产环境请使用vxe-ajax.min.js,更小的压缩版本,可以带来更快的速度体验。cdnjs获取最新版本点击浏览已发布的所有npm包源码unpkg获取最新版本点击浏览已发布的所有npm包源码AMD安装require.js安装示例ES6Module安装通过Vue.use()来全局安装示例./Home.vue

  3. AJAX POST数据中文乱码解决

    前端使用encodeURI进行编码后台java.net.URLDecoder进行解码编解码工具

  4. Koa2框架利用CORS完成跨域ajax请求

    实现跨域ajax请求的方式有很多,其中一个是利用CORS,而这个方法关键是在服务器端进行配置。本文仅对能够完成正常跨域ajax响应的,最基本的配置进行说明。这样OPTIONS请求就能够通过了。至此为止,相当于仅仅完成了预检,还没发送真正的请求呢。

  5. form提交时,ajax上传文件并更新到&lt;input&gt;中的value字段

  6. ajax的cache作用

    filePath="+escape;},error:{alert;}});解决方案:1.加cache:false2.url加随机数正常代码:网上高人解读:cache的作用就是第一次请求完毕之后,如果再次去请求,可以直接从缓存里面读取而不是再到服务器端读取。

  7. 浅谈ajax上传文件属性contentType = false

    默认值为contentType="application/x-www-form-urlencoded".在默认情况下,内容编码类型满足大多数情况。在这里,我们主要谈谈contentType=false.在使用ajax上传文件时:在其中先封装了一个formData对象,然后使用post方法将文件传给服务器。说到这,我们发现在JQueryajax()方法中我们使contentType=false,这不是冲突了吗?这就是因为当我们在form标签中设置了enctype=“multipart/form-data”,

  8. 909422229_ajaxFileUpload上传文件

    ajaxFileUpload.js很多同名的,因为做出来一个很容易。我上github搜AjaxFileUpload出来很多类似js。ajaxFileUpload是一个异步上传文件的jQuery插件传一个不知道什么版本的上来,以后不用到处找了。语法:$.ajaxFileUploadoptions参数说明:1、url上传处理程序地址。2,fileElementId需要上传的文件域的ID,即的ID。3,secureuri是否启用安全提交,默认为false。4,dataType服务器返回的数据类型。6,error

  9. AJAX-Cache:一款好用的Ajax缓存插件

    原文链接AJAX-Cache是什么Ajax是前端开发必不可少的数据获取手段,在频繁的异步请求业务中,我们往往需要利用“缓存”提升界面响应速度,减少网络资源占用。AJAX-Cache是一款jQuery缓存插件,可以为$.ajax()方法扩展缓存功能。

  10. jsf – Ajax update/render在已渲染属性的组件上不起作用

    我试图ajax更新一个有条件渲染的组件。我可以确保#{user}实际上是可用的。这是怎么引起的,我该如何解决呢?必须始终在ajax可以重新呈现之前呈现组件。Ajax正在使用JavaScriptdocument.getElementById()来查找需要更新的组件。但是如果JSF没有将组件放在第一位,那么JavaScript找不到要更新的内容。解决方案是简单地引用总是渲染的父组件。

返回
顶部