javaweb webSocket 实现简单的点对点聊天功能

ydx3 6年前

本文依据 http://redstarofsleep.iteye.com/blog/1488639?page=4  内容修改完成,实现点对点聊天

需要 jdk 7 , tomcat需要支持websocket的版本 

 

1.InitServlet

   该类主要是用来初始化构造将来存储用户身份信息的map仓库,利用其初始化方法Init 初始化仓库, 利用其静态方法getSocketList 获得对应的用户身份信息。

   webSocket ,我认为MessageInbound 用来识别登录人的信息,用它来找到对应的人,推送消息。每次登录都会产生一个MessageInbound。

  这里的 HashMap<String,MessageInbound>    :string 存储用户session的登录id,MessageInbound存储 推送需要的身份信息。以上属于个人口头话理解。

package socket;    import java.nio.CharBuffer;  import java.util.ArrayList;  import java.util.HashMap;  import java.util.List;    import javax.servlet.ServletConfig;  import javax.servlet.ServletException;  import javax.servlet.http.HttpServlet;    import org.apache.catalina.websocket.MessageInbound;    public class InitServlet extends HttpServlet {        private static final long serialVersionUID = -3163557381361759907L;              //private static List<MessageInbound> socketList;          private static HashMap<String,MessageInbound> socketList;                  public void init(ServletConfig config) throws ServletException {      //        InitServlet.socketList = new ArrayList<MessageInbound>();              InitServlet.socketList = new HashMap<String,MessageInbound>();              super.init(config);              System.out.println("Server start============");          }                    public static HashMap<String,MessageInbound> getSocketList() {              return InitServlet.socketList;          }      /*    public static List<MessageInbound> getSocketList() {              return InitServlet.socketList;          }      */}

2.MyWebSocketServlet 

  websocket用来建立连接的servlet,建立连接时,首先在session获取该登录人的userId,在调用MyMessageInbound构造函数传入userId

package socket;    import java.io.IOException;  import java.io.PrintWriter;  import java.nio.CharBuffer;    import javax.servlet.ServletException;  import javax.servlet.http.HttpServlet;  import javax.servlet.http.HttpServletRequest;  import javax.servlet.http.HttpServletResponse;    import org.apache.catalina.websocket.StreamInbound;  import org.apache.catalina.websocket.WebSocketServlet;  /**   *    * @ClassName: MyWebSocketServlet    * @Description: 建立连接时创立    * @author mangues   * @date 2015-7-19   */  public class MyWebSocketServlet extends WebSocketServlet {            public String getUser(HttpServletRequest request){           String userName = (String) request.getSession().getAttribute("user");          if(userName==null){              return null;          }          return userName;           // return (String) request.getAttribute("user");        }        @Override      protected StreamInbound createWebSocketInbound(String arg0,              HttpServletRequest request) {          System.out.println("##########");            return new MyMessageInbound(this.getUser(request));       }    }

3.onOpen方法调用InitServlet的map身份仓库,

放入用户userId 和 对应该登录用户的websocket身份信息MessageInbound (可以用userId来寻找到推送需要的 身份MessageInbound )

onTextMessage :用来获取消息,并发送消息
package socket;    import java.io.IOException;  import java.nio.ByteBuffer;  import java.nio.CharBuffer;  import java.util.HashMap;    import org.apache.catalina.websocket.MessageInbound;  import org.apache.catalina.websocket.WsOutbound;    import util.MessageUtil;    public class MyMessageInbound extends MessageInbound {        private String name;      public MyMessageInbound() {          super();      }        public MyMessageInbound(String name) {          super();          this.name = name;      }        @Override        protected void onBinaryMessage(ByteBuffer arg0) throws IOException {            // TODO Auto-generated method stub                   }            @Override        protected void onTextMessage(CharBuffer msg) throws IOException {           //用户所发消息处理后的map          HashMap<String,String> messageMap = MessageUtil.getMessage(msg);    //处理消息类          //上线用户集合类map          HashMap<String, MessageInbound> userMsgMap = InitServlet.getSocketList();                    String fromName = messageMap.get("fromName");    //消息来自人 的userId                        String toName = messageMap.get("toName");         //消息发往人的 userId          //获取该用户          MessageInbound messageInbound = userMsgMap.get(toName);    //在仓库中取出发往人的MessageInbound                                        if(messageInbound!=null){     //如果发往人 存在进行操作               WsOutbound outbound = messageInbound.getWsOutbound();                                              String content = messageMap.get("content");  //获取消息内容               String msgContentString = fromName + "     " + content;   //构造发送的消息                              //发出去内容               CharBuffer toMsg =  CharBuffer.wrap(msgContentString.toCharArray());              outbound.writeTextMessage(toMsg);  //              outbound.flush();          }                                   /*  for (MessageInbound messageInbound : InitServlet.getSocketList()) {                CharBuffer buffer = CharBuffer.wrap(msg);                WsOutbound outbound = messageInbound.getWsOutbound();                outbound.writeTextMessage(buffer);                outbound.flush();            }  */                  }            @Override        protected void onClose(int status) {            InitServlet.getSocketList().remove(this);            super.onClose(status);        }            @Override        protected void onOpen(WsOutbound outbound) {            super.onOpen(outbound);            //登录的用户注册进去          if(name!=null){              InitServlet.getSocketList().put(name, this);            }  //        InitServlet.getSocketList().add(this);        }                    }

4.消息处理类,处理前端发来的消息

package util;    import java.nio.CharBuffer;  import java.util.HashMap;  /**   *    * @ClassName: MessageUtil    * @Description: 消息处理类   * @author mangues   * @date 2015-7-19   */  public class MessageUtil {        public static HashMap<String,String> getMessage(CharBuffer msg) {          HashMap<String,String> map = new HashMap<String,String>();          String msgString  = msg.toString();          String m[] = msgString.split(",");          map.put("fromName", m[0]);          map.put("toName", m[1]);          map.put("content", m[2]);          return map;      }  }

5.web配置

<?xml version="1.0" encoding="UTF-8"?>  <web-app version="3.0"       xmlns="http://java.sun.com/xml/ns/javaee"       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"       xsi:schemaLocation="http://java.sun.com/xml/ns/javaee       http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">          <servlet>        <servlet-name>mywebsocket</servlet-name>        <servlet-class>socket.MyWebSocketServlet</servlet-class>      </servlet>      <servlet-mapping>        <servlet-name>mywebsocket</servlet-name>        <url-pattern>*.do</url-pattern>      </servlet-mapping>            <servlet>        <servlet-name>initServlet</servlet-name>        <servlet-class>socket.InitServlet</servlet-class>        <load-on-startup>1</load-on-startup>      </servlet>      <welcome-file-list>      <welcome-file>index.jsp</welcome-file>    </welcome-file-list>  </web-app>

6,。前端,为方便起见,我直接用了两个jsp,在其中用<%session.setAttribute("user","小明")%>;来表示登录。

      两个jsp没任何本质差别,只是用来表示两个不同的人登录,可以同两个浏览器打开不同的jsp,来聊天操作

   A.小化

<%@ page language="java" contentType="text/html; charset=UTF-8"      pageEncoding="UTF-8"%>  <!DOCTYPE html>  <html>  <head>  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">  <title>Index</title>  <script type="text/javascript" src="js/jquery 2.1.1.min.js"></script>  <%session.setAttribute("user", "小化");%>  <script type="text/javascript">  var ws = null;  function startWebSocket() {      if ('WebSocket' in window)          ws = new WebSocket("ws://localhost:8080/webSocket/mywebsocket.do");      else if ('MozWebSocket' in window)          ws = new MozWebSocket("ws://localhost:8080/webSocket/mywebsocket.do");      else          alert("not support");                  ws.onmessage = function(evt) {          //alert(evt.data);          console.log(evt);          $("#xiaoxi").val(evt.data);      };            ws.onclose = function(evt) {          //alert("close");          document.getElementById('denglu').innerHTML="离线";      };            ws.onopen = function(evt) {          //alert("open");          document.getElementById('denglu').innerHTML="在线";          document.getElementById('userName').innerHTML='小化';      };  }    function sendMsg() {      var fromName = "小化";      var toName = document.getElementById('name').value;  //发给谁      var content = document.getElementById('writeMsg').value; //发送内容      ws.send(fromName+","+toName+","+content);  }  </script>  </head>  <body onload="startWebSocket();">  <p>聊天功能实现</p>  登录状态:  <span id="denglu" style="color:red;">正在登录</span>  <br>  登录人:  <span id="userName"></span>  <br>  <br>  <br>    发送给谁:<input type="text" id="name" value="小明"></input>  <br>  发送内容:<input type="text" id="writeMsg"></input>  <br>  聊天框:<textarea rows="13" cols="100" readonly id="xiaoxi"></textarea>  <br>  <input type="button" value="send" onclick="sendMsg()"></input>  </body>  </html>

 B.小明
<%@ page language="java" contentType="text/html; charset=UTF-8"      pageEncoding="UTF-8"%>  <!DOCTYPE html>  <html>  <head>  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">  <title>Index</title>  <script type="text/javascript" src="js/jquery 2.1.1.min.js"></script>  <%session.setAttribute("user", "小明");%>  <script type="text/javascript">  var ws = null;  function startWebSocket() {      if ('WebSocket' in window)          ws = new WebSocket("ws://localhost:8080/webSocket/mywebsocket.do");      else if ('MozWebSocket' in window)          ws = new MozWebSocket("ws://localhost:8080/webSocket/mywebsocket.do");      else          alert("not support");                  ws.onmessage = function(evt) {          console.log(evt);          //alert(evt.data);          $("#xiaoxi").val(evt.data);      };            ws.onclose = function(evt) {          //alert("close");          document.getElementById('denglu').innerHTML="离线";      };            ws.onopen = function(evt) {          //alert("open");          document.getElementById('denglu').innerHTML="在线";          document.getElementById('userName').innerHTML="小明";      };  }    function sendMsg() {      var fromName = "小明";      var toName = document.getElementById('name').value;  //发给谁      var content = document.getElementById('writeMsg').value; //发送内容      ws.send(fromName+","+toName+","+content);  }  </script>  </head>  <body onload="startWebSocket();">  <p>聊天功能实现</p>  登录状态:  <span id="denglu" style="color:red;">正在登录</span>  <br>  登录人:  <span id="userName"></span>  <br>  <br>  <br>    发送给谁:<input type="text" id="name" value="小化"></input>  <br>  发送内容:<input type="text" id="writeMsg"></input>  <br>  聊天框:<textarea rows="13" cols="100" readonly id="xiaoxi"></textarea>  <br>  <input type="button" value="send" onclick="sendMsg()"></input>  </body>  </html>

来自:http://www.cnblogs.com/Mangues/p/4658635.html