spring+springMVC+webSocket实现给指定用户推送消息(二)

本片文章实现的功能是后端程序给指定的用户通过webSocket推送消息。根据前端用户登录时给后台传递用户ID,然后在后台将用户ID和对应的webSocketSession存储起来,用于推送消息时使用。

一、引入sockjs-1.0.3.js

二、自己封装的WebSocket组件


/**
 * 自己封装的WebSocket组件
 * @param factory
 * @returns
 */
(function(factory) {
	// 启用严格模式
	"use strict";
	// 环境探测语句:如果采用了AMD异步加载模块的方式
	if (typeof define === 'function' && define.amd) {
		// 启用AMD模块化
		define([ 'jquery' ], factory);
	} else if (typeof exports === 'object' && typeof require === 'function') {
		// 如果采用了CommonJS的模块加载方式,启用CommonJS模块化
		factory(require('jquery'));
	} else {
		// 原生JS调用工厂模式
		factory(jQuery);
	}
}
(function($, undefined) {
	// 启用严格模式
	"use strict";

	var DIYWebSocket = function(opt) {

		this.options = $.extend(true, {}, DIYWebSocket.defaultOptions, opt);

		// 原生支持websocket的地址
		this.options.wsUrl = this.options.webSocketProtocol
				+ this.options.websocketServiceDomain
				+ "/webSocketService"
				+ (this.options.clientID ? "?clientID=" + this.options.clientID : "");

		// 不支持websocket使用sockjs连接的地址
		this.options.wsSockjsUrl = this.options.webSocketJSProtocol
				+ this.options.websocketServiceDomain
				+ "/webSocketService/sockjs"
				+ (this.options.clientID ? "?clientID=" + this.options.clientID : "");

		this.ws = this.createWebSocket();
	};

	/**
	 * 默认配置
	 */
	DIYWebSocket.defaultOptions = {
		// webSocket客户端ID
		clientID : "",
		// webSocket协议
		webSocketProtocol : "",
		// 不支持websocket使用sockjs连接的协议
		webSocketJSProtocol : "",
		// webSocket服务域名
		websocketServiceDomain : "",
		// 未收到消息多少秒后,给后端服务发送消息,(心跳间隔默认20秒)
		timeout : 40000,
		// 前端发送消息后,未收到消息超时时间,默认60000毫秒
		serverTimeout : 60000,
		// 连接间隔时间
		intervalTime : 6000,
		// 收到消息回调函数
		onMessageCallBack : function(msg) {
		},
		// 收到消息回调函数
		errorCallBack : function() {
		}
	}

	DIYWebSocket.prototype.createWebSocket = function() {
		try {
			var ws;
			if ('WebSocket' in window) {
				ws = new WebSocket(this.options.wsUrl);
			} else {
				// sockjs是javascript库,提供了服务器和浏览器间的双向通信,优先使用websocket通信,当浏览器不支持时,则自动改为轮询与服务器通信。
				ws = new SockJS(this.options.wsSockjsUrl);
			}
			this.initEventHandle(ws);
			return ws;
		} catch (e) {
			this.reconnect();
			throw e;
		}
	};

	DIYWebSocket.prototype.initEventHandle = function(ws) {
		var obj = this;
		ws.onclose = function() {
			console.info("连接关闭onclose");
			obj.closeWebSocket();
		};
		ws.onerror = function() {
			console.info("传输异常");
			obj.closeWebSocket();
			obj.options.errorCallBack.call(this);
		};
		ws.onopen = function() {
			// 心跳检测重置
			obj.heartCheck();
		};
		ws.onmessage = function(event) {
			var json;
			try {
				json = eval('(' + event.data + ')');
			} catch (e) {
				json = event.data;
			}
			console.info("收到的消息" + json);
			obj.options.onMessageCallBack.call(this, json);
			// 拿到任何消息都说明当前连接是正常的,心跳检测重置
			obj.heartCheck();
		};
	};

	/**
	 * 连接端webSocket服务
	 */
	DIYWebSocket.prototype.reconnect = function() {
		var obj = this;

		// 检测是否已连接
		if (obj.options.lockReconnect) {
			return;
		}

		obj.options.lockReconnect = true;

		// 没连接上会一直重连
		setTimeout(function() {
			// 连接服务端
			obj.createWebSocket();
			console.info("重连接websocket");
			obj.options.lockReconnect = false;
		}, obj.options.intervalTime);
	};

	/**
	 * 给后台服务发送消息
	 */
	DIYWebSocket.prototype.sendMessage = function(msg) {
		var obj = this;
		obj.ws.send(msg);
	};

	/**
	 * 心跳检测
	 */
	DIYWebSocket.prototype.heartCheck = function() {
		var obj = this;
		obj.heartReset();
		obj.heartStart();
	};

	/**
	 * 开始心跳检测
	 */
	DIYWebSocket.prototype.heartStart = function() {
		var obj = this;
		obj.timeoutID = setTimeout(function() {
			// 发送一个消息,后端收到后,返回消息,onmessage拿到返回的消息就说明连接正常
			obj.sendMessage("HeartBeat");
			console.info("客户端发送心跳:" + new Date());
			
			// 如果超过一定时间还没收到消息,说明后端主动断开了
			obj.serverTimeoutID = setTimeout(function() {
				// 关闭ws.close()
				obj.closeWebSocket();
			}, obj.options.serverTimeout);
		}, obj.options.timeout);
	};

	/**
	 * 重置心跳检测
	 */
	DIYWebSocket.prototype.heartReset = function() {
		console.info("重置心跳检测");
		var obj = this;
		clearTimeout(obj.timeoutID);
		clearTimeout(obj.serverTimeoutID);
	};

	/**
	 * 关闭webSocket
	 */
	DIYWebSocket.prototype.closeWebSocket = function() {
		console.info("关闭webSocket");
		var obj = this;
		obj.ws.close();
	};

	/**
	 * 使用jquery方式对外提供调用
	 */
	$.extend({
		bindWebSocket : function(options) {
			return new DIYWebSocket(options);
		}
	})

}));

三、页面使用

//websocket实例
var ws = $.bindWebSocket({
	// webSocket客户端ID
	clientID : "${loginPersonID}",
	// webSocket协议,当项目使用https协议访问时,webSocket使用wss协议访问
	webSocketProtocol : "ws://",
	// 不支持websocket使用sockjs连接的协议,跟随项目协议访问方式一致
	webSocketJSProtocol : "http://",
	// webSocket服务域名(有端口号时,需要携带端口号)
	websocketServiceDomain : "${websocketServiceDomain}",
	// 收到消息回调函数
	onMessageCallBack : function(msg) {
		//处理服务器返回的消息
	}
});

 

你可能感兴趣的:(webSocket)