websocket导入进度条

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;
	}
}

注意:1.websocket只支持get请求;
           2.websocket可以通过@PathParam(参数名)获取到请求传递的参数;
           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连接。


  • 3
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值