WebSocket实现数据库更新前台实时显示

通过一个小实例来实现数据库更新后,推送消息给前台,让前台进行相应操作。

需求

数据库更新之后服务器推送消息给前台,让前台做操作。(数据库的数据不是由服务器写入的)

实现的话说到底都是用轮询,因为数据库的数据不是通过后台插入更新的,所以无论用什么办法,都需要循环地去读取数据库中的信息或者数据库的日志文件。区别就是,到底是前台轮询,还是后台轮询了。

如果使用前台轮询,就是前台定期给后台发送请求,来对数据进行更新,用setInterval()就能实现。你F12看Network就能看到一会就有几十甚至几百个请求。。因为我也是第一次实现这样的功能,虽然对性能这方面没有什么研究,但是看到短时间内这么多请求还是觉得心慌慌。

所以想到了使用后台轮询,后台轮询的好处就是,前台不用一直发送请求给后台,而是等到后台发现数据更新了再提醒前台重新请求数据。这就需要用到WebSocket。

我们平常使用的http连接,都是只能客户端向服务器发送请求。

而WebSocket的最大特点就是,服务器可以主动向客户端推送信息,客户端也可以主动向服务器发送信息,是真正的双向平等对话,属于服务器推送技术的一种。

在查询资料的时候也查到可以用数据库的存储过程来实现,在存储数据的时候,调用Java的程序来进行通知。(因为还有一些处理方面的问题没有去实现)

环境

Server version : Apache Tomcat/7.0.69
Java version: 1.7.0_80

需要引入的jar包:tomcat自带的tomcat7-websocket.jarwebsocket-api.jar,这两个jar包都在tomcat安装目录的lib文件夹下。

需要注意的是:tomcat需要7.0.47版本以上才支持JSR-356,具体文档可以查看

思路

在建立连接的时候开启一个线程对数据库中的数据进行轮询,如果查询到数据变化了,就发消息给WebSocket实现类,实现类接收到消息后,推送消息给连接着的用户。

(如果数据是通过后台添加的,就不用这么麻烦了,直接在添加数据的操作类中发送消息给WebSocket实现类就好了)

客户端代码

这部分比较简单,就是通过url来建立WebSocket连接,协议名称ws也就是WebSocket。在websocket.onmessage()方法中对接收到的消息进行处理,你可以做输出也可以更新页面等等。

    var websocket = null;
    //判断当前浏览器是否支持WebSocket
    if (‘WebSocket‘ in window) {
        //建立连接,这里的/websocket ,是Servlet中注解中的那个值
        websocket = new WebSocket("ws://localhost:8080/项目名/websocket");
    }
    else {
        alert(‘当前浏览器 Not support websocket‘);
    }
    //连接发生错误的回调方法
    websocket.onerror = function () {
        console.log("WebSocket连接发生错误");
    };
    //连接成功建立的回调方法
    websocket.onopen = function () {
        console.log("WebSocket连接成功");
    }
    //接收到消息的回调方法
    websocket.onmessage = function (event) {
        console.log(event.data);
        if(event.data=="1"){
            console.log("数据更新啦");
        }
    }
    //连接关闭的回调方法
    websocket.onclose = function () {
        console.log("WebSocket连接关闭");
    }
    //监听窗口关闭事件,当窗口关闭时,主动去关闭WebSocket连接,防止连接还没断开就关闭窗口,server端会抛异常。
    window.onbeforeunload = function () {
        closeWebSocket();
    }
    //关闭WebSocket连接
    function closeWebSocket() {
        websocket.close();
    }

服务器端代码

在开启连接的时候启动了一个线程,关闭连接的时候调用线程的stopMe()方法,终止线程。当接收到消息的时候,调用sendMessage()方法给所有连接着的用户发送消息。

需要注意的是,一旦建立了连接,就会创建一个session,这个session和request中的session不一样,但是可以用类似的想法来理解。所以在发送消息的时候也需要调用session的方法来给连接着的用户发送消息。

WebSocket session发送文本消息有两个方法:getAsyncRemote()和getBasicRemote(),这两个方法我只是简单了解了一下,前者是异步发送消息,后者是同步发送消息。也就是说getBasicRemote()要等上一条消息发送完才能发送下一条消息。如果有错误的话希望大家指出!

在文档中我们看到也可以在服务器端接收消息的时候也可以直接在onMessage()方法中return txt.toUpperCase()来发送消息给消息发送方,但是在这个例子中,我们的消息是线程发送给WebSocket实现类的,所以不用这个方法。

//在相对路径中发布端点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;

    /**
     * @ClassName: onOpen
     * @Description: 开启连接的操作
     */
    @OnOpen
    public void onOpen(Session session) throws IOException{
        this.session=session;
        webSocketSet.add(this);
        System.out.println(webSocketSet);
        //开启一个线程对数据库中的数据进行轮询
        thread.start();

    }

    /**
     * @ClassName: onClose
     * @Description: 连接关闭的操作
     */
    @OnClose
    public void onClose(){
        thread1.stopMe();
        webSocketSet.remove(this);
    }

    /**
     * @ClassName: onMessage
     * @Description: 给服务器发送消息告知数据库发生变化
     */
    @OnMessage
    public void onMessage(int count) {
        System.out.println("发生变化"+count);
        try {
            sendMessage();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

  /**
     * @ClassName: OnError
     * @Description: 出错的操作
     */
    @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");
        }
    }
}

线程的定义

线程先对数据库中的数据查询一次,存在sum变量中,然后再一直对数据库中的数据进行轮询,new_sum与sum不同的话就发送消息给WebSocket实现类。

public class MyThread implements Runnable{
    private int sum;
    private int new_sum;
    private boolean stopMe = true;
    public void stopMe() {
        stopMe = false;
    }  

    /* (non-Javadoc)
     * @see java.lang.Runnable#run()
     */
    public void run()  {
        UrlDao urlDao=new UrlDao();
        sum=urlDao.selectCount();
        WebSocketServlet wbs=new WebSocketServlet();
        while(stopMe){
            new_sum=urlDao.selectCount();
            if(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();
            }
        }
    }
}

测试

至此我的需求是大概完成了,因为是第一次写WebSocket和线程相关的实例,如果有问题希望大家可以指出!

原文地址:https://www.cnblogs.com/huangcy/p/9183767.html

时间: 2024-10-10 05:08:13

WebSocket实现数据库更新前台实时显示的相关文章

websocket实现数据库更新时前端页面实时刷新

websocket实现数据库更新时前端页面实时刷新 javaweb 目录(?)[+] userjsp ManagerServletjava 如题,实现以上功能,我知道主要有两大种思路: 轮询:轮询的原理是隔一段时间向服务器发送一个请求,这里不累述.这里主要谈一下第二种思路. websocket进行前后端通讯:websocket是html5的新协议,基于TCP,在一次握手后,建立http连接,实现客户端与服务端全双工通信.相比较轮询机制,节约资源,不需要频繁的请求. 下面通过最精简的javaweb

python实现websocket服务器,可以在web实时显示远程服务器日志

一.开始的话 使用python简单的实现websocket服务器,可以在浏览器上实时显示远程服务器的日志信息. 之前做了一个web版的发布系统,但没实现在线看日志,每次发布版本后,都需要登录到服务器上查看日志,非常麻烦,为了偷懒,能在页面点几下按钮完成工作,所以这几天查找了这方面的资料,实现了这个功能,瞬间觉的看日志什么的,太方便了,以后也可以给开发们查日志,再也不用麻烦运维了,废话少说,先看效果吧. 二.代码 在实现这功能前,看过别人的代码,发现很多都是只能在web上显示本地的日志,不能看远程

玩转SSH--Hibernate(三)---手动修改数据库,前台查询信息不同步更新问题解决方法

在用hibernate时遇到一个挺纠结的问题,就是我在手动修改数据库的信息后,前台页面查询到的信息还是之前的结果,一开始以为是缓存的问题,经过多次修改和在网上查询资料,最终发现可能是hibernate自身的连接池存在问题,通过下面方法配置C3P0连接池就可以解决这个问题. 首先在hibernate.cfg.xml中加入下面代码: <!-- C3P0连接池 可以应对手动修改数据库后前台不更新的问题--> <property name="hibernate.connection.p

运维开发:python websocket网页实时显示远程服务器日志信息

功能:用websocket技术,在运维工具的浏览器上实时显示远程服务器上的日志信息 一般我们在运维工具部署环境的时候,需要实时展现部署过程中的信息,或者在浏览器中实时显示程序日志给开发人员看.你还在用ajax每隔段时间去获取服务器日志?out了,试试用websocket方式吧 我用bottle框架,写了个websocket服务端,浏览器连接到websocket server,再用python subprocess获取远程服务器的日志信息,subprocess,就是用Popen调用shell的sh

Spring Boot 入门(十一):集成 WebSocket, 实时显示系统日志

以前面的博客为基础,最近一篇为Spring Boot 入门(十):集成Redis哨兵模式,实现Mybatis二级缓存.本篇博客主要介绍了Spring Boot集成 Web Socket进行日志的推送,并实时显示在页面上. 1.导入jar包 第一个jar包是websocket的,第二个jar包是关于环形队列的jar包,本案例是通过本地队列存储日志.有条件的话,最好通过中间件存储(eg:redis,mq……).通过本地队列存储日志会存在日志丢失的情况,且日志量太大,会把页面卡死. 1 <!--beg

AngularJS判断checkbox/复选框是否选中并实时显示

最近做了一个选择标签的功能,把一些标签展示给用户,用户选择自己喜欢的标签,就类似我们在购物网站看到的那种过滤标签似的: 简单的效果如图所示: 首先看一下html代码: 1 <!DOCTYPE html> 2 <html data-ng-app="App"> 3 <head> 4 <script type="text/javascript" src="https://ajax.googleapis.com/ajax/

实时显示iOS编写UI代码效果

编写iOS应用UI的方式大概有两种,一种是Storyboard/Xib,另一种是手写代码.采用Storyboard/Xib方式组织UI,由于提供可视化的特性,只要从UI库中拖动UI控件,便可以显示结果,极大地提高开发速度.但面临一个问题就是多人协作开发,由于所有的UI都放在同一个Storyboard文件中,使用Git/SVN合并代码就会出现冲突.多人协作开发还不是主要问题,有人提出可以创建多个Storyboard来分开UI编写,而Storyboard/Xib最主要问题是代码复用性比较差.所以有些

利用checkbox的到值,并且存到数据库修改的话要显示之前选择的

在前台当然是利用checkbox来得到复选框的语言:{% for language in languages%}<input type="checkbox" name="language" value='{{ language.id }}' >{{ language.name }}{% endfor %}而复选框如果是已经选的在前台就展示的是选择的,那么input的属性就应该有checked 那么就可以通过在前台if来判断language.id跟已经选择

基于MATLAB的GUI(Graphical User Interface)音频实时显示设计

摘要:本文章的设计主要讲基于matlab的gui音频实时显示设计,此次设计的gui相当于一个简洁的音乐播放器,界面只有”录音“和”播放“两个控件,哈哈,够简洁吧.通过”录音“按钮可以实现声音从电脑的声卡录入,并且实时显示录入声音的时域图形和频域图形:待录音结束,通过”播放“按钮可以播放刚录入的声音,并且一边播放一遍实时显示时域和频域图形.本设计的编码在matlab2013a上亲测,可以实现... 一.首先matlab的gui界面设计 打开matlab—>在命令行执行guide—>出现gui编辑