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)技术来开发事件驱 ...
随机推荐
- 【sqli-labs】 less54 GET -Challenge -Union -10 queries allowed -Variation1 (GET型 挑战 联合查询 只允许10次查询 变化1)
尝试的次数只有10次 http://192.168.136.128/sqli-labs-master/Less-54/index.php?id=1' 单引号报错,错误信息没有显示 加注释符页面恢复正常 ...
- Docker是什么?可以用Docker做什么?
作者:刘允鹏 链接:https://www.zhihu.com/question/28300645/answer/67707287 来源:知乎 著作权归作者所有.商业转载请联系作者获得授权,非商业转载 ...
- 关于JS闭包的一点理解
通常来讲,闭包通常是指函数内部可以访问到外部作用域的一个过程. 一.广义的定义:任何函数都产生了闭包. 二.狭义的定义:函数内部能访问到其他变量函数的作用域. 我们来看个例子 var a = 10; ...
- 【剑指Offer】66、机器人的运动范围
题目描述: 地上有一个m行和n列的方格.一个机器人从坐标0,0的格子开始移动,每一次只能向左,右,上,下四个方向移动一格,但是不能进入行坐标和列坐标的数位之和大于k的格子. 例如,当k为18时 ...
- shell使用eval进行赋值bc计算,bad substitution
开始我认为是这样的: [root@jiangyi02.sqa.zmf /home/ahao.mah/ALIOS_TEST] #cat bbb.sh #!/bin/sh eval $1_new=123 ...
- 02. 爬取get请求的页面数据
目录 02. 爬取get请求的页面数据 一.urllib库 二.由易到难的爬虫程序: 02. 爬取get请求的页面数据 一.urllib库 urllib是Python自带的一个用于爬虫的库,其主要作用 ...
- 7.2.1 代码测试 doctest
Python标准库 doctest 可以搜索程序中类似于交互式Python代码的文本片段,并运行这些交互式代码来验证是否符合预期结果和功能,常用于Python程序的模块测试. 使用doctest模块测 ...
- Maven学习总结(9)——使用Nexus搭建Maven私服
1 . 私服简介 私服是架设在局域网的一种特殊的远程仓库,目的是代理远程仓库及部署第三方构件.有了私服之后,当 Maven 需要下载构件时,直接请求私服,私服上存在则下载到本地仓库:否则,私服请求外部 ...
- [React Storybook] Get started with Storybook for React
Storybook is a UI component development environment for React, Vue, and Angular. With that, you can ...
- poj 1256 Anagram—next_permutation的神奇应用
题意:给你一条字符串,让你输出字符串中字符的全排列,输出的顺序要按它给的奇葩的字典序. 题解:要输出全排列,暴力dfs可以过,但要注意题目的字典序以及相同字符的情况.如果用next_permutati ...