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.jar和websocket-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和线程相关的实例,如果有问题希望大家可以指出!
WebSocket实现数据库更新前台实时显示的更多相关文章
- websocket实现数据库更新时前端页面实时刷新
websocket实现数据库更新时前端页面实时刷新 javaweb 目录(?)[+] userjsp ManagerServletjava 如题,实现以上功能,我知道主要有两大种思路: 轮询:轮询的原 ...
- Spring MVC框架下 将数据库内容前台页面显示完整版【获取数据库人员参与的事件列表】
1.书写jsp页面包括要显示的内容[people.jsp] <!-- 此处包括三个方面内容: 1.包含 文本输入框 查询按钮 查询结果显示位置 (paging) 2.包括对按钮(button) ...
- jsp实时显示后台批处理进度 - out分块,简单的长连接方式
这两天在实现一个批处理操作,但是想让前台实时显示后台批处理进度,本想着用复杂一些的框架可以实现异步信息调用 但是鉴于是内部管理系统,且只有一两个人用到这个功能,所以做了一个简单的长连接方式的实时响应 ...
- springboot1.5.9整合websocket实现实时显示的小demo
最近由于项目需要实时显示数据库更新的数据变化情况,一开始想过在前端使用ajax异步轮询方法实现,但后面考虑到性能和流量等要求,就放弃该方法而选择使用websocket(毕竟现在springboot整合 ...
- python实现websocket服务器,可以在web实时显示远程服务器日志
一.开始的话 使用python简单的实现websocket服务器,可以在浏览器上实时显示远程服务器的日志信息. 之前做了一个web版的发布系统,但没实现在线看日志,每次发布版本后,都需要登录到服务器上 ...
- python2.7实现websocket服务器,可以在web实时显示远程服务器日志
一.开始的话 使用python实现websocket服务器,可以在浏览器上实时显示远程服务器的日志. 之前写了一个发布系统,每次发布版本后,为了了解发布情况(进度.是否有错误)都会登录到服务器上查看日 ...
- EF实体框架-从数据库更新模型 一部分表的外键(导航属性)无法显示
从数据库更新模型 要想让数据库表之间的外键关系 显示到实体模型的导航属性中去. 表的外键 对应另一张表的字段要是主键,唯一键显示不出来
- 玩转SSH--Hibernate(三)---手动修改数据库,前台查询信息不同步更新问题解决方法
在用hibernate时遇到一个挺纠结的问题,就是我在手动修改数据库的信息后,前台页面查询到的信息还是之前的结果,一开始以为是缓存的问题,经过多次修改和在网上查询资料,最终发现可能是hibernate ...
- python websocket网页实时显示远程服务器日志信息
功能:用websocket技术,在运维工具的浏览器上实时显示远程服务器上的日志信息 一般我们在运维工具部署环境的时候,需要实时展现部署过程中的信息,或者在浏览器中实时显示程序日志给开发人员看.你还在用 ...
随机推荐
- 了解一下zookeeper,搭建单机版和集群版的环境玩玩,需要手稿的,留下邮箱
第一章:Zookeeper介绍 Zookeeper,动物管理员,是用来管理hadoop(大象).Hive(蜜蜂).Pig(小猪)的管理员. Apache Hbase和Apache Solr的分布式集群 ...
- MyBatis一对多和多对多xml配置
MyBatis一对多和多对多xml配置 <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE ma ...
- cve-2018-14515复现
一.环境 Windows NT WIN-RRI9T9SN85D 6.1 build 7600 (Windows 7 Business Edition) i586 Apache/2.4.23 (Win3 ...
- 《 C#语言学习笔记》——自动属性
属性是访问对象状态的首选方式,因为它们禁止外部代码实现对象内部的数据存储机制.属性还对内部数据的访问方式有了更多控制.一般以非常标准的方式定义属性,即通过一个公共属性直接访问一个私有成员. 利用自动属 ...
- 如何使用 nvm-windows 管理 nodejs 版本
写在前边的话: (1). 路径一定不要包含空格,如 Program Files 这样,所以有把程序安装到 D:\Program Files 文件下的同学请注意了:(2). 为了避免 nvm 无法切换源 ...
- opencv编译
1. clone源码 https://github.com/opencv/opencv 2. 安装cmake 3. cmake配置的时候,输出目录需要另外设置一个目录,不可以放到源码目录 4. 用cm ...
- 一文彻底搞懂Java中的环境变量
一文搞懂Java环境变量 记得刚接触Java,第一件事就是配环境变量,作为一个初学者,只知道环境变量怎样配,在加上各种IDE使我们能方便的开发,而忽略了其本质的东西,只知其然不知其所以然,随着不断的深 ...
- cachestat 安装文档
安装环境:ubuntu18.04 安装步骤 1. 打开命令行,输入以下命令 sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys ...
- Shiro权限管理框架(二):Shiro结合Redis实现分布式环境下的Session共享
首发地址:https://www.guitu18.com/post/2019/07/28/44.html 本篇是Shiro系列第二篇,使用Shiro基于Redis实现分布式环境下的Session共享. ...
- HTML&CSS兼容性总结
对目前所遇见的兼容性笔记进行整理分类: 不兼容浏览器 问题概要 问题描述 解决方法 IE6,IE7 3px 并列一行的元素左侧第一个元素没浮动,第二个元素左浮动,则两个元素之间会多3像素空隙 并在一 ...