使用DWR长连接技术实现客户端一对一发送消息

关于DWR怎么使用我的上一篇博文里面记录了,这里写一个DWR一对一消息推送的WEB程序,也就是WEB一对一聊天。我的思路是这样的:首先每个用户在登陆后在各自的页面放置一个唯一标记(如用户的ID,也可以放在session里面),用户A向用户B发送的消息 --》服务器 --》JAVA方法--》JAVA方法调用前端所有正在访问聊天页面的JS函数--》JS判断消息发送至的客户端是否是用户B --》是则显示,否则不显示;用户B向A同样过程

首先是该项目的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"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
    id="WebApp_ID" version="3.0">
    <display-name>DWRDemo</display-name>

    <!-- 加入DWRServlet -->
    <servlet>
        <servlet-name>dwr-invoker</servlet-name>

        <servlet-class>org.directwebremoting.servlet.DwrServlet</servlet-class>
        <init-param>
            <param-name>debug</param-name>
            <param-value>true</param-value>
        </init-param>
        
        <!-- 使用comet方式 -->
        <init-param>
            <param-name>activeReverseAjaxEnabled</param-name>
            <param-value>true</param-value>
        </init-param>
    </servlet>

    <servlet-mapping>
        <servlet-name>dwr-invoker</servlet-name>
        <url-pattern>/dwr/*</url-pattern>
    </servlet-mapping>

    <welcome-file-list>
        <welcome-file>index.html</welcome-file>
        <welcome-file>index.htm</welcome-file>
        <welcome-file>index.jsp</welcome-file>
        <welcome-file>default.html</welcome-file>
        <welcome-file>default.htm</welcome-file>
        <welcome-file>default.jsp</welcome-file>
    </welcome-file-list>

</web-app>

然后是index.jsp,这是主页面:

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%
    String path = request.getContextPath();
    String basePath = request.getScheme() + "://"
            + request.getServerName() + ":" + request.getServerPort()
            + path + "/";
%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">

<title>DWR Demo</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
<!--
    <link rel="stylesheet" type="text/css" href="styles.css">
    -->
<!-- <script src="http://libs.baidu.com/jquery/2.0.0/jquery.js"></script> -->
<script type=‘text/javascript‘ src=‘<%=basePath%>dwr/engine.js‘></script>
<script type=‘text/javascript‘ src=‘<%=basePath%>dwr/util.js‘></script>
<script type=‘text/javascript‘ src=‘<%=basePath%>dwr/interface/Hello.js‘></script>
<script type=‘text/javascript‘
    src=‘<%=basePath%>dwr/interface/LoginService.js‘></script>
<script type=‘text/javascript‘
    src=‘<%=basePath%>dwr/interface/MessageService.js‘></script>
<script type="text/javascript">
    
    dwr.engine.setActiveReverseAjax(true);//使用长链接的方式

    /**
     * 模拟用户登陆
     */
    function login() {

        var inputName = dwr.util.getValue("userName");

        //alert(inputName);

        if (inputName.length == 0) {
            alert("please enter your user name");
        } else {

            LoginService.login(inputName, function(data) {

                dwr.util.setValue("loginName", data);
            });
        }
    }

    /**
     * 本用户发送信息到服务端JAVA类
     */
    function sendMessage() {

        var inputMessageText = dwr.util.getValue("messageText");

        var userName = dwr.util.getValue("loginName");
        var toName = dwr.util.getValue("toName");

        if (userName.length == 0) {

            alert("please login");
        } else if (toName.length == 0) {

            alert("please enter the name you send to");
        } else if (inputMessageText.length == 0) {

            alert("please enter the message you want to send");
        } else {

            var mydate = new Date();
            var currentDate = mydate.toLocaleTimeString();
            
            /**
            * 发送消息至服务其,toName是发送到哪个用户的用户标识
            */
            MessageService.sendMessage(currentDate + " " + " " + userName
                    + " : " + inputMessageText, toName);

            sendMessageToChatArea();//本用户发送的消息更新对话域
        }

    }

    /**
     * 本用户发送完成,对方信息域显示更新
     * @param message
     * @param toName
     * @returns
     */
    function newMessage(message, toName) {

        var thisUserName = dwr.util.getValue("loginName");

        if (toName == thisUserName) {

            var chatArea = document.getElementById("chatArea");

            var oldMessage = chatArea.innerHTML;

            if (oldMessage.length == 0) {

                chatArea.innerHTML = message;
            } else {

                chatArea.innerHTML = oldMessage + "<br/>" + message;

                //始终显示最新发送的消息
                var chatAreaHeight = chatArea.scrollHeight;
                chatArea.scrollTop = chatAreaHeight;
            }
        }

    }

    /**
     * 本用户发送信息显示在信息域
     * @returns
     */
    function sendMessageToChatArea() {

        var inputMessageText = dwr.util.getValue("messageText");

        var chatArea = document.getElementById("chatArea");

        var oldMessage = chatArea.innerHTML;

        var mydate = new Date();
        var currentDate = mydate.toLocaleTimeString();
        var loginName = dwr.util.getValue("loginName");

        chatArea.innerHTML = oldMessage + "<br/>" + currentDate + " "
                + loginName + " : " + inputMessageText;

        //始终显示最新发送的消息
        var chatAreaHeight = chatArea.scrollHeight;
        chatArea.scrollTop = chatAreaHeight;
    }
</script>
</head>

<body>
    <h1>Simple Test</h1>
    <p>
        Name: <input type="text" id="demoName" /> <input value="Send"
            type="button" onclick="update()" /> <br /> Reply: <span
            id="demoReply"></span>
    </p>
    <hr />
    <h1>DWR ANDJAVA Chat Test</h1>
    <span id="loginName"></span>
    <br /> Your Name
    <input type="text" size="30" id="userName">
    <input type="button" value="login" onclick="login()" />
    <br /> Send To Who
    <input type="text" size="30" id="toName" />
    <br />
    <div id="chatArea" style="width: 600px; height: 300px; overflow: auto"></div>
    <br />
    <p>
        <input type="text" size="40" id="messageText" /> | <input
            type="button" value="Send" onclick="sendMessage()">
    </p>
</body>
</html>

dwr.xml文件:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE dwr PUBLIC
    "-//GetAhead Limited//DTD Direct Web Remoting 3.0//EN"
    "http://getahead.org/dwr/dwr30.dtd">

<dwr>
    <allow>
    
        <create creator="new" javascript="MessageService">
            <param name="class" value="com.dwrdemo.pojo.MessageService"></param>
        </create>
        
        <create creator="new" javascript="LoginService">
            <param name="class" value="com.dwrdemo.pojo.LoginService"></param>
        </create>
        
    </allow>
</dwr>

JAVA代码:

LoginService:

package com.dwrdemo.pojo;

/**
 * ,模拟用户登陆
 * @author lin
 *
 */
public class LoginService {
    
    /**
     * 用户登陆
     * @param userName 用户名
     * @return
     */
    public String login(String userName)
    {
        return userName;
    }
    
}

MessageService:

package com.dwrdemo.pojo;

import java.util.Collection;

import javax.servlet.ServletContext;

import org.directwebremoting.ScriptSession;
import org.directwebremoting.ServerContext;
import org.directwebremoting.ServerContextFactory;
import org.directwebremoting.WebContext;
import org.directwebremoting.WebContextFactory;
import org.directwebremoting.proxy.ScriptProxy;

public class MessageService {

    public String sendMessage(String messageText,String toName) {
        
        //Message message = createMessage(messageText, toName);
        
        System.out.println(messageText+"\t\t\t"+toName);
        
        postNewMessage(messageText, toName);
        
        return null;

    }

    /**
     * 获得前端脚本代理
     * @return
     */
    public ScriptProxy getScriptProxy() {
        
        WebContext webContext = WebContextFactory.get();
        
        ServletContext servletContext = webContext.getServletContext();
        
        ServerContext serverContext = ServerContextFactory.get(servletContext);
        
        webContext.getScriptSessionsByPage("");
        
        /**
         * 项目根路径
         */
        String contextPath = servletContext.getContextPath();
        
        if (contextPath != null) {
            
            /**
             * 获得当前访问该页面的全部脚本会话
             */
            Collection<ScriptSession> sessions = serverContext.getScriptSessionsByPage(contextPath+"/index.jsp");
        
            ScriptProxy proxy = new ScriptProxy(sessions);
            
            return proxy;
        }
        return null;
    }
    
    /**
     * 调用前端javascript函数
     * @param newMessage
     */
     public void postNewMessage(String message,String toName) {
         
          ScriptProxy proxy = getScriptProxy();
          
          if (proxy != null) {
              
              /**
               * 调用的前端函数名,和函数的参数
               */
              System.out.println("NEW MESSAGE:"+message+"\t\t\t"+toName);
             proxy.addFunctionCall("newMessage",message,toName);
          }
       }

}

项目目录结构:

运行结果:

我的这种一对一消息推送办法可能不是很好,如果有人有更好的解决方案,麻烦告诉我一下,谢谢!

时间: 2025-01-02 16:02:52

使用DWR长连接技术实现客户端一对一发送消息的相关文章

长连接技术(Long Polling)

在服务器端hold住一个连接, 不立即返回, 直到有数据才返回, 这就是长连接技术的原理 长连接技术的关键在于hold住一个HTTP请求, 直到有新数据时才响应请求, 然后客户端再次自动发起长连接请求. 那怎么样hold住一个请求呢?服务器端的代码可能看起来像这样的 <?php set_time_limit(0); //这句很重要, 不至于运行超时 while (true) { if (hasNewMessage()) { echo json_encode(getNewMessage()); b

PHP使用memcache长连接作为RPC客户端需要注意的地方

memcache扩展版本 3.0.8 一. retry_interval $retry_interval 某个rpc服务器端失败后故障转移的时间,retry_interval的时间内,该节点会被一直标记为不可用,隔离掉,为小于0的数一直隔离. int mmc_server_valid(mmc_t *mmc TSRMLS_DC) /* checks if a server should be considered valid to serve requests {{{ */ { if (mmc !

转:基于ASP.NET的Comet长连接技术解析

原文来自于: Comet技术原理 来自维基百科:Comet是一种用于web的技术,能使服务器能实时地将更新的信息传送到客户端,而无须客户端发出请求,目前有两种实现方式,长轮询和iframe流. 简单的说是一种基于现有Http协议基础上的长轮询技术,之所有会产生这种技术的主要原因是Http协议是无状态的所以客户端和服务端之间没办法建立起一套长时间的连接.比如我们要做一个聊天室,在Web环境下我们通常不能从服务端推送消息到浏览器里,而只能通过每个客户端不断的轮询服务器,以获取最新的消息,这样一来效率

java Socket 长连接 心跳包 客户端 信息收发 demo

今天写了个socket的测试小程序,代码如下 import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.Socket; import java.net.UnknownHostException; /** * @author 某家: * @version 创建时间:2015年8月17日 下午3:04:14 * 类说明 */ public class Con

我写的websocket推送例子,每隔5秒服务器向客户端浏览器发送消息(node.js和浏览器)

node.js服务端 先要安装ws模块的支持 npm install ws 服务端(server.js) var gws; var WebSocketServer = require('ws').Server, wss = new WebSocketServer({ port: 9000 }); wss.on('connection', function (ws) { gws = ws; console.log('client connected'); ws.on('message', func

nginx之旅(第六篇):nginx优化--nginx优化目的、工作进程优化、长连接设置、数据压缩、客户端缓存

一.Nginx优化目的 标准情况下,软件默认的参数都是对安装软件的硬件标准来设置的,目前我们服务?的硬件资源远远大于要求的标准,所以为了让服务?性能更加出众,充分利用服务?的硬件资源,我们一般需要优化APP的并发数来提升服务器?的性能. 二.工作进程优化 1) worker_processes worker_processes指Nginx的工作进程,这个值是直接受到服务器CPU核数量影响的(当然也有其他影响),Nginx默认配置为auto,意思是会自动检测CPU核做修改,建议worker_pro

Web 通信 之 长连接、长轮询(long polling)(转载)

基于HTTP的长连接,是一种通过长轮询方式实现"服务器推"的技术,它弥补了HTTP简单的请求应答模式的不足,极大地增强了程序的实时性和交互性. 一.什么是长连接.长轮询? 用通俗易懂的话来说,就是客户端不停的向服务器发送请求以获取最新的数据信息.这里的“不停”其实是有停止的,只是我们人眼无法分辨是否停止,它只是一种快速的停下然后又立即开始连接而已. 二.长连接.长轮询的应用场景 长连接.长轮询一般应用与WebIM.ChatRoom和一些需要及时交互的网站应用中.其真实案例有:WebQQ

Web 通信 之 长连接、长轮询(long polling)

基于HTTP的长连接,是一种通过长轮询方式实现"服务器推"的技术,它弥补了HTTP简单的请求应答模式的不足,极大地增强了程序的实时性和交互性. 一.什么是长连接.长轮询? 用通俗易懂的话来说,就是客户端不停的向服务器发送请求以获取最新的数据信息.这里的“不停”其实是有停止的,只是我们人眼无法分辨是否停止,它只是一种快速的停下然后又立即开始连接而已. 二.长连接.长轮询的应用场景 长连接.长轮询一般应用与WebIM.ChatRoom和一些需要及时交互的网站应用中.其真实案例有:WebQQ

Web 通信 之 长连接、长轮询(转)

Web 通信 之 长连接.长轮询(long polling) 基于HTTP的长连接,是一种通过长轮询方式实现"服务器推"的技术,它弥补了HTTP简单的请求应答模式的不足,极大地增强了程序的实时性和交互性. 一.什么是长连接.长轮询? 用通俗易懂的话来说,就是客户端不停的向服务器发送请求以获取最新的数据信息.这里的"不停"其实是有停止的,只是我们人眼无法分辨是否停止,它只是一种快速的停下然后又立即开始连接而已. 二.长连接.长轮询的应用场景 长连接.长轮询一般应用与W