1. 程式人生 > >WebSocket實現前臺實時顯示資料庫資料

WebSocket實現前臺實時顯示資料庫資料

業務邏輯:
在瀏覽器和伺服器之間建立WebSocket雙工連線,啟動一個執行緒,設定私有變數資料修改時間,迴圈讀取資料庫實時表中某個感測器的資料修改時間,與私有變數進行對比,如果相同則不做任何改動,若不同,則把查詢到的時間賦值給私有變數,同時向瀏覽器傳送推送訊息,前端通過ajax傳送請求更新資料。
新增依賴:
用之前 需查詢依賴版本是否與spring版本相容
WebSocket依賴:

 <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>5.1.38</version>
    </dependency>
    <dependency>
      <groupId>javax</groupId>
      <artifactId>javaee-api</artifactId>
      <version>7.0</version>
      <scope>provided</scope>
    </dependency>

日期比較依賴:

 <dependency>
            <groupId>joda-time</groupId>
            <artifactId>joda-time</artifactId>
            <version>2.9.2</version>
        </dependency>

前端功能程式碼及作用:

var websocket = null;
    //判斷當前瀏覽器是否支援WebSocket
    if ('WebSocket' in window) {
        //建立連線,這裡的/websocket ,是Servlet中註解中的那個值
        websocket = new WebSocket("ws://localhost:8080/專案名/websocket");
    }
    else {
        alert('當前瀏覽器不支援WebSocket');
    }
    //連線發生錯誤的回撥方法
    websocket.onerror = function () {
        //發生連線錯誤的處理程式碼
    };
    //連線成功建立的回撥方法
    websocket.onopen = function () {
        //連線成功的處理程式碼
    }
    //接收到訊息的回撥方法
    websocket.onmessage = function (event) {
        console.log(event.data);
        if(event.data=="1"){
            //接收到訊息的處理程式碼
        }
    }
    //連線關閉的回撥方法
    websocket.onclose = function () {
        //連線關閉時的處理程式碼
    }
    //監聽視窗關閉事件,當視窗關閉時,主動去關閉WebSocket連線,防止連線還沒斷開就關閉視窗,server端會拋異常。
    window.onbeforeunload = function () {
        closeWebSocket();
    }
    //關閉WebSocket連線
    function closeWebSocket() {
        websocket.close();
    }

後端功能程式碼及作用:

//在相對路徑中釋出端點websocket,註解中的路徑要與前端程式碼對應“ websocket = new WebSocket("ws://localhost:8080/專案名/websocket");”
@ServerEndpoint("/websocket")
public class WebSocketServlet {
    MyThread thread1=new MyThread();
    Thread thread=new Thread(thread1);
    //用來存放每個客戶端對應的MyWebSocket物件。
    private static CopyOnWriteArraySet<WebSocketServlet> webSocketSet = new CopyOnWriteArraySet<WebSocketServlet>();
    private  javax.websocket.Session session=null;
    //開啟連線
    @OnOpen
    public void onOpen(Session session) throws IOException{
        this.session=session;
        webSocketSet.add(this); 
        System.out.println(webSocketSet);
        //開啟一個執行緒對資料庫中的資料進行輪詢
        thread.start();    
    }
    //關閉連線
    @OnClose
    public void onClose(){
        thread1.stopMe();
        webSocketSet.remove(this);
    }
    //給伺服器傳送訊息告知資料庫發生變化
    @OnMessage
    public void onMessage(int count) {    
        System.out.println("發生變化"+count);
        try {
            sendMessage();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
   //出錯的操作
    @OnError
    public void onError(Throwable error){
        System.out.println(error);
        error.printStackTrace();
    }
    
    /**
     * 這個方法與上面幾個方法不一樣。沒有用註解,是根據自己需要新增的方法。
     * @throws IOException
     * 傳送自定義訊號,“1”表示告訴前臺,資料庫發生改變了,需要重新整理
     */
    public void sendMessage() throws IOException{
        //群發訊息
        for(WebSocketServlet item: webSocketSet){
            item.session.getBasicRemote().sendText("1");
        }
    }
}

定義執行緒:

public class MyThread implements Runnable{
    private Date sum;
    private  Date new_sum;
    private boolean stopMe = true;  
    public void stopMe() {  
        stopMe = false;  
    }  
    public void run()  {
    //查詢資料更新時間
        UrlDao urlDao=new UrlDao();
        new_sum=urlDao.selectTime();
        WebSocketServlet wbs=new WebSocketServlet();
        while(stopMe){
            new_sum=urlDao.selectCount();
            if(sameDate(sum, new_sum )){
                System.out.println("change");
                sum=new_sum;
                wbs.onMessage(sum);
            }
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
    public static Boolean sameDate(Date dt1 , Date dt2 ){
	LocalDate ld1 = new LocalDate(new DateTime(dt1));
	LocalDate ld2 = new LocalDate(new DateTime(dt2));
	return ld1.equals( ld2 );
    }
}