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

本文依据 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存储 推送需要的身份信息。以上属于个人口头话理解。

 1 package socket;
 2 
 3 import java.nio.CharBuffer;
 4 import java.util.ArrayList;
 5 import java.util.HashMap;
 6 import java.util.List;
 7 
 8 import javax.servlet.ServletConfig;
 9 import javax.servlet.ServletException;
10 import javax.servlet.http.HttpServlet;
11 
12 import org.apache.catalina.websocket.MessageInbound;
13 
14 public class InitServlet extends HttpServlet {
15 
16     private static final long serialVersionUID = -3163557381361759907L;  
17     
18     //private static List<MessageInbound> socketList;    
19     private static HashMap<String,MessageInbound> socketList;    
20       
21     public void init(ServletConfig config) throws ServletException {    
22 //        InitServlet.socketList = new ArrayList<MessageInbound>();    
23         InitServlet.socketList = new HashMap<String,MessageInbound>();    
24         super.init(config);    
25         System.out.println("Server start============");    
26     }    
27         
28     public static HashMap<String,MessageInbound> getSocketList() {    
29         return InitServlet.socketList;    
30     }    
31 /*    public static List<MessageInbound> getSocketList() {    
32         return InitServlet.socketList;    
33     }    
34 */}

 

2.MyWebSocketServlet 

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

 1 package socket;
 2 
 3 import java.io.IOException;
 4 import java.io.PrintWriter;
 5 import java.nio.CharBuffer;
 6 
 7 import javax.servlet.ServletException;
 8 import javax.servlet.http.HttpServlet;
 9 import javax.servlet.http.HttpServletRequest;
10 import javax.servlet.http.HttpServletResponse;
11 
12 import org.apache.catalina.websocket.StreamInbound;
13 import org.apache.catalina.websocket.WebSocketServlet;
14 /**
15  * 
16  * @ClassName: MyWebSocketServlet 
17  * @Description: 建立连接时创立 
18  * @author mangues
19  * @date 2015-7-19
20  */
21 public class MyWebSocketServlet extends WebSocketServlet {
22     
23     public String getUser(HttpServletRequest request){ 
24         String userName = (String) request.getSession().getAttribute("user");
25         if(userName==null){
26             return null;
27         }
28         return userName;  
29        // return (String) request.getAttribute("user");  
30     }  
31     @Override
32     protected StreamInbound createWebSocketInbound(String arg0,
33             HttpServletRequest request) {
34         System.out.println("##########");  
35         return new MyMessageInbound(this.getUser(request)); 
36     }
37 
38 }

 

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

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

onTextMessage :用来获取消息,并发送消息

 1 package socket;
 2 
 3 import java.io.IOException;
 4 import java.nio.ByteBuffer;
 5 import java.nio.CharBuffer;
 6 import java.util.HashMap;
 7 
 8 import org.apache.catalina.websocket.MessageInbound;
 9 import org.apache.catalina.websocket.WsOutbound;
10 
11 import util.MessageUtil;
12 
13 public class MyMessageInbound extends MessageInbound {
14 
15     private String name;
16     public MyMessageInbound() {
17         super();
18     }
19 
20     public MyMessageInbound(String name) {
21         super();
22         this.name = name;
23     }
24 
25     @Override  
26     protected void onBinaryMessage(ByteBuffer arg0) throws IOException {  
27         // TODO Auto-generated method stub 
28           
29     }  
30   
31     @Override  
32     protected void onTextMessage(CharBuffer msg) throws IOException { 
33         //用户所发消息处理后的map
34         HashMap<String,String> messageMap = MessageUtil.getMessage(msg);    //处理消息类
35         //上线用户集合类map
36         HashMap<String, MessageInbound> userMsgMap = InitServlet.getSocketList();
37         
38         String fromName = messageMap.get("fromName");    //消息来自人 的userId
39         
40   
41         String toName = messageMap.get("toName");         //消息发往人的 userId
42         //获取该用户
43         MessageInbound messageInbound = userMsgMap.get(toName);    //在仓库中取出发往人的MessageInbound
44         
45         
46         
47         if(messageInbound!=null){     //如果发往人 存在进行操作
48              WsOutbound outbound = messageInbound.getWsOutbound(); 
49              
50              
51              String content = messageMap.get("content");  //获取消息内容
52              String msgContentString = fromName + "     " + content;   //构造发送的消息
53              
54              //发出去内容
55              CharBuffer toMsg =  CharBuffer.wrap(msgContentString.toCharArray());
56             outbound.writeTextMessage(toMsg);  //
57             outbound.flush();
58         }
59      
60         
61         
62       /*  for (MessageInbound messageInbound : InitServlet.getSocketList()) {  
63             CharBuffer buffer = CharBuffer.wrap(msg);  
64             WsOutbound outbound = messageInbound.getWsOutbound();  
65             outbound.writeTextMessage(buffer);  
66             outbound.flush();  
67         }  */
68           
69     }  
70   
71     @Override  
72     protected void onClose(int status) {  
73         InitServlet.getSocketList().remove(this);  
74         super.onClose(status);  
75     }  
76   
77     @Override  
78     protected void onOpen(WsOutbound outbound) {  
79         super.onOpen(outbound);  
80         //登录的用户注册进去
81         if(name!=null){
82             InitServlet.getSocketList().put(name, this);  
83         }
84 //        InitServlet.getSocketList().add(this);  
85     }  
86       
87       
88 }

 

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

 1 package util;
 2 
 3 import java.nio.CharBuffer;
 4 import java.util.HashMap;
 5 /**
 6  * 
 7  * @ClassName: MessageUtil 
 8  * @Description: 消息处理类
 9  * @author mangues
10  * @date 2015-7-19
11  */
12 public class MessageUtil {
13 
14     public static HashMap<String,String> getMessage(CharBuffer msg) {
15         HashMap<String,String> map = new HashMap<String,String>();
16         String msgString  = msg.toString();
17         String m[] = msgString.split(",");
18         map.put("fromName", m[0]);
19         map.put("toName", m[1]);
20         map.put("content", m[2]);
21         return map;
22     }
23 }

 

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.小化

 1 <%@ page language="java" contentType="text/html; charset=UTF-8"
 2     pageEncoding="UTF-8"%>
 3 <!DOCTYPE html>
 4 <html>
 5 <head>
 6 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
 7 <title>Index</title>
 8 <script type="text/javascript" src="js/jquery 2.1.1.min.js"></script>
 9 <%session.setAttribute("user", "小化");%>
10 <script type="text/javascript">
11 var ws = null;
12 function startWebSocket() {
13     if ('WebSocket' in window)
14         ws = new WebSocket("ws://localhost:8080/webSocket/mywebsocket.do");
15     else if ('MozWebSocket' in window)
16         ws = new MozWebSocket("ws://localhost:8080/webSocket/mywebsocket.do");
17     else
18         alert("not support");
19     
20     
21     ws.onmessage = function(evt) {
22         //alert(evt.data);
23         console.log(evt);
24         $("#xiaoxi").val(evt.data);
25     };
26     
27     ws.onclose = function(evt) {
28         //alert("close");
29         document.getElementById('denglu').innerHTML="离线";
30     };
31     
32     ws.onopen = function(evt) {
33         //alert("open");
34         document.getElementById('denglu').innerHTML="在线";
35         document.getElementById('userName').innerHTML='小化';
36     };
37 }
38 
39 function sendMsg() {
40     var fromName = "小化";
41     var toName = document.getElementById('name').value;  //发给谁
42     var content = document.getElementById('writeMsg').value; //发送内容
43     ws.send(fromName+","+toName+","+content);
44 }
45 </script>
46 </head>
47 <body onload="startWebSocket();">
48 <p>聊天功能实现</p>
49 登录状态:
50 <span id="denglu" style="color:red;">正在登录</span>
51 <br>
52 登录人:
53 <span id="userName"></span>
54 <br>
55 <br>
56 <br>
57 
58 发送给谁:<input type="text" id="name" value="小明"></input>
59 <br>
60 发送内容:<input type="text" id="writeMsg"></input>
61 <br>
62 聊天框:<textarea rows="13" cols="100" readonly id="xiaoxi"></textarea>
63 <br>
64 <input type="button" value="send" onclick="sendMsg()"></input>
65 </body>
66 </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>

 

posted @ 2015-07-19 14:45  mangues  阅读(27119)  评论(3编辑  收藏  举报