1.js部分
var lockReconnect = false; //避免ws重复连接
var ws = null; // 判断当前浏览器是否支持WebSocket
var wsUrl = "ws:"+ip+":8081";
createWebSocket(wsUrl); //连接ws
function createWebSocket(url) {
try {
if ('WebSocket' in window) {
ws = new WebSocket(url);
} else if ('MozWebSocket' in window) {
ws = new MozWebSocket(url);
} else {
layui.use(['layer'], function () {
var layer = layui.layer;
layer.alert("您的浏览器不支持websocket协议,建议使用新版谷歌、火狐等浏览器,请勿使用IE10以下浏览器,360浏览器请使用极速模式,不要使用兼容模式!");
});
}
initEventHandle();
} catch (e) {
reconnect(url);
console.log(e);
}
}
function initEventHandle() {
ws.onclose = function () {
console.log("llws连接关闭!" + new Date().toUTCString());
var start=0;
reconnect(wsUrl);
};
ws.onerror = function () {
console.log("llws连接错误!");
reconnect(wsUrl);
};
ws.onopen = function () {
ws.send(uid);
heartCheck.reset().start(); //心跳检测重置
console.log("llws连接成功!" + new Date().toUTCString());
};
ws.onmessage = function (event) { //如果获取到消息,心跳检测重置
var eventData = event.data;
handMsg(eventData);
heartCheck.reset().start(); //拿到任何消息都说明当前连接是正常的
};
}
// 监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。
window.onbeforeunload = function () {
ws.close();
}
function reconnect(url) {
if (lockReconnect) return;
lockReconnect = true;
setTimeout(function () { //没连接上会一直重连,设置延迟避免请求过多
createWebSocket(url);
lockReconnect = false;
}, 5000);
}
//心跳检测
var heartCheck = {
timeout: 60000, //1分钟发一次心跳
timeoutObj: null,
serverTimeoutObj: null,
reset: function () {
clearTimeout(this.timeoutObj);
clearTimeout(this.serverTimeoutObj);
return this;
},
start: function () {
var self = this;
this.timeoutObj = setTimeout(function () {
ws.send(uid);
self.serverTimeoutObj = setTimeout(function () {
ws.close();
},self.timeout)
},this.timeout)
}
}
function handMsg(eventData){
//ajax连接后台处理业务...
}
2.后台代码
//使用监听器机制实现ServletContextListener接口
public class WebContextListener implements ServletContextListener{
//消亡时执行的方法
@Override
public void contextDestroyed(ServletContextEvent arg0) {
}
//项目启动时初始化执行的方法
@Override
public void contextInitialized(ServletContextEvent arg0) {
WebSocketImpl.DEBUG = false;
int port = 8081;
WsServer wsServer = new WsServer(port);
wsServer.start();
/*new Thread(new Runnable() {
@Override
public void run() {
while (true) {
try {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
String msg = simpleDateFormat.format(new Date());
System.out.println(msg);
Collection<String> allOnlineUser = WsPool.getAllOnlineUser();
System.out.println(allOnlineUser.size());
if (allOnlineUser.size() > 0) {
WsPool.sendMessageToAll(msg);
}
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();*/
}
}
//连接池
public class WsPool {
private static final Map<WebSocket, String> wsUserMap = new HashMap<WebSocket, String>();
//单发
public static WebSocket test(String name){
Set<WebSocket> keySet = wsUserMap.keySet();
for(WebSocket socket : keySet){
String string = wsUserMap.get(socket);
if(name.equals(string)){
return socket;
}
}
return null;
}
//群发
public static List<WebSocket> massTexting(String name){
List<WebSocket> fbList = new ArrayList<WebSocket>();
Set<WebSocket> keySet = wsUserMap.keySet();
for(WebSocket socket : keySet){
String string = wsUserMap.get(socket);
if(name.equals(string)){
fbList.add(socket);
}
}
return fbList;
}
/**
* 通过webSocket连接获取用户
* @param conn
* @return
*/
public static String getUserByWs(WebSocket conn) {
return wsUserMap.get(conn);
}
/**
* 根据用户获取webSocket对象
* 此处应返回的是一个websocket集合,但是在close方法中将失效的连接移除,
* 所以保证返回的是一个
* @param userName
* @return
*/
public static WebSocket getWsByUser(String userName) {
Set<WebSocket> webSockets = wsUserMap.keySet();
synchronized (webSockets){
for (WebSocket conn : webSockets) {
if (conn.equals(userName)) {
return conn;
}
}
}
return null;
}
/**
* 获取所有的在线用户
* @return
*/
public static Collection<String> getAllOnlineUser() {
List<String> users = new ArrayList<String>();
Collection<String> values = wsUserMap.values();
for (String value : values) {
users.add(value);
}
return users;
}
/**
* 向连接池中添加连接
* @param userName
* @param conn
*/
public static void addUser(String userName, WebSocket conn) {
wsUserMap.put(conn, userName);
}
/**
* 移除池中的特定连接
* @param conn
* @return
*/
public static boolean removeUser(WebSocket conn) {
if (wsUserMap.containsKey(conn)) {
wsUserMap.remove(conn);
return true;
}else {
return false;
}
}
/**
* 向一特定的用户发送消息
* @param msg
* @param conn
*/
public static void sendMessageToUser(String msg, WebSocket conn) {
if (null != conn && null != wsUserMap.get(conn)) {
conn.send(msg);
}
}
/**
* 向所用的用户发送消息
* @param msg
*/
public static void sendMessageToAll(String msg) {
Set<WebSocket> webSockets = wsUserMap.keySet();
synchronized (webSockets) {
for (WebSocket conn : webSockets) {
String user = wsUserMap.get(conn);
if (null != user) {
conn.send(msg);
}
}
}
}
}
public class WsServer extends WebSocketServer{
public WsServer(int port) {
super(new InetSocketAddress(port));
}
public WsServer(InetSocketAddress address) {
super(address);
}
/**
* 连接时触发
*/
@Override
public void onOpen(WebSocket webSocket, ClientHandshake clientHandshake) {
//LOGGER.debug("connected~~~~~~");
System.out.println("connected~~~~~~");
}
/**
* 断开连接时触发的方法
*/
@Override
public void onClose(WebSocket webSocket, int code, String reason, boolean remote) {
//断开连接时,移除连接
userLeave(webSocket);
System.out.println(reason);
}
@Override
public void onMessage(WebSocket webSocket, String msg) {
System.out.println(msg);//获取用户名
userJoin(webSocket, msg);
webSocket.send(msg);
}
/**
* 错误时触发
*/
@Override
public void onError(WebSocket webSocket, Exception e) {
System.out.println("on error");
e.printStackTrace();
}
/**
* 将连接从池中移除
* @param conn
*/
private void userLeave(WebSocket conn) {
WsPool.removeUser(conn);
}
/**
* 向池中添加连接
* @param conn
* @param userName
*/
private void userJoin(WebSocket conn, String userName) {
WsPool.addUser(userName, conn);
}
}
//在service层处理完业务逻辑之后在控制层调用连接池的方法
WebSocket webSocket = WsPool.test(us.getuId());
if(webSocket!=null){
webSocket.send(us.getuId());
}
本人已测可用!