Comet反向ajax技术实现客服聊天系统

说明:Comet反向Ajax是在看了燕十八老师的视频以后,结合他讲解的例子,自己用ajax+java实现了一遍。在这里把代码贴出来,以供大家学习。同时,ajax轮询技术也可以用在消息推送的功能中,下次有时间,可以把相关的代码和设计思路贴出来,一起学习学习!

客户端代码:

 1 <!DOCTYPE html>
 2 <html>
 3   <head>
 4     <title>客户端</title>
 5     
 6     <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
 7     <meta http-equiv="description" content="this is my page">
 8     <meta http-equiv="content-type" content="text/html; charset=UTF-8">
 9     <style>
10         *{margin:0; padding:0;}
11         h1{padding-left:300px;}
12         #msg{margin:20px;width:800px;height:400px;background:#ccc;border:2px solid #000;padding-left:10px;font-family: "微软雅黑";
13             font-size: 14px;padding:20px;overflow:auto;}
14         #msg p{line-height:20px;}
15         .say p:nth-of-type(2){text-indent: 20px;}
16         .reply{text-align:right;color:blue;}
17         #operate{margin:20px;font-family: "微软雅黑";font-size:14px;}
18         #operate #content{width:600px;height:30px;padding-left:10px;}
19         #operate input:nth-of-type(2){width:80px;height:30px;font-family: "微软雅黑";}
20     </style>
21   </head>
22   
23   <body>
24       <h1>客户端发送信息</h1>
25       <div id="msg">
26       </div>
27       <div id="operate">
28           <input type="text" id="content" placeholder="请输入发送内容"/>
29           <input type="button" value="点击发送" onclick="sendHandler();">
30       </div>
31   </body>
32 </html>
33 <script type="text/javascript">
34     var xhr = new XMLHttpRequest();
35     window.onload = function(){
36         function autoSend(){
37             xhr.open("POST", "getClientMsg.do",true);
38             xhr.onreadystatechange = function(){
39                 if(xhr.readyState == 4 && xhr.status == 200){
40                     if(xhr.responseText != "reload")setValue(xhr.responseText);
41                     window.setTimeout(function(){
42                         autoSend();
43                     }, 500);
44                 }
45             };
46             xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
47             xhr.send(null);
48         }
49         autoSend();
50     }
51     
52     function setValue(result){
53         console.log("result",result);
54         var strs = result.split("&");
55         var date = new Date();
56         date = date.toLocaleDateString();
57         document.getElementById("msg").innerHTML += "<div class='say'><p>客服中心&nbsp;"+date+"</p><p>"+strs[1]+"</p></div>";    
58     }
59     //发送数据
60     function sendHandler(){
61         var oContent = document.getElementById("content");
62         if(null != oContent.value){
63             var xhr = new XMLHttpRequest();
64             xhr.open("POST", "sendMsg.do",true);
65             xhr.onreadystatechange = function(){
66                 if(xhr.readyState == 4 && xhr.status == 200){
67                     if(xhr.responseText == "success"){
68                         var date = new Date();
69                         date = date.toLocaleDateString();
70                         document.getElementById("msg").innerHTML += "<div class='reply'><p>我&nbsp;"+date+"</p>"+
71                             "<p>"+oContent.value+"</p></div>";
72                         document.getElementById("content").value = "";
73                     }
74                 }
75             }
76             xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
77             xhr.send("sendIdentity=client&content="+oContent.value);
78             
79         }
80     }
81 
82 </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");
            }
        }
}

  客服端:

 1 <!DOCTYPE html>
 2 <html>
 3   <head>
 4     <title>客服端</title>
 5     <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
 6     <meta http-equiv="description" content="this is my page">
 7     <meta http-equiv="content-type" content="text/html; charset=UTF-8">
 8     <style>
 9         *{margin:0; padding:0;}
10         h1{padding-left:300px;}
11         #msg{margin:20px;width:800px;height:400px;background:#ccc;border:2px solid #000;padding-left:10px;font-family: "微软雅黑";
12             font-size: 14px;padding:20px;overflow:auto;}
13         #msg p{line-height:20px;}
14         .say p:nth-of-type(1){cursor: pointer;}
15         .say p:nth-of-type(2){text-indent: 20px;}
16         .reply{text-align:right;color:blue;}
17         #operate{margin:20px;font-family: "微软雅黑";font-size:14px;}
18         #operate #content{width:600px;height:30px;padding-left:10px;}
19         #operate input:nth-of-type(2){width:80px;height:30px;font-family: "微软雅黑";}
20     </style>
21   </head>
22   
23   <body>
24       <h1>服务端回复信息</h1>
25       <div id="msg">
26       </div>
27       <div id="operate">
28           <p>回复人:<span id="person"></span></p><br/>
29           <input type="text" id="content" placeholder="请输入回复内容"/>
30           <input type="button" value="点击回复" onclick="replyHandler();">
31       </div>
32   </body>
33 </html>
34 <script type="text/javascript">
35     var xhr = new XMLHttpRequest();
36     window.onload = function(){
37         document.getElementById("msg").onclick = function(ev){
38             var event = ev || window.event;
39             if(event.target.nodeName.toLowerCase() == "span"){
40                 document.getElementById("person").innerHTML = event.target.innerText;
41             }
42         }
43     
44         function autoSend(){
45             xhr.open("POST", "getServerMsg.do",true);
46             xhr.onreadystatechange = function(){
47                 if(xhr.readyState == 4 && xhr.status == 200){
48                     if(xhr.responseText != "reload")setValue(xhr.responseText);
49                     window.setTimeout(function(){
50                         autoSend();
51                     }, 500);
52                 }
53             };
54             xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
55             xhr.send(null);
56         }
57         autoSend();
58     }
59     function setValue(result){
60         var strs = result.split("&");
61         var date = new Date();
62         date = date.toLocaleDateString();
63         document.getElementById("msg").innerHTML += "<div class='say'><p class='clientIp'>"+
64             "<span>"+strs[0]+"</span>&nbsp;"+date+"</p><p>"+strs[1]+"</p></div>";    
65     }
66     //发送回复内容
67     function replyHandler(){
68         var value = document.getElementById("content").value;
69         var rec = document.getElementById("person").innerText;
70         if(!rec){
71             alert("请选择回复人");
72             return;
73         }
74         if(null != value){
75             var xhr = new XMLHttpRequest();
76             xhr.open("POST", "sendMsg.do",true);
77             xhr.onreadystatechange = function(){
78                 if(xhr.readyState == 4 && xhr.status == 200){
79                     if(xhr.responseText == "success"){
80                         var date = new Date();
81                         date = date.toLocaleDateString();
82                         document.getElementById("msg").innerHTML += "<div class='reply'><p>我&nbsp;"+date+"</p><p>"+value+"</p></div>";
83                         document.getElementById("content").value = "";
84                     }
85                 }
86             }
87             xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
88             xhr.send("sendIdentity=admin&content="+value+"&rec="+rec);
89         }
90     }
91 </script>

  服务端获取消息代码:

 1 package com.sgepit.ajax;
 2 
 3 import java.io.IOException;
 4 import java.sql.Connection;
 5 
 6 import javax.servlet.ServletException;
 7 import javax.servlet.annotation.WebServlet;
 8 import javax.servlet.http.HttpServlet;
 9 import javax.servlet.http.HttpServletRequest;
10 import javax.servlet.http.HttpServletResponse;
11 
12 import org.apache.commons.dbutils.QueryRunner;
13 import org.apache.commons.dbutils.handlers.BeanHandler;
14 
15 import com.sgepit.ajax.entity.Msg;
16 import com.sgepit.ajax.util.DBCon;
17 
18 
19 /**
20  * @author tengri
21  * @since 2015-12-12 下午9:59:45
22  * @description: 服务端获取消息
23  */
24 @SuppressWarnings("all")
25 @WebServlet("/getServerMsg.do")
26 public class GetServerMsg extends HttpServlet {
27 
28         @Override
29         protected void doPost(HttpServletRequest req, HttpServletResponse resp)throws ServletException, IOException {
30             try {
31                 Connection conn = DBCon.getConnection();
32                 QueryRunner qr = new QueryRunner();
33                 String clientIP = req.getRemoteAddr();
34                 String sql = "select * from msg where rec =? and isread = 0 limit 1";
35                 Object[] param = {"admin"};
36                 Msg msg = null;
37                 resp.setCharacterEncoding("utf-8"); //处理中文乱码
38                 long startTime = System.currentTimeMillis();
39                 while(true){
40                     msg = qr.query(DBCon.getConnection(), sql, new BeanHandler(Msg.class), param);
41                     if(null != msg ){
42                         String result = msg.getPos() + "&" + msg.getContent();
43                         System.out.println("servler:" +result);
44                         resp.getWriter().write(result);
45                         sql = "update msg set isread=1 where uuid=?";
46                         Object[] param2 = {msg.getUuid()};
47                         qr.update(conn, sql, param2);
48                         break;
49                     }
50                     if(System.currentTimeMillis() - startTime >=5000){
51                         resp.getWriter().write("reload");
52                         break;
53                     }
54                     Thread.sleep(500);
55                 }
56             } catch (Exception e) {
57                 e.printStackTrace();
58                 resp.getWriter().write("error");
59             }
60         }
61 }

  发送消息代码:客户端和客服端发送消息都是调用同一个接口,只是在后台做了相关判断。

 1 package com.sgepit.ajax;
 2 
 3 import java.io.IOException;
 4 
 5 import javax.servlet.ServletException;
 6 import javax.servlet.annotation.WebServlet;
 7 import javax.servlet.http.HttpServlet;
 8 import javax.servlet.http.HttpServletRequest;
 9 import javax.servlet.http.HttpServletResponse;
10 
11 import org.apache.commons.dbutils.QueryRunner;
12 import org.apache.commons.dbutils.handlers.BeanHandler;
13 
14 import com.sgepit.ajax.entity.Msg;
15 import com.sgepit.ajax.util.DBCon;
16 
17 /**
18  * @author tengri
19  * @since 2015-12-12 下午9:59:24
20  * @description: 发送消息
21  */
22 @SuppressWarnings("all")
23 @WebServlet("/sendMsg.do")
24 public class SendMsg extends HttpServlet {
25 
26     @Override
27     protected void doPost(HttpServletRequest req, HttpServletResponse resp)throws ServletException, IOException {
28         req.setCharacterEncoding("utf-8");
29         String sendIdentity = req.getParameter("sendIdentity");
30         String content = req.getParameter("content");
31         String rec = "admin";
32         String pos = "admin";
33         try {
34             //如果是服务端发送消息,则会传过来接收者对象,如果是客户端发送消息,接收者为admin,发送端为当前ip用户
35             if("admin".equals(sendIdentity)){
36                 rec = req.getParameter("rec");
37             }else{
38                 pos = req.getRemoteAddr();
39             }
40             QueryRunner qr = new QueryRunner();
41             String sql = "insert into msg(rec,pos,content,isread)values(?,?,?,0)";
42             Object[] params = {rec,pos,content};
43             qr.insert(DBCon.getConnection(),sql, new BeanHandler(Msg.class), params);
44             resp.getWriter().write("success");
45         } catch (Exception e) {
46             resp.getWriter().write("error");
47             e.printStackTrace();
48         }
49     }
50 }

  截图:

原文地址:https://www.cnblogs.com/tengri/p/5555891.html