说明: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>客服中心&nbsp;"+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>我&nbsp;"+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>&nbsp;"+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>我&nbsp;"+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技术实现客服聊天系统的更多相关文章

  1. 用 WebSocket 实现一个简单的客服聊天系统

    一 需求 一个多商家的电商系统,比如京东商城,不同商家之间的客服是不同的,所面对的用户也是不同的.要实现一个这样的客服聊天系统,那该系统就必须是一个支持多客服.客服一对多用户的聊天系统. 二 思路 使 ...

  2. Comet——随着AJAX技术兴起而产生的新技术

    不得不说Ajax确实是一个好东西,由它的出现使得WEB端新技术不断产生,Comet就属于这么一个技术,这个技术有时叫做反向AJAX,有时叫做服务器"推"技术,嗯,不要被牛逼闪闪的名 ...

  3. 08 comet反向ajax

    一:HTTP协议与技久链接+分块传输---->反向ajax 反向ajax又叫comet, server push,服务器推技术. 应用范围: 网页聊天服务器,, 新浪微博在线聊天,google ...

  4. Comet——反向Ajax (基础知识)

    Comet:服务器推送,与ajax页面向服务器请求数据相反.几乎可以实时将数据推送到客户端. 但本质一样:浏览器向服务器发起请求,服务器响应请求 Comet实现方式:长轮询.HTTP流 1.长轮询—— ...

  5. php开发客服系统(持久连接+轮询+反向ajax)

    欢迎在php严程序 - php教程学习AJAX教程, 本节课讲解:php开发客服系统(持久连接+轮询+反向ajax) php开发客服系统(下载源码) 用户端(可直接给客户发送消息)客服端(点击用户名. ...

  6. php开发客服系统(持久连接+轮询+反向ajax 转载 http://www.tuicool.com/articles/2mU7v2R)

    php开发客服系统( 下载源码 ) 用户端(可直接给客户发送消息) 客服端(点击用户名.即可给该用户回复消息) 讲两种实现方式: 一:iframe + 服务器推技术comet(反向ajax,即服务器向 ...

  7. HTTP 笔记与总结(9)分块传输、持久链接 与 反向 ajax(comet / server push / 服务器推技术)

    反向 ajax 又叫 comet / server push / 服务器推技术 应用范围:网页聊天服务器,例如新浪微博在线聊天.google mail 网页聊天 原理:一般而言,HTTP 协议的特点是 ...

  8. 反向Ajax,第2部分:WebSocket

    转自:http://kb.cnblogs.com/page/112616/ 前言 时至今日,用户期待的是可通过web访问快速.动态的应用.这一文章系列展示了如何使用反向Ajax(Reverse Aja ...

  9. 反向ajax实现

    在过去的几年中,web开发已经发生了很大的变化.现如今,我们期望的是能够通过web快速.动态地访问应用.在这一新的文章系列中,我们学习如何使用反 向Ajax(Reverse Ajax)技术来开发事件驱 ...

随机推荐

  1. Address space layout randomization

    Address space layout randomization (ASLR) is a computer security technique involved in preventing ex ...

  2. jboss 虚拟路径

    jboss 虚拟路径 上传文件到服务器时,保存到服务器发布应用外路径.这时,就要通过在jboss配置虚拟路劲以访问. 在standalong.xml里找到 <subsystem xmlns=&q ...

  3. redis键的过期和内存淘汰策略

    键的过期时间 设置过期时间 Redis可以为存储在数据库中的值设置过期时间,作为一个缓存数据库,这个特性是很有帮助的.我们项目中的token或其他登录信息,尤其是短信验证码都是有时间限制的. 按照传统 ...

  4. C语言数据结构链栈(创建、入栈、出栈、取栈顶元素、遍历链栈中的元素)

    /**创建链栈*创建一个top指针代表head指针*采用链式存储结构*采用头插法创建链表*操作 创建 出栈 入栈 取栈顶元素*创建数据域的结构体*创建数据域的名称指针*使用随机函数对数据域的编号进行赋 ...

  5. 【转】resultMap详解(包含多表查询)

    简介: MyBatis的每一个查询映射的返回类型都是ResultMap,只是当我们提供的返回类型属性是resultType的时候,MyBatis对自动的给我们把对应的值赋给resultType所指定对 ...

  6. [API 开发管理] EOLINKER 升级为多产品架构, AMS V4.5 版本常见问题汇总

    自AMS4.5开始,eoLinker 全面升级为多产品架构,部分操作方式较以前有较大改变,本文针对改进部分做重点说明. 在说明之前,我们先通过以下的图文看看AMSV4.5更新了哪些内容: Q:我可以创 ...

  7. (蓝桥杯)第八届A组C/C++跳蚱蜢

    #include<iostream> #include<memory.h> #include<stack> #include<string> #incl ...

  8. STM32学习笔记:读写内部Flash(介绍+附代码)

    一.介绍 首先我们需要了解一个内存映射: stm32的flash地址起始于0x0800 0000,结束地址是0x0800 0000加上芯片实际的flash大小,不同的芯片flash大小不同. RAM起 ...

  9. 一个电商项目的Web服务化改造

    一个电商项目的Web服务化改造 项目,早期是随便瞎做的,没啥架构,连基本的设计也没. 有需求,实现需求,再反复修改. 大致就是这么做的. 最近,项目要重新架构,和某boss协商的结果是,采用阿里开源的 ...

  10. Java基础之构造方法及其应用

    构造方法是一种特殊的方法,它是一个与类同名且无返回值类型(连void也不能有)的方法. 对象的创建就是通过构造方法来完成,其功能主要是完成对象的初始化. 当类实例化一个对象时会自动调用构造方法.构造方 ...