1.封装websocket公用类
function websocket(){
this.socket = null;
this.code = new Date().getTime()+""+Math.floor(Math.random() * ( 1000 + 1));
this.options = {
url:getWsPath,
dataType:"json",
onmessage:function(msg){
return msg;
},
onopen:function(msg){
return msg;
},
onclose:function(msg){
return msg;
},
onerror:function(msg){
return msg;
}
};
}
websocket.prototype.init = function(options){
//判断当前浏览器是否支持WebSocket
if (!window.WebSocket) {
window.WebSocket = window.MozWebSocket;
}
if(window.WebSocket){
this.socket = new WebSocket(getWsPath()+"/"+this.code);
}else{
$CommonUI.alert('当前浏览器 不支持 websocket');
return;
}
//如果存在配置信息
if(options){
//初始化默认属性
options = $.extend(this.options,options);
//连接发生错误的回调方法
this.socket.onerror = function (event) {
options.onerror(event.data);
};
//连接成功建立的回调方法
this.socket.onopen = function (event) {
options.onopen(event.data);
}
//接收到消息的回调方法
this.socket.onmessage = function (event) {
//当返回配置为json的时候则配置为json
if(options.dataType=="json"){
options.onmessage($.parseJSON(event.data));
}else{
options.onmessage(event.data);
}
}
//连接关闭的回调方法
this.socket.onclose = function (event) {
options.onclose(event.data);
}
//监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。
window.onbeforeunload = function () {
if(this.socket){
this.socket.close();
}
}
}
}
//发送消息
websocket.prototype.send = function(msg){
if (!window.WebSocket) { return; }
if (this.socket.readyState == WebSocket.OPEN) {
if(typeof msg == "string"){
this.socket.send(msg);
}else{
msg["code"] = this.code;
msg.paramsIn = JSON.stringify(msg.paramsIn);
this.socket.send(JSON.stringify(msg));
}
} else {
$CommonUI.alert("连接没有打开!");
}
};
//获取websocket路径
function getWsPath(){
var host = window.location.host; //主机IP:port
var path = window.document.location.pathname;//端口后的路径
var projectName = path.substring(0,path.substr(1).indexOf("/")+1);//项目名
return "ws://"+host+projectName+"/websocket";
}
2.前端调用websocket
var websocket = new websocket();
websocket.init({
onmessage:function(msg){
$CommonUI.getProgressBar('#importProgress').progressbar('setValue', msg);
}
})
3.后端websocket的支持
package com.dhcc.isccore.common.websocket;
import java.io.IOException;
import java.util.concurrent.ConcurrentHashMap;
import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import com.dhcc.isccore.dto.websocket.WebsocketDto;
@ServerEndpoint("/websocket/{code}")
public class WebSocketListen {
//用于记录接入的websocket连接
private static ConcurrentHashMap<String,WebsocketDto> websocketMap = new ConcurrentHashMap<String,WebsocketDto>();
/**
* 连接建立成功调用的方法
*
* @param session
* 可选的参数。session为与某个客户端的连接会话,需要通过它来给客户端发送数据
*/
@OnOpen
public void onOpen(@PathParam("code") String code,Session session) {
WebsocketDto websocketDto = new WebsocketDto();
websocketDto.setCode(code);
websocketDto.setSession(session);
websocketMap.put(code, websocketDto);
}
/**
* 连接关闭调用的方法
*/
@OnClose
public void onClose(@PathParam("code") String code) {
websocketMap.remove(code);
}
/**
* 收到客户端消息后调用的方法
*
* @param message
* 客户端发送过来的消息
* @param session
* 可选的参数
*/
@OnMessage
public void onMessage(String message, Session session) {
}
/**
* 发生错误时调用
*
* @param session
* @param error
*/
@OnError
public void onError(Session session, Throwable error) {
error.printStackTrace();
}
//发送消息
public static void sendMessage(String code,String message) throws IOException {
Session session = websocketMap.get(code).getSession();
session.getBasicRemote().sendText(message);
}
public static ConcurrentHashMap<String, WebsocketDto> getWebsocketMap() {
return websocketMap;
}
public static void setWebsocketMap(ConcurrentHashMap<String, WebsocketDto> websocketMap) {
WebSocketListen.websocketMap = websocketMap;
}
}
2.websocket可以通过@PathParam(参数名)获取到请求传递的参数;
3.参数名实在@ServerEndpoint中通过{参数名}定义的。
这里使用传入的code唯一标识一次请求,其他地方可根据该code获取到当前session并发送消息到前台。
3.参数名实在@ServerEndpoint中通过{参数名}定义的。
这里使用传入的code唯一标识一次请求,其他地方可根据该code获取到当前session并发送消息到前台。
4.Websocket定义
package com.dhcc.isccore.dto.websocket;
import javax.websocket.Session;
public class WebsocketDto{
/**
* 字段: 字段名称
* @Fields serialVersionUID : TODO
*/
private String code; //客户端传入的唯一标识
private int totalNum; //总数量
private int handleNum = 0; //当前操作数量
private Session session; //当前websocket的session
public int getTotalNum() {
return totalNum;
}
public void setTotalNum(int totalNum) {
this.totalNum = totalNum;
}
public int getHandleNum() {
return handleNum;
}
public void setHandleNum(int handleNum) {
this.handleNum = handleNum;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public Session getSession() {
return session;
}
public void setSession(Session session) {
this.session = session;
}
}
5.后端返回进度
<pre name="code" class="java">//websocket开始
WebsocketDto webSocketDto = WebSocketListen.getWebsocketMap().get(code);
int handleNum = webSocketDto.getHandleNum();
handleNum = handleNum + i;
String progress = (int)(handleNum*100/webSocketDto.getTotalNum())+"";
WebSocketListen.sendMessage(code, progress);
//websocket结束
这里i是本次插入数据库的数据量
6.进度条设计原理
a.初始化定义一个长连接的websocket,用于更新进度。
b.当导入的时候读取当前导入的总条数。
c.当每插入总数的1%数据时发送一个进度回前端,前端渲染该进度,直到100%完成。
注意:每一次数据传输websocket都会新建一个通道,发送一次ws请求,在请求完成后自动关闭该websocket连接。