Comet反向ajax技术实现客服聊天系统
说明:Comet反向Ajax是在看了燕十八老师的视频以后,结合他讲解的例子,自己用ajax+java实现了一遍。在这里把代码贴出来,以供大家学习。同时,ajax轮询技术也可以用在消息推送的功能中,下次有时间,可以把相关的代码和设计思路贴出来,一起学习学习!
客户端代码:
<!DOCTYPE html>
<html>
<head>
<title>客户端</title> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="this is my page">
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<style>
*{margin:0; padding:0;}
h1{padding-left:300px;}
#msg{margin:20px;width:800px;height:400px;background:#ccc;border:2px solid #000;padding-left:10px;font-family: "微软雅黑";
font-size: 14px;padding:20px;overflow:auto;}
#msg p{line-height:20px;}
.say p:nth-of-type(2){text-indent: 20px;}
.reply{text-align:right;color:blue;}
#operate{margin:20px;font-family: "微软雅黑";font-size:14px;}
#operate #content{width:600px;height:30px;padding-left:10px;}
#operate input:nth-of-type(2){width:80px;height:30px;font-family: "微软雅黑";}
</style>
</head> <body>
<h1>客户端发送信息</h1>
<div id="msg">
</div>
<div id="operate">
<input type="text" id="content" placeholder="请输入发送内容"/>
<input type="button" value="点击发送" onclick="sendHandler();">
</div>
</body>
</html>
<script type="text/javascript">
var xhr = new XMLHttpRequest();
window.onload = function(){
function autoSend(){
xhr.open("POST", "getClientMsg.do",true);
xhr.onreadystatechange = function(){
if(xhr.readyState == 4 && xhr.status == 200){
if(xhr.responseText != "reload")setValue(xhr.responseText);
window.setTimeout(function(){
autoSend();
}, 500);
}
};
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
xhr.send(null);
}
autoSend();
} function setValue(result){
console.log("result",result);
var strs = result.split("&");
var date = new Date();
date = date.toLocaleDateString();
document.getElementById("msg").innerHTML += "<div class='say'><p>客服中心 "+date+"</p><p>"+strs[1]+"</p></div>";
}
//发送数据
function sendHandler(){
var oContent = document.getElementById("content");
if(null != oContent.value){
var xhr = new XMLHttpRequest();
xhr.open("POST", "sendMsg.do",true);
xhr.onreadystatechange = function(){
if(xhr.readyState == 4 && xhr.status == 200){
if(xhr.responseText == "success"){
var date = new Date();
date = date.toLocaleDateString();
document.getElementById("msg").innerHTML += "<div class='reply'><p>我 "+date+"</p>"+
"<p>"+oContent.value+"</p></div>";
document.getElementById("content").value = "";
}
}
}
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
xhr.send("sendIdentity=client&content="+oContent.value); }
} </script>
客户端获取消息代码:
package com.sgepit.ajax; import java.io.IOException;
import java.sql.Connection; import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler; import com.sgepit.ajax.entity.Msg;
import com.sgepit.ajax.util.DBCon; /**
* @author tengri
* @since 2015-12-12 下午9:59:45
* @description: 客户端获取消息
*/
@SuppressWarnings("all")
@WebServlet("/getClientMsg.do")
public class GetClientMsg extends HttpServlet { @Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)throws ServletException, IOException {
try {
Connection conn = DBCon.getConnection();
QueryRunner qr = new QueryRunner();
String clientIP = req.getRemoteAddr();
String sql = "select * from msg where rec =? and isread = 0 limit 1";
Object[] param = {clientIP};
Msg msg = null;
resp.setCharacterEncoding("utf-8");
long startTime = System.currentTimeMillis();
while(true){
msg = qr.query(DBCon.getConnection(), sql, new BeanHandler(Msg.class), param);
if(null != msg ){
String result = msg.getPos() + "&" + msg.getContent();
System.out.println("clientMsg:" + result);
resp.getWriter().write(result);
sql = "update msg set isread=1 where uuid=?";
Object[] param2 = {msg.getUuid()};
qr.update(conn, sql, param2);
break;
}
if(System.currentTimeMillis() - startTime >=5000){
resp.getWriter().write("reload");
break;
}
Thread.sleep(500);
}
} catch (Exception e) {
resp.getWriter().write("error");
}
}
}
客服端:
<!DOCTYPE html>
<html>
<head>
<title>客服端</title>
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="this is my page">
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<style>
*{margin:0; padding:0;}
h1{padding-left:300px;}
#msg{margin:20px;width:800px;height:400px;background:#ccc;border:2px solid #000;padding-left:10px;font-family: "微软雅黑";
font-size: 14px;padding:20px;overflow:auto;}
#msg p{line-height:20px;}
.say p:nth-of-type(1){cursor: pointer;}
.say p:nth-of-type(2){text-indent: 20px;}
.reply{text-align:right;color:blue;}
#operate{margin:20px;font-family: "微软雅黑";font-size:14px;}
#operate #content{width:600px;height:30px;padding-left:10px;}
#operate input:nth-of-type(2){width:80px;height:30px;font-family: "微软雅黑";}
</style>
</head> <body>
<h1>服务端回复信息</h1>
<div id="msg">
</div>
<div id="operate">
<p>回复人:<span id="person"></span></p><br/>
<input type="text" id="content" placeholder="请输入回复内容"/>
<input type="button" value="点击回复" onclick="replyHandler();">
</div>
</body>
</html>
<script type="text/javascript">
var xhr = new XMLHttpRequest();
window.onload = function(){
document.getElementById("msg").onclick = function(ev){
var event = ev || window.event;
if(event.target.nodeName.toLowerCase() == "span"){
document.getElementById("person").innerHTML = event.target.innerText;
}
} function autoSend(){
xhr.open("POST", "getServerMsg.do",true);
xhr.onreadystatechange = function(){
if(xhr.readyState == 4 && xhr.status == 200){
if(xhr.responseText != "reload")setValue(xhr.responseText);
window.setTimeout(function(){
autoSend();
}, 500);
}
};
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
xhr.send(null);
}
autoSend();
}
function setValue(result){
var strs = result.split("&");
var date = new Date();
date = date.toLocaleDateString();
document.getElementById("msg").innerHTML += "<div class='say'><p class='clientIp'>"+
"<span>"+strs[0]+"</span> "+date+"</p><p>"+strs[1]+"</p></div>";
}
//发送回复内容
function replyHandler(){
var value = document.getElementById("content").value;
var rec = document.getElementById("person").innerText;
if(!rec){
alert("请选择回复人");
return;
}
if(null != value){
var xhr = new XMLHttpRequest();
xhr.open("POST", "sendMsg.do",true);
xhr.onreadystatechange = function(){
if(xhr.readyState == 4 && xhr.status == 200){
if(xhr.responseText == "success"){
var date = new Date();
date = date.toLocaleDateString();
document.getElementById("msg").innerHTML += "<div class='reply'><p>我 "+date+"</p><p>"+value+"</p></div>";
document.getElementById("content").value = "";
}
}
}
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
xhr.send("sendIdentity=admin&content="+value+"&rec="+rec);
}
}
</script>
服务端获取消息代码:
package com.sgepit.ajax; import java.io.IOException;
import java.sql.Connection; import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler; import com.sgepit.ajax.entity.Msg;
import com.sgepit.ajax.util.DBCon; /**
* @author tengri
* @since 2015-12-12 下午9:59:45
* @description: 服务端获取消息
*/
@SuppressWarnings("all")
@WebServlet("/getServerMsg.do")
public class GetServerMsg extends HttpServlet { @Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)throws ServletException, IOException {
try {
Connection conn = DBCon.getConnection();
QueryRunner qr = new QueryRunner();
String clientIP = req.getRemoteAddr();
String sql = "select * from msg where rec =? and isread = 0 limit 1";
Object[] param = {"admin"};
Msg msg = null;
resp.setCharacterEncoding("utf-8"); //处理中文乱码
long startTime = System.currentTimeMillis();
while(true){
msg = qr.query(DBCon.getConnection(), sql, new BeanHandler(Msg.class), param);
if(null != msg ){
String result = msg.getPos() + "&" + msg.getContent();
System.out.println("servler:" +result);
resp.getWriter().write(result);
sql = "update msg set isread=1 where uuid=?";
Object[] param2 = {msg.getUuid()};
qr.update(conn, sql, param2);
break;
}
if(System.currentTimeMillis() - startTime >=5000){
resp.getWriter().write("reload");
break;
}
Thread.sleep(500);
}
} catch (Exception e) {
e.printStackTrace();
resp.getWriter().write("error");
}
}
}
发送消息代码:客户端和客服端发送消息都是调用同一个接口,只是在后台做了相关判断。
package com.sgepit.ajax; import java.io.IOException; import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler; import com.sgepit.ajax.entity.Msg;
import com.sgepit.ajax.util.DBCon; /**
* @author tengri
* @since 2015-12-12 下午9:59:24
* @description: 发送消息
*/
@SuppressWarnings("all")
@WebServlet("/sendMsg.do")
public class SendMsg extends HttpServlet { @Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)throws ServletException, IOException {
req.setCharacterEncoding("utf-8");
String sendIdentity = req.getParameter("sendIdentity");
String content = req.getParameter("content");
String rec = "admin";
String pos = "admin";
try {
//如果是服务端发送消息,则会传过来接收者对象,如果是客户端发送消息,接收者为admin,发送端为当前ip用户
if("admin".equals(sendIdentity)){
rec = req.getParameter("rec");
}else{
pos = req.getRemoteAddr();
}
QueryRunner qr = new QueryRunner();
String sql = "insert into msg(rec,pos,content,isread)values(?,?,?,0)";
Object[] params = {rec,pos,content};
qr.insert(DBCon.getConnection(),sql, new BeanHandler(Msg.class), params);
resp.getWriter().write("success");
} catch (Exception e) {
resp.getWriter().write("error");
e.printStackTrace();
}
}
}
截图:


Comet反向ajax技术实现客服聊天系统的更多相关文章
- 用 WebSocket 实现一个简单的客服聊天系统
一 需求 一个多商家的电商系统,比如京东商城,不同商家之间的客服是不同的,所面对的用户也是不同的.要实现一个这样的客服聊天系统,那该系统就必须是一个支持多客服.客服一对多用户的聊天系统. 二 思路 使 ...
- Comet——随着AJAX技术兴起而产生的新技术
不得不说Ajax确实是一个好东西,由它的出现使得WEB端新技术不断产生,Comet就属于这么一个技术,这个技术有时叫做反向AJAX,有时叫做服务器"推"技术,嗯,不要被牛逼闪闪的名 ...
- 08 comet反向ajax
一:HTTP协议与技久链接+分块传输---->反向ajax 反向ajax又叫comet, server push,服务器推技术. 应用范围: 网页聊天服务器,, 新浪微博在线聊天,google ...
- Comet——反向Ajax (基础知识)
Comet:服务器推送,与ajax页面向服务器请求数据相反.几乎可以实时将数据推送到客户端. 但本质一样:浏览器向服务器发起请求,服务器响应请求 Comet实现方式:长轮询.HTTP流 1.长轮询—— ...
- php开发客服系统(持久连接+轮询+反向ajax)
欢迎在php严程序 - php教程学习AJAX教程, 本节课讲解:php开发客服系统(持久连接+轮询+反向ajax) php开发客服系统(下载源码) 用户端(可直接给客户发送消息)客服端(点击用户名. ...
- php开发客服系统(持久连接+轮询+反向ajax 转载 http://www.tuicool.com/articles/2mU7v2R)
php开发客服系统( 下载源码 ) 用户端(可直接给客户发送消息) 客服端(点击用户名.即可给该用户回复消息) 讲两种实现方式: 一:iframe + 服务器推技术comet(反向ajax,即服务器向 ...
- HTTP 笔记与总结(9)分块传输、持久链接 与 反向 ajax(comet / server push / 服务器推技术)
反向 ajax 又叫 comet / server push / 服务器推技术 应用范围:网页聊天服务器,例如新浪微博在线聊天.google mail 网页聊天 原理:一般而言,HTTP 协议的特点是 ...
- 反向Ajax,第2部分:WebSocket
转自:http://kb.cnblogs.com/page/112616/ 前言 时至今日,用户期待的是可通过web访问快速.动态的应用.这一文章系列展示了如何使用反向Ajax(Reverse Aja ...
- 反向ajax实现
在过去的几年中,web开发已经发生了很大的变化.现如今,我们期望的是能够通过web快速.动态地访问应用.在这一新的文章系列中,我们学习如何使用反 向Ajax(Reverse Ajax)技术来开发事件驱 ...
随机推荐
- jstree CHECKBOX PLUGIN
The checkbox plugin makes multiselection possible using three-state checkboxes. Configuration overri ...
- STM32的USART发送数据时如何使用TXE和TC标志
在USART的发送端有2个寄存器,一个是程序可以看到的USART_DR寄存器,另一个是程序看不到的移位寄存器,对应USART数据发送有两个标志,一个是TXE=发送数据寄存器空,另一个是TC=发送结束. ...
- PAT 1047. Student List for Course
Zhejiang University has 40000 students and provides 2500 courses. Now given the registered course li ...
- 3 Java的基本程序设计结构
本章主要内容: 一个简单的Java应用程序 注释 数据类型 变量 运算符 字符串 输入输出 控制流 大数值 数组 本章主要介绍程序设计的基本概念(如数据类型.分支以及循环)在Jav ...
- 优雅的退出/关闭/重启gunicorn进程
在工作中,会发现gunicorn启动的web服务,无论怎么使用kill -9 进程号都是无法杀死gunicorn,经过我一番百度和谷歌,发现想要删除gunicorn进程其实很简单. 第一步获取Guni ...
- ganglia3.7.2,web3.7.1安装
1.准备安装包 ganglia-3.7.2-2.el6.x86_64.rpm ganglia-gmetad-3.7.2-2.el6.x86_64.rpm ganglia-gmond-3.7.2-2.e ...
- [bzoj3224]普通平衡树[Treap]
Treap 的各种操作,模板题,要再写几遍 #include <iostream> #include <algorithm> #include <cstdio> # ...
- 一个最简单的SPRINGMVC示例
持久层,服务层,表现层都涉及到了. 这个分得确实比DJANGO细致, 多体会,多注解..:) The domain layer package com.packt.webstore.domain; i ...
- C/C++中的64位整数
C/C++中的64位整数(__int64 and long long) 在做ACM题时,经常都会遇到一些比较大的整数.而常用的内置整数类型常常显得太小了:其中long 和 int 范围是[-2^31, ...
- N天学习一个Linux命令之hostnamectl
前言 安装了CentOS7,发现按照以前修改文件/etc/sysconfig/network HOSTNAME字段主机名的方式不生效了,查资料发现可以使用hostnamectl命令 用途 Contro ...