websocket+springboot+vue+element ui完成数据表格的数据实时更新(指定秒数更新)

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;

直接替换掉旧的数据而后代码就不用有大改动

相关文章
相关标签/搜索