转载Ajax+js实时聊天文

来源:互联网 发布:linux防cc攻击 编辑:程序博客网 时间:2024/06/08 20:25

AJAX+js实现实时聊天

原创 2015年09月02日 11:21:56


了解AJAX基本流程之后,根据我们实际需要可以完成很多功能,这里我通过AJAX+javascript完成了一个简单的基于网页的实时聊天工具,代码不是很多,但是对过程的理解是最重要的,每行我都有注释,下面是代码:
首先是一个jsp网页,(html也可以)

   1   2   3   4   5   6   7   8   9  10  11  12  13  14  15  16  17  18  19  20  21  22  23  24  25  26  27  28  29  30  31  32  33  34  35  36  37  38  39  40  41  42  43  44  45  46  47  48  49  50  51  52  53  54  55  56  57  58  59  60  61  62  63  64  65  66  67  68  69  70  71  72  73  74  75  76  77  78  79  80  81  82  83  84  85  86  87  88  89  90  91  92  93  94  95  96  97  98  99 100 101 102 103 104
<%@ 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>聊天案例</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">

<!-- js部分,本应在一个js文件里,这里为了演示方便,放在一起 -->
<script type="text/javascript">

/* ajax生成后台访问的http对象 */
function getXmlHttpObject() {
var xmlHttp = null;
try {
// Firefox, Opera 8.0+, Safari
xmlHttp = new XMLHttpRequest();
} catch (e) {
// Internet Explorer
try {
xmlHttp = new ActiveXObject("Msxml2.XMLHTTP");
} catch (e) {
xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
}
}
return xmlHttp;
}
/* ajax执行方法,访问servlet, */
function getServerInfo() {
http = getXmlHttpObject();
var url = "getmsg?time=" + Math.random();
http.onreadystatechange = getInfoBack;
http.open("GET", url, true);
http.send(null);
}
/* 消息返回执行方法, */
function getInfoBack() {
if (http.readyState == 4) {
if (http.status == 200) {
//获取返回的消息字符串
var response = http.responseText;
//通过id找到聊天显示框把消息显示出来
document.getElementById("chatbox").innerHTML += response
+ "\r\n";
//再次执行getServerInfo方法访问servlet
getServerInfo();
}
}
}
/* 点击发送按钮执行,提交表单,把输入框清空,消息显示框显示到最底部
@param o输入框的id */
function sendok(o) {
//提交表单(直接使用form表单的名字)
myform.submit();
//通过传来的输入框的id参数o把输入框的内容清空
document.getElementById(o).value = "";
//用txt保存聊天显示框的对象
var txt = document.getElementById("chatbox");
//设置显示框显示在最底部
txt.scrollTop = txt.scrollHeight;
}
</script>
</head>

<!-- 加载时就执行getServerInfo方法,监听是否有数据输入 -->
<body onload="getServerInfo()">
聊天内容:
<br>
<!-- textarae显示聊天内容,设置id方便访问该标签,设置disabled让文本框不可以输入数据,设置style背景色为白色(这些在css里设置,这里为了演示方便) -->
<textarea id="chatbox" rows="10" cols="50" disabled="disabled"
style="background-color: white;"></textarea>
<br>
<!-- 用表单来提交数据,设置name方便访问,action为servlet地址,target为跳转下面设置的页面“sform”,相当于不跳转 -->
<form name="myform" method="post" action="sendmsg" target="sform">
<!-- 输入框完成消息输入 -->
<input id="msginput" type="text" name="chatmsg" />
<!-- 发送按钮,点击执行sendok()方法 -->
<input type="button" value="发送" onclick="sendok('msginput')" />
</form>
<!-- 设置一个空iframe,让表单提交后不跳转, -->
<iframe width="0" height="0" style="display: none" name="sform"></iframe>
</body>
</html>
 来自CODE的代码片
chatClient.jsp


然后需要一个消息对象(基于面向对象的原则)

  1  2  3  4  5  6  7  8  9 10 11 12 13 14
package chat.classinfo;
/* 封装消息对象的类,这里为了演示就只设置了message一个属性 ,提供相应的set、get方法*/
public class Message {
private String message;

public String getMessage() {
return message;
}

public void setMessage(String message) {
this.message = message;
}

}
 来自CODE的代码片
chatdemo_message.java


然后需要一个加载时监听消息的servlet

  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
package chat.servlet;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.Hashtable;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import chat.classinfo.Message;

/* 监听是否有消息输入,当页面加载时就会用AJAX访问该servlet, */
public class GetMsgServlet extends HttpServlet {
// 用一个Hashtable保存正在监听消息的客户端,键为每个客户端的session,值为消息对象
public static Hashtable<String, Message> waitList = new Hashtable<String, Message>();

public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doPost(request, response);
}

/* 消息监听,如果没有消息就会等待,当发送消息的servlet执行后会释放该同步锁 */
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 保存Message对象
Message msg = new Message();
// 把该对象与相应的session放到Hashtable中,
waitList.put(request.getSession(true).getId(), msg);
// 消息同步,消息刚刚创建是没有任何内容的,所以一定会先进入等待状态,等到消息值放进去之后再执行后面的操作
synchronized (msg) {
try {
// 同步等待
msg.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

// 当执行到这一步时,就说明消息同步已被唤醒,就说明msg里面已经把消息内容放进去了。
// 设置返回编码
response.setCharacterEncoding("utf-8");
// 用pw保存返回输出对象
PrintWriter pw = response.getWriter();
// 把消息内容通过输出对象输出
pw.print(msg.getMessage());

// 把输出对象清空关闭
pw.flush();
pw.close();
}

}
 来自CODE的代码片
chatdemo_getmsg.jsva


然后还需要一个发送时处理消息的servlet

  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
package chat.servlet;

import java.io.IOException;
import java.util.Iterator;
import java.util.Set;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import chat.classinfo.Message;

/* 当点击发送按钮提交表单执行该servlet,对消息进行处理 */
public class SendMsgSrevlet extends HttpServlet {

public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doPost(request, response);
}

/* 处理消息,把消息放进消息对象,把同步锁唤醒 */
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 设置传过来的数据编码
request.setCharacterEncoding("utf-8");
// 得到由输入的消息内容
String chatmsg = request.getParameter("chatmsg");
// 通过Set(Hashtable键)获取所有正在等待的session列表,方便使用迭代器
Set<String> sessions = GetMsgServlet.waitList.keySet();
// 使用迭代器Iterator方便遍历到所有的等待session
Iterator<String> sessionsIt = sessions.iterator();
// 遍历所有等待的session对象
while (sessionsIt.hasNext()) {
// 获取每一个等待的sessionid
String sessionId = sessionsIt.next();
// 通过sessionid获取该等待session的消息对象
Message msg = GetMsgServlet.waitList.get(sessionId);
// 在把输入框传过来的消息内容放进消息对象中时,可以用迭代器方便的把该等待session从等待列表中移除
sessionsIt.remove();
// 把消息内容放进消息对象,把同步消息唤醒
msg.setMessage(chatmsg);
// 同步唤醒所有正在等待的消息对象
synchronized (msg) {
msg.notifyAll();
}
}
}
}
 来自CODE的代码片
chatdemosendmsg.jsva

最后测试一下,打开多个聊天网页


总结一下整个聊天过程:
①进入聊天页加载时就会执行监听消息的servlet,在servlet中消息同步等待
②点击发送按钮时,通过表单把输入框的内容提交到处理消息的servlet
③处理消息时就会获取所有正在等待的session和对应的消息对象,把消息内容

写进去然后同步唤醒所有等待的消息对象
④消息被同步唤醒后,把消息内容通过AJAX返回到页面
⑤获取AJAX返回的消息后显示到聊天框,并再一次执行消息监听,访问servlet

时又会等待,以此循环执行②~⑤

版权声明:博主也花了很多的心思归纳整理才分享给大家,转载请注明出处。

原创粉丝点击