websocket實例(顯示文件導入處理進度)

大批量數據導入時,須要即時顯示對文件的處理進度。考慮ajax輪詢太浪費資源,使用websocket實現。html

項目使用Spring MVC(3.1),與websocket結合要求版本4.0以上。因此沒有使用Spring提供的websocket。java

1.依賴Tomcat 7 或者 J2EE 7web

maven導入:ajax

<!-- webscoket start -->
        <dependency>
            <groupId>org.apache.tomcat</groupId>
            <artifactId>tomcat-websocket-api</artifactId>
            <version>7.0.47</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>javax</groupId>
            <artifactId>javaee-api</artifactId>
            <version>7.0</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.java-websocket</groupId>
            <artifactId>Java-WebSocket</artifactId>
            <version>1.3.0</version>
        </dependency>
<!-- webscoket end -->

2.服務端apache

  工具類,存儲惟一key和鏈接api

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import javax.websocket.Session;

public class WebsocketSessionUtils {

    public static Map<String, Session> clients = new ConcurrentHashMap<>();

    public static void put(String batchKey, Session session) {
        clients.put(batchKey, session);
    }

    public static Session get(String batchKey) {
        return clients.get(batchKey);
    }

    public static void remove(String batchKey) {
        clients.remove(batchKey);
    }

    public static boolean hasConnection(String batchKey) {
        return clients.containsKey(batchKey);
    }

}

  websocket處理類,不要添加業務邏輯tomcat

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

@ServerEndpoint("/websocket.ws/{batchKey}")
public class WebsocketEndPoint {
    private static Log log = LogFactory.getLog(WebsocketEndPoint.class);

    @OnOpen
    public void onOpen(@PathParam("batchKey") String batchKey, Session session) {
        log.info("Websocket Start Connecting:" + batchKey);
        WebsocketSessionUtils.put(batchKey, session);
    }

    @OnMessage
    public String onMessage(@PathParam("batchKey") String batchKey,
            String message) {
        return "Got your message (" + message + ").Thanks !";
    }

    @OnError
    public void onError(@PathParam("batchKey") String batchKey,
            Throwable throwable, Session session) {
        log.info("Websocket Connection Exception:" + batchKey);
        log.info(throwable.getMessage(), throwable);
        WebsocketSessionUtils.remove(batchKey);
    }

    @OnClose
    public void onClose(@PathParam("batchKey") String batchKey, Session session) {
        log.info("Websocket Close Connection:" + batchKey);
        WebsocketSessionUtils.remove(batchKey);
    }

}

3.客戶端websocket

  使用js閉包封裝websocket,導入websocket.jsjava-web

var myWebSocket = (function() {
    var mySocket = {};
    mySocket.tryTime = 0;
    mySocket.webSocketUrl = null;
    mySocket.batchKey = null;
    mySocket.webSocket = null;
    mySocket.initSocket = function() {
        if (!window.WebSocket) {
            // alert("Your browsers don't support websocket.");
            return false;
        }
        mySocket.webSocket = new WebSocket(mySocket.webSocketUrl + mySocket.batchKey);
        mySocket.webSocket.onmessage = function(msg) {
            console.log(msg);
        };
        mySocket.webSocket.onerror = function(event) {
            console.log(event);
        };
        mySocket.webSocket.onopen = function(event) {
            console.log(event);
        };
        mySocket.webSocket.onclose = function() {
            if (mySocket.tryTime < 10) {
                setTimeout(function() {
                    webSocket = null;
                    mySocket.tryTime++;
                    mySocket.initSocket();
                }, 500);
            } else {
                mySocket.tryTime = 0;
            }
        };
    };
    mySocket.closeSocket = function() {
        if (mySocket.webSocket) {
            mySocket.webSocket.close();
        }
    };
    return mySocket;
})();

  在ajax執行時啓動websocket,使用timestamp做爲惟一key。session

var commissionWebsocketUrl = "ws://${remote_websocket}/commission/websocket.ws/";

 

        var timestamp=new Date().getTime();
        $.ajax({
            type : "POST",
            url : trialUrl+"?batchKey="+timestamp,
            data : $("#batchUploadForm").serialize(),
            dataType : "html",
            beforeSend: function(xhr) {
                var countDiv = $('#loading #countDiv');
                if(countDiv.length==0){
                    countDiv =$("<div id='countDiv'></span>");
                    $('#loading').append(countDiv);
                }
                $('#loading').show();
                myWebSocket.webSocketUrl = commissionWebsocketUrl;
                myWebSocket.batchKey = timestamp;
                myWebSocket.initSocket();
                myWebSocket.webSocket.onmessage = function(msg) {
                    countDiv.html("mTusker is processing date,Please wait... "+msg.data);
                };
            },
            complete: function(){
                $('#loading').hide();
                myWebSocket.closeSocket();
            },
            success : function(data) {
                $("#trialInfoPopup").html(data);
                mydialog = $("#trialInfoPopup").dialog({
                    position: ['center',100] ,width : 1400,height: 600,
                    modal : true,
                    title : "Batch Upload Trial"
                });
            }
        });

  java項目做爲客戶端

import java.io.IOException;

import javax.websocket.ClientEndpoint;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;

@ClientEndpoint
public class WebsocketClient {
    @OnOpen
    public void onOpen(Session session) {
        System.out.println("Connected to endpoint:" + session.getBasicRemote());
        try {
            session.getBasicRemote().sendText("Hello");
        } catch (IOException ex) {
        }
    }

    @OnMessage
    public void onMessage(String message) {
        System.out.println(message);
    }

    @OnError
    public void onError(Throwable t) {
        t.printStackTrace();
    }
}
import java.io.IOException;
import java.net.URI;

import javax.websocket.ContainerProvider;
import javax.websocket.DeploymentException;
import javax.websocket.Session;
import javax.websocket.WebSocketContainer;

public class WebsocketApp {
    private static String webUrl = "localhost";
    
    public static void send(String batchKey, String message) {
        WebSocketContainer container = ContainerProvider.getWebSocketContainer();
        String uri = "ws://"+webUrl+"/websocket.ws/" + batchKey;
        System.out.println("Connecting to" + uri);
        try {
            Session session = WebsocketSessionUtils.get(batchKey);
            if (session == null) {
                session = container.connectToServer(WebsocketClient.class, URI.create(uri));
                WebsocketSessionUtils.put(batchKey, session);
            }
            session.getBasicRemote().sendText(message);
        } catch (DeploymentException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static String getWebUrl() {
        return webUrl;
    }

    public static void setWebUrl(String webUrl) {
        WebsocketApp.webUrl = webUrl;
    }
    
    
}

  把導入文件處理部分,當作java項目客戶端,處理過程當中調用websocket

                int num = 0;
                for(Map<String,String> rowInfo : rows){    
                    WebsocketApp.send(batchKey, num++ + "/" + rows.size());
                    ......       
                }

  由此實如今處理文件過程當中即時發送處理進度。

注: 當使用https時須要改成

var commissionWebsocketUrl = "wss://${remote_websocket}/commission/websocket.ws/";
相關文章
相關標籤/搜索