本文依據 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>