zoukankan      html  css  js  c++  java
  • java websocket时时通信

     基本案例是网上爬的,改了很多,单纯发文字聊天功能完整, 1对1单聊, 离线用户能接受到另一方的留言,增加了一张数据库表,如果不用表保存离线数据,也可以选择单例模式缓存来保存。测试了下还可以哦!直接贴代码不明白的可以问我。

       

       java服务端:

              

    package websockets;
    import java.io.IOException;
    import java.io.PrintWriter;
    import java.text.SimpleDateFormat;
    import java.util.Date;
    import java.util.Map;
    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.lang.time.DateFormatUtils;
    import org.json.JSONArray;
    import org.json.JSONException;
    import org.json.JSONObject;
    import org.springframework.http.server.ServletServerHttpRequest;
    
    import  Helper.AAAAYulebaoShareSingleton;
    import  Helper.MySqlHepler2;
    import  Helper.EncryptSafa;
    
    import java.io.IOException;
    import java.util.concurrent.CopyOnWriteArraySet;
    
    import javax.websocket.*;
    import javax.websocket.server.PathParam;
    import javax.websocket.server.ServerEndpoint;
     
     //auth:liaohang
    @ServerEndpoint("/javaWebSocket")
    public class javaWebSocket {
         //静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。
         private static int onlineCount = 0;
     
          //concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象。若要实现服务端与单一客户端通信的话,可以使用Map来存放,其中Key可以为用户标识
      //   private static CopyOnWriteArraySet<javaWebSocket> webSocketSets = new CopyOnWriteArraySet<javaWebSocket>();
         private static JSONObject  webSocketSets = new JSONObject();
          //与某个客户端的连接会话,需要通过它来给客户端发送数据
         private Session session;
         private String[] parameterArr;
         
         private String shareStr;
         private String userKey;
         private String shopKey;
         private String type;
         
         
     
         //这里来个请求的httpRequest类
         /**
           * 连接建立成功调用的方法
          * @param session  可选的参数。session为与某个客户端的连接会话,需要通过它来给客户端发送数据
          */
         
    
         private javaWebSocket chatmemeber;
         
         //数据库操作参数
      private   MySqlHepler2  helper=new MySqlHepler2();
      private JSONArray  returnJsonArray;
      private       String[] mysqlParameter=null;
      private JSONObject  shareObject;
      private String  datatime;
      private int shareInt=0;
     
         @OnOpen
         public void onOpen(Session session){
              this.session = session;
              shareStr= session.getRequestURI().toString();
              shareStr=shareStr.replace("/yulebaoServlet/javaWebSocket?", "");
              
           
           
              shareStr=shareStr.replace("user=", "");
              shareStr=shareStr.replace("shop=", "");
              shareStr=shareStr.replace("type=", "");
              parameterArr=shareStr.split("&");
              
              
              
              
              type=parameterArr[2];
              if(type.equals("user"))
              {
                  userKey=parameterArr[0];
                  shopKey=parameterArr[1];
                  webSocketSets.put(userKey, this); 
                  //查询一次数据库,看是有人在我离线时给我发了消息
                    mysqlParameter=new String[]{userKey};   
                     returnJsonArray=helper.executeQueryT("select * from AAAAAAAAAChatSheet where  sessionKey=?", mysqlParameter);  
                     try
                     { 
                         shareInt=returnJsonArray.length();
                     } catch (Exception e) {
                         shareInt=0;
                      }
                     
                     if(returnJsonArray.length()>0)
                     {
                         shareObject=returnJsonArray.getJSONObject(0);
                         shareStr= shareObject.getString("chatContentArray");
                          try {
                            this.sendMessage(shareStr);
                        } catch (IOException e) {
                          e.printStackTrace();
                        }
                          
                      mysqlParameter=new String[]{userKey};  
                           helper.executeUpdate("delete from   AAAAAAAAAChatSheet     where sessionKey=?", mysqlParameter);
                     }
                      
                    
                     
              }
              else
              {
                  userKey=parameterArr[0];
                  shopKey=parameterArr[1];
                  webSocketSets.put(shopKey, this); 
                  //查询一次数据库,看是有人在我离线时给我发了消息
                   mysqlParameter=new String[]{shopKey}; 
                  returnJsonArray=helper.executeQueryT("select * from AAAAAAAAAChatSheet where  sessionKey=?", mysqlParameter);  
                  try
                  { 
                      shareInt=returnJsonArray.length();
                  } catch (Exception e) {
                      shareInt=0;
                   }
                  
                  if(returnJsonArray.length()>0)
                  {
                      shareObject=returnJsonArray.getJSONObject(0);
                     shareStr= shareObject.getString("chatContentArray");
                       try {
                          this.sendMessage(shareStr);
                        } catch (IOException e) {
                          e.printStackTrace();
                        }
                       //删除key
                  
                     mysqlParameter=new String[]{shopKey};  
                     helper.executeUpdate("delete from   AAAAAAAAAChatSheet     where sessionKey=?", mysqlParameter);
                  }
                  
                  
                  
                  
              }
             
              
               
               
                //加入set中
             addOnlineCount();           //在线数加1
             System.out.println("有新连接加入!当前在线人数为" + getOnlineCount());
         } 
      
      
         /**
          * 连接关闭调用的方法
          */
         @OnClose
          public void onClose(){
             if(type.equals("user"))
             {
               if(!webSocketSets.isNull(userKey))   
                  {
               webSocketSets.remove(userKey); 
                }
            
             }
             else
             {
                 if(!webSocketSets.isNull(shopKey))
                    {
                     webSocketSets.remove(shopKey); 
                    }
                 
         
             }
             //从set中删除
             subOnlineCount();           //在线数减1
             System.out.println("有一连接关闭!当前在线人数为" + getOnlineCount());
         }
     
          /**
           * 收到客户端消息后调用的方法
          * @param message 客户端发送过来的消息
          * @param session 可选的参数
          */
          @OnMessage
          public void onMessage(String message, Session session) {
              System.out.println("来自客户端的消息:" + message);
              //群发消息
              if(type.equals("user"))
              {
                  if(!webSocketSets.isNull(shopKey))   
                    {
                  chatmemeber=(javaWebSocket)webSocketSets.get(shopKey);
                    try {
                      chatmemeber.sendMessage(message);
                     } catch (IOException e) {
                       e.printStackTrace();
                      }
                    }
                  else
                  {
                      
                      insertDataBase(shopKey,message);
                     
                        
                  
                  }
              }
               else
               {
                   if(!webSocketSets.isNull(userKey))   
                    {
                   chatmemeber=(javaWebSocket)webSocketSets.get(userKey);
                   
                  try {
                     chatmemeber.sendMessage(message);
                  } catch (IOException e) {
                      e.printStackTrace();
                   }
                    }
                   
                   else
                   {
                       //接消息以方不在,插入数据库保存
                      insertDataBase(userKey,message);
                     
                   }
                   
                   
               }
             
              
             
              //1对多发消息
            /* for(javaWebSocket item: webSocketSets){
                  try {
                     item.sendMessage(message);
                  } catch (IOException e) {
                      e.printStackTrace();
                      continue;
                 }
             }*/
          }
     
         /**
          * 发生错误时调用
          * @param session
          * @param error
          */
         @OnError
         public void onError(Session session, Throwable error){
              System.out.println("发生错误");
             error.printStackTrace();
         }
     
         /**
           * 这个方法与上面几个方法不一样。没有用注解,是根据自己需要添加的方法。
          * @param message
           * @throws IOException
          */
          public void sendMessage(String message) throws IOException{
             this.session.getBasicRemote().sendText(message);
              //this.session.getAsyncRemote().sendText(message);
          }
     
         public static synchronized int getOnlineCount() {
              return onlineCount;
          }
     
          public static synchronized void addOnlineCount() {
              javaWebSocket.onlineCount++;
         }
     
          public static synchronized void subOnlineCount() {
              javaWebSocket.onlineCount--;
         }
          
          
          
          //当一方用户下线之后,如果再发消息,需要将接收消息保存到数据库
          public void insertDataBase(String shareKey,String message)
          {
              shareObject=new JSONObject();
               datatime=DateFormatUtils.format(new Date(), "yyyy-MM-dd HH:mm");
              shareObject.put("datatime", datatime);
              shareObject.put("message", message);
              
              
             mysqlParameter=new String[]{shareKey};   
             returnJsonArray=helper.executeQueryT("select * from AAAAAAAAAChatSheet where  sessionKey=?", mysqlParameter);    
            try
            {
                shareInt=returnJsonArray.length();
            }
            catch(Exception e)
            {
                shareInt=0;
                returnJsonArray=new JSONArray();
             }
            
            
            if(shareInt==0) //插入数据
            {
            
             returnJsonArray.put(shareObject);
             mysqlParameter=new String[]{shareKey,datatime,returnJsonArray.toString()};  
             helper.executeUpdate("insert into AAAAAAAAAChatSheet(sessionKey,sessionCreateTimes,chatContentArray)values(?,?,?)", mysqlParameter);
            
            }
            else//更新连端的数据
            {
                returnJsonArray.put(shareObject);
                mysqlParameter=new String[]{returnJsonArray.toString(),shareKey};  
               helper.executeUpdate("update  AAAAAAAAAChatSheet set chatContentArray=? where sessionKey=?", mysqlParameter);
                
            }
            
               
          }
     }

      前端页面User方:

      

    <%@ page language="java" pageEncoding="UTF-8" %>
      <!DOCTYPE html>
      <html>
      <head>
          <title>Java后端WebSocket的Tomcat实现</title>
      </head>
      <body>
          Welcome<br/><input id="text" type="text"/>
          <button onclick="send()">发送消息</button>
         <hr/>
         <button onclick="closeWebSocket()">关闭WebSocket连接</button>
         <hr/>
         <div id="message"></div>
     </body>
     
     <script type="text/javascript">
         var websocket = null;
         //判断当前浏览器是否支持WebSocket
         if ('WebSocket' in window) {
               //第一个创建链接的用户需要两个key,创建一个webosckt链接。为了保证JSONObject单个创建的websocket key唯一 所以参数就用双方的唯一账户或id正反组合+类型'
               //为什么要传两个key?比如这个是user请求的链接,他创建websocket时需要查询一下对方有没有离线留言,如果有离线留言得访问一次数据库读出来返回,所以shop这个key也必须带上
              var user="liaohang"+"xiaoming"+"user";
              var  shop="xiaoming"+"liaohang"+"shop";
             websocket = new WebSocket("ws://localhost:8080/yulebaoServlet/javaWebSocket?user="+user+"&shop="+shop+"&type=user");
           
         }
         else {
             alert('当前浏览器 Not support websocket')
         }
     
         //连接发生错误的回调方法
         websocket.onerror = function () {
             setMessageInnerHTML("WebSocket连接发生错误");
         };
     
         //连接成功建立的回调方法
         websocket.onopen = function () {
             setMessageInnerHTML("WebSocket连接成功");
         }
     
         //接收到消息的回调方法
         websocket.onmessage = function (event) {
             setMessageInnerHTML(event.data);
         }
     
         //连接关闭的回调方法
         websocket.onclose = function () {
             setMessageInnerHTML("WebSocket连接关闭");
         }
     
         //监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。
         window.onbeforeunload = function () {
             closeWebSocket();  
            }
    
         //将消息显示在网页上
         function setMessageInnerHTML(innerHTML) {
             document.getElementById('message').innerHTML += innerHTML + '<br/>';
         }
     
         //关闭WebSocket连接
         function closeWebSocket() {
            websocket.close();
         }
     
         //发送消息
        function send() {
            var message = document.getElementById('text').value;
             websocket.send(message);
          }
      </script>
      </html>

    前端页面Shop方:

    <%@ page language="java" pageEncoding="UTF-8" %>
      <!DOCTYPE html>
      <html>
      <head>
          <title>Java后端WebSocket的Tomcat实现</title>
      </head>
      <body>
          Welcome<br/><input id="text" type="text"/>
          <button onclick="send()">发送消息</button>
         <hr/>
         <button onclick="closeWebSocket()">关闭WebSocket连接</button>
         <hr/>
         <div id="message"></div>
     </body>
     
     <script type="text/javascript">
         var websocket = null;
         //判断当前浏览器是否支持WebSocket
         if ('WebSocket' in window) {
        	  //Id account+对方的account      +type  接单者发起请求
        	  var user="liaohang"+"xiaoming"+"user";
        	  var  shop="xiaoming"+"liaohang"+"shop";
             websocket = new WebSocket("ws://localhost:8080/yulebaoServlet/javaWebSocket?user="+user+"&shop="+shop+"&type=shop");
           
         }
         else {
             alert('当前浏览器 Not support websocket')
         }
     
         //连接发生错误的回调方法
         websocket.onerror = function () {
             setMessageInnerHTML("WebSocket连接发生错误");
         };
     
         //连接成功建立的回调方法
         websocket.onopen = function () {
             setMessageInnerHTML("WebSocket连接成功");
         }
     
         //接收到消息的回调方法
         websocket.onmessage = function (event) {
             setMessageInnerHTML(event.data);
         }
     
         //连接关闭的回调方法
         websocket.onclose = function () {
             setMessageInnerHTML("WebSocket连接关闭");
         }
     
         //监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。
         window.onbeforeunload = function () {
             closeWebSocket();  
            }
    
         //将消息显示在网页上
         function setMessageInnerHTML(innerHTML) {
             document.getElementById('message').innerHTML += innerHTML + '<br/>';
         }
     
         //关闭WebSocket连接
         function closeWebSocket() {
            websocket.close();
         }
     
         //发送消息
        function send() {
            var message = document.getElementById('text').value;
             websocket.send(message);
          }
      </script>
      </html>
    

      前端页面User方和 Shop方 不同的就是传参数的类型

    https://www.bai6du.com/yulebaoServlet/talkTest.jsp

    https://www.bai6du.com/yulebaoServlet/talkTest2.jsp

  • 相关阅读:
    MFC 错误异常,用vs添加资源并为资源定义类后报错:error C2065 : 未声明的标识符
    概率统计:数学期望、方差、协方差、相关系数、矩
    图像处理中的一些基本概念
    OpenCV中对Mat里面depth,dims,channels,step,data,elemSize和数据地址计算的理解
    C++语言运算符的功能、优先级和结合性
    标准C++中的string类的用法总结
    linux性能系列--块设备
    linux性能系列--网络
    linux性能系列--内存
    linux性能系列--cpu
  • 原文地址:https://www.cnblogs.com/xiaoliao/p/12458390.html
Copyright © 2011-2022 走看看