java部分:vue
import org.springframework.stereotype.Component; import javax.websocket.OnClose; import javax.websocket.OnMessage; import javax.websocket.OnOpen; import javax.websocket.Session; import javax.websocket.server.PathParam; import javax.websocket.server.ServerEndpoint; import java.util.HashMap; import java.util.Map; import java.util.concurrent.CopyOnWriteArraySet; /** * @description:TODO * @author:xing.Li * @date:2019/8/26 10:02 */ @Component @ServerEndpoint("/websocket/{code}") //此註解至關於設置訪問URL public class WebSocket { private Session session; private static CopyOnWriteArraySet<WebSocket> webSockets =new CopyOnWriteArraySet<>(); private static Map<String,Session> sessionPool = new HashMap<String,Session>(); @OnOpen public void onOpen(Session session, @PathParam(value="code")String code) { this.session = session; webSockets.add(this); sessionPool.put(code, session); Constants.WEBSOCKET = true;//定義常量 是否開啓websocket鏈接 System.out.println("【websocket消息】有新的鏈接,總數爲:"+webSockets.size()); } @OnClose public void onClose() { webSockets.remove(this); Constants.WEBSOCKET = false; System.out.println("【websocket消息】鏈接斷開,總數爲:"+webSockets.size()); } @OnMessage public void onMessage(String message) { System.out.println("【websocket消息】收到客戶端消息:"+message); } // 此爲廣播消息 public void sendAllMessage(String message) { for(WebSocket webSocket : webSockets) { System.out.println("【websocket消息】廣播消息:"+message); try { webSocket.session.getAsyncRemote().sendText(message); } catch (Exception e) { e.printStackTrace(); } } } // 此爲單點消息 public void sendOneMessage(String code, String message) { Session session = sessionPool.get(code); /*在發送數據以前先確認 session是否已經打開 使用session.isOpen() 爲true 則發送消息 * 否則會報錯:The WebSocket session [0] has been closed and no method (apart from close()) may be called on a closed session */ if (session != null && session.isOpen()) { try { session.getAsyncRemote().sendText(message); } catch (Exception e) { e.printStackTrace(); } } }
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.socket.server.standard.ServerEndpointExporter; /** * @description:TODO * @author:xing.Li * @date:2019/8/25 17:44 */ @Configuration public class WebSocketConfig {//打包部署到tomcat中須要刪除此文件 /** * 注入ServerEndpointExporter, * 這個bean會自動註冊使用了@ServerEndpoint註解聲明的Websocket endpoint */ @Bean public ServerEndpointExporter serverEndpointExporter() { return new ServerEndpointExporter(); } }
此處爲springboot自動執行代碼 @Scheduled(fixedRate = 5 * 1000)//多少秒執行一次 @Async//異步執行 public void computerTableOnline() { if (Constants.WEBSOCKET) { R r = computerListService.queryList(Constants.COMPUTER_GROUP); if ("0".equals(r.get("code").toString()) && r.get("ComputerList") != null) { List<ComputerList> computerList = (List<ComputerList>) r.get("ComputerList"); String str = JSON.toJSONString(computerList); // List轉json webSocket.sendOneMessage("computer", str);//websocket推送數據 } } }
最終要的固然是jar包了java
<!--websocket--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-websocket</artifactId> <version>1.5.3.RELEASE</version> <type>pom</type> </dependency>
js部分:web
data(){} 中spring
created() { // 頁面建立生命週期函數 this.initWebSocket() }, destroyed: function () { // 離開頁面生命週期函數 this.websocketclose(); },
methods中json
initWebSocket: function () { // WebSocket與普通的請求所用協議有所不一樣,ws等同於http,wss等同於https key你自定義的key var host = window.location.host; this.websock = new WebSocket("ws://" + host + "/websocket/key"); this.websock.onopen = this.websocketonopen; this.websock.onerror = this.websocketonerror; this.websock.onmessage = this.websocketonmessage; this.websock.onclose = this.websocketclose; }, websocketonopen: function () { console.log("WebSocket鏈接成功"); console.log("WebSocket正在發送實時數據......."); }, websocketonerror: function (e) { console.log("WebSocket鏈接發生錯誤"); }, websocketonmessage: function (e) { JSON.parse(e.data); //這個是收到後端主動推送的值 } }, websocketclose: function (e) { console.log("WebSocket鏈接斷開"); }
實現思路:經過websocket長鏈接從後端主動推送數據,利用vue的雙向綁定實現數據同步後端
注:由於數據的改變也會刷新表格上覆選框的選中狀態,本人思路爲,element ui中有選中複選框的值得集合,判斷複選框裏面有沒有值,有值的話就是在操做數據,這時中止websocket的鏈接,操做完成後,複選框值所在集合也就沒有值了,這時再開啓websocket鏈接,這樣也有問題,可是算是實現了吧。。。。緩存
在此記錄方便之後觀看tomcat
固然上面的部分代碼是忘記那位博主的了,時間過久找不到連接了,就不放原文連接了springboot
----------------------------------------------------------------------------------------------------------------------------------------------------------------websocket
更新:
最近打包發現了個問題,websocket放在tomcat中運行會報錯,具體緣由忘了。。好像是說在tomcat8以上會替代spring管理bean因此刪除WebSocketConfig這個配置bean的文件就能夠正常運行了
----------------------------------------------------------------------------------------------------------------------------------------------------------------
更新:
需求又變了,說是讓選中也能夠進行實時刷新,又網上找了下,發現大佬寫法:http://www.javashuo.com/article/p-risyvwhh-dn.html
其實element ui 官網就有寫法,仍是要多看看文檔-0.0-
官網是說
代碼爲
<!-- stripe--啓用馬紋線 border--啓用邊框 highlight-current-row--啓用單選 sortable--啓用排序--> <el-table ref="multipleTable" :data="tables.slice((currentPage-1)*pagesize,currentPage*pagesize)" stripe border highlight-current-row tooltip-effect="dark" style="width: 100%;font-size: 13px" :cell-style="{padding:'0px'}" @row-click="rowClick" :row-style="rowStyle" :row-class-name="rowClassName" @selection-change="handleSelectionChange" :row-key="getRowKeys"> <el-table-column sortable :reserve-selection="true" type="selection" width="55"></el-table-column> <el-table-column sortable prop="test" label="test" show-overflow-tooltip></el-table-column> <el-table-column sortable prop="test" label="test" show-overflow-tooltip></el-table-column> <el-table-column sortable prop="test" label="test" show-overflow-tooltip></el-table-column> <el-table-column sortable prop="test" label="testtest" show-overflow-tooltip></el-table-column> <el-table-column sortable prop="test" label="test" show-overflow-tooltip></el-table-column> </el-table>
須要加入代碼已加粗加下劃線 這個不能直接reserve-selection="true"這樣寫
會報錯Invalid prop: type check failed for prop "reserveSelection". Expected Boolean, got String with value "true".
錯誤大體爲須要一個boolean類型的參數,可是傳入爲String類型的須要加上 :reserve-selection="true"
還有要返回一個當前行標識
// 指定返回的行 getRowKeys(row){ return row.id; },
----------------------------------------------------------------------------------------------------------------------------------------------------------------
再更新,忽然發現一個問題,由於element ui 中
@selection-change="handleSelectionChange"
是獲取複選框選中的行的全部值,當我選中時就會緩存進頁面聲明的集合或者對象中,若是這時websocket更新了tabledata中的值,這時緩存的值就成了舊數據,這樣確定是不行的,那怎麼辦,看到這個大佬的博客,先貼出來 https://blog.csdn.net/qq_36537108/article/details/89261394 上面是這樣說的 利用vue的ref屬性和element中的 複選框屬性
type="selection"
在按鈕點擊的時候獲取當前複選框選中的值,這時點擊按鈕時就是當前的新數據這樣就避免了出現舊數據
懶得打,複製過來吧,注意這個selection就是複選框呀
而後選中的是這樣寫的
this.$refs.multipleTable.selection
個人代碼是這個邏輯,由於只有一個頁面會用到實時刷新,因此其餘頁面就不用改了,而後就是在點擊事件的開始就讓
下面這個就是element ui 官網給出的選中複選框的那個@selection-change="handleSelectionChange"
注意這個 self 是 var self = this;
handleSelectionChange(val) { this.multipleSelection = val },
self.multipleSelection = this.$refs.multipleTable.selection;
直接替換掉舊的數據而後代碼就不用有大改動