重点前端
一、JAVA内的WebSocket是在Java jar7.0以后才能使用的。java
二、须要在JavaServer项目lib目录下引入 javaee-api-7.0 包web
|前端代码后端
|后端JAVA代码api
package websocketPro;数组
import javax.websocket.OnClose;服务器
import javax.websocket.OnMessage;websocket
import javax.websocket.OnOpen;session
import javax.websocket.Session;socket
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.util.HashSet;
import java.util.Set;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet;
/**
* writer: holien Time: 2017-08-01 13:00 Intent: webSocket服务器
*/
@ServerEndpoint("/webSocket/ChatRoom/{roomName}")//这里是你请求的生成的房间服务器路径 roomName是前端发来的 roomName名字
public class ChatRoom {
private static final Map> rooms = new ConcurrentHashMap();
@OnOpen //session 是可选的参数,session为与某个客户端的链接会话,须要经过它来给客户端发送数据
public void connect(@PathParam("roomName") String roomName, Session session) throws Exception {
if (!rooms.containsKey(roomName)) {
Set room = new HashSet<>();
room.add(session);
rooms.put(roomName, room);
} else {
rooms.get(roomName).add(session);
}
System.out.println("创建链接 !");
}
@OnClose
public void disConnect(@PathParam("roomName") String roomName, Session session) {
rooms.get(roomName).remove(session);
System.out.println("断开链接!");
}
@OnMessage
public void receiveMsg(@PathParam("roomName") String roomName, String msg, Session session) throws Exception {
System.out.println(msg);
broadcast(roomName, msg);
}
// 按照房间名进行广播
public static void broadcast(String roomName, String msg) throws Exception {
for (Session session : rooms.get(roomName)) {
session.getAsyncRemote().sendText(msg);
}
}
}
|JAVA服务器目录结构
Tip:下面简单的解释一下每一个函数及其方法的含义和关联。
全部WebSocket项目双向通讯的创建,都须要前端先发送给后端一个请求,而且握手成功以后才能进行通讯 就和打电话一个道理。
webSocket = new WebSocket(url);
上面这个就是前端JS建立一个WebSocket对象 而且发送给后端(URL地址的服务器)一个通讯请求 你正在向一我的打电话,而且等他接电话
@ServerEndpoint("/webSocket/ChatRoom/{roomName}")
var url = "ws://172.16.245.232:8080/WebsocketPro/webSocket/mainBlock/" + roomName;
后端java这个注释标记了当前这个Java文件的服务器访问地址和前端的请求的地址是一致的。
前端定义 roomName 的名称会被后端的 {roomName} 读取到
以前 前端的roomName定义为 MainBlock
因此在请求以后后端注释内的访问路径就变成了
/webSocket/ChatRoom/MainBlock
private static final Map> rooms = new ConcurrentHashMap();
@OnOpen
public void connect(@PathParam("roomName") String roomName, Session session) throws Exception {
if (!rooms.containsKey(roomName)) {
Set room = new HashSet<>(); //建立Hash数组 的数理化对象
room.add(session); //把session对象 即用户对象 添加到Hash对象里
rooms.put(roomName, room); //而且根据房间名添加用户组成的 Hash对象 这里就获取了一个用户集
} else {
rooms.get(roomName).add(session); //获取对应房间的 用户集
}郑州较好的妇科医院 http://www.kd0371.com/
System.out.println("创建链接 !");
}
关于 ConcurrentHashMap 参考ConcurrentHashMap
此时在申请以后会被后端的 @OnOpen注释下的方法接收到
这个时候底层WebSocket会进行和前端的握手协议 咱们是看不到的
诺访问正常而且握手成功,则服务器会自动调用这个链接方法
此时底层会向服务器发送成功握手的协议
而且前端也会调用下面这个定义的的方法
webSocket.onopen = function () {
console.log("和服务器的握手链接创建...(握手)")
};
到这里为止 前端和后端创建了一个理论上永久的通讯协议,只要其中一方不要断开链接。 你成功和他打通了电话
|开始交流
webSocket.send(msg);
咱们前端调用了WebSocket对象的 send() 方法 传入要发送给后台的消息
封装要发送到服务端的数据通常来讲JSON比较好
@OnMessage
public void receiveMsg(@PathParam("roomName") String roomName, String msg, Session session) throws Exception {
System.out.println(msg);
broadcast(roomName, msg);
}
传入的消息就会被后台的 @OnMessage 标记的方法接收
@PathParam(“roomName”) String roomName
这句话的意思就是以前标记的 /webSocket/ChatRoom/{roomName} 里的 roomName 的值
String msg
这个参数就是前台发送的消息。 Session session 这个参数在代码中说明了就不重复解释
在接收到消息以后就调用这个这个函数内的一个完美自定义的方法 broadcast()
public static void broadcast(String roomName, String msg) throws Exception {
for (Session session : rooms.get(roomName)) {
session.getAsyncRemote().sendText(msg);
}
}
这个方法调用了 session 对象里的 getAsyncRemote() 方法的 sendText(msg)
用来向以前封装的全部对象( rooms )广播消息
webSocket.onmessage = function (evt) {
var Data = JSON.parse(evt.data)
};
接收到广播消息以后,前端调用了 WebSocket对象的 onmessage 方法
这里的 evt 参数就是广播的消息 可是后端传过来的是一个对象
咱们要调用这个对象的 evt.data 方法 若是是Json数据 就把它转换成咱们js能识别的对象
到这里为止来就完成了消息的交流。
要断开请求的话,就调用 webSocket.close() 方法 ,这个时候
后台就会自动调用 下面这个方法
@OnClose
public void disConnect(@PathParam("roomName") String roomName, Session session) {
System.out.println("断开链接!");
}
同时响应到前端 ,调用下面这个方法
webSocket.onclose = function () {
console.log("和服务器的握手链接已关闭...(分手)")
webSocket = null;
};
到这里来位置完成了WebSocket 完整的双向通讯。