Python+java+websocket+SpringMVC实时监控数据库中的表

本文涉及的产品
RDS MySQL DuckDB 分析主实例,集群系列 4核8GB
RDS MySQL DuckDB 分析主实例,基础系列 4核8GB
RDS DuckDB + QuickBI 企业套餐,8核32GB + QuickBI 专业版
简介: Python+java+websocket+SpringMVC实时监控数据库中的表

Python+java+websocket+SpringMVC实时监控数据库中的表

为什么要对数据库中的表进行实时的监控?

做数据展示你可能会想到ajax,做实时数据展示你可能会想到定时器+ajax。

定时器+ajax可能会造成:如果到一个指定的时间点没有新数据的话会造成一定的资源浪费。

那么就要考虑其他的方式来解决实时的数据推送了。

这里我使用SpringMVC+Websocket配合前端HTML做实时数据展示;

使用Python监控Mysql的日志文件,从而起到了监控数据库的作用。

例1:股票系统

后台有数据了会主动的把数据推向前台,前台进行实时的展示数据。

例2:聊天系统

例3:实时大数据平台

模拟环境

利用一个写好的学生信息管理系统的dome做为数据来源(添加数据),模拟硬件设备实时采集的数据往数据库中新增的数据的过程。也可以直接在数据库中新增数据。

这个dome使用的是SpringBoot+Mybatis+thymeleaf+Mysql,前端使用的是layui。

可以做为一个很好的例子来学习。

前台展示页面

很粗糙

Mysql日志文件

为了方便演示,我是在windows下的mysql,可以直接加上

log=文件路径

代码

SpringMvc+WebSocket

目录结构

BitCoinServer.java文件
package cn.socketConfig;
import cn.websocket.controller.QuartzTask;
import java.io.IOException;
import java.time.LocalTime;
import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
/**
 * @ServerEndpoint 注解是一个类层次的注解,它的功能主要是将目前的类定义成一个websocket服务器端,
 * 注解的值将被用于监听用户连接的终端访问URL地址,客户端可以通过这个URL来连接到WebSocket服务器端
 */
@ServerEndpoint("/ws/bitcoinServer")
public class BitCoinServer {
  //与某个客户端的连接会话,需要通过它来给客户端发送数据
  private Session session;
  @OnOpen
  public void onOpen(Session session){
    this.session = session;
    ServerManager.add(this);     
  }
  public void sendMessage(String message) throws IOException{
    this.session.getBasicRemote().sendText(message);
  }
  @OnClose
  public void onClose(){
    ServerManager.remove(this);  
  }
  @OnMessage
  public void onMessage(String message, Session session) {
//    if(message!=null){
      System.out.println("来自客户端的消息:" + message+",数据库发生改变了,正在向前台推送数据");
      QuartzTask.Message();
//    }
  }
  @OnError
  public void onError(Session session, Throwable error){
    System.out.println("发生错误");
    error.printStackTrace();
  }
}
ServerManager.java文件
package cn.socketConfig;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
public class ServerManager {
  private static Collection<BitCoinServer> servers = Collections.synchronizedCollection(new ArrayList<BitCoinServer>());
  public static void broadCast(String msg){
    for (BitCoinServer bitCoinServer : servers) {
      try {
        bitCoinServer.sendMessage(msg);
      } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
      }
    }
  }
  public static int getTotal(){
    return servers.size();
  }
  public static void add(BitCoinServer server){
    System.out.println("有新连接加入! 当前总连接数是:"+ servers.size());
    servers.add(server);
  }
  public static void remove(BitCoinServer server){
    System.out.println("有连接退出! 当前总连接数是:"+ servers.size());
    servers.remove(server);
  }
}
QuartzTask.java文件
package cn.websocket.controller;
import cn.socketConfig.ServerManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import javax.xml.crypto.Data;
import java.time.LocalTime;
//@Component("taskJob")
public class QuartzTask {
    public static void Message() {
        LocalTime time = LocalTime.now();
//      System.out.println("哈哈,我执行了!"+"当前时间=" + time);
        System.out.println("数据库更新数据了"+"当前时间=" + time+",已向前台推送数据!");
        //广播出去
        ServerManager.broadCast("数据库更新数据了"+"当前时间=" + time+",已向前台推送数据!");
        System.out.println("已成功向前台推送了数据");
    }
    /**
     * CRON表达式                含义 
    "0 0 12 * * ?"            每天中午十二点触发 
    "0 15 10 ? * *"            每天早上10:15触发 
    "0 15 10 * * ?"            每天早上10:15触发 
    "0 15 10 * * ? *"        每天早上10:15触发 
    "0 15 10 * * ? 2005"    2005年的每天早上10:15触发 
    "0 * 14 * * ?"            每天从下午2点开始到2点59分每分钟一次触发 
    "0 0/5 14 * * ?"        每天从下午2点开始到2:55分结束每5分钟一次触发 
    "0 0/5 14,18 * * ?"        每天的下午2点至2:55和6点至6点55分两个时间段内每5分钟一次触发 
    "0 0-5 14 * * ?"        每天14:00至14:05每分钟一次触发 
    "0 10,44 14 ? 3 WED"    三月的每周三的14:10和14:44触发 
    "0 15 10 ? * MON-FRI"   每个周一、周二、周三、周四、周五的10:15触发
     */
    /**
     * 每天5点触发(清空验证码表t_captcha中的数据)
     */
//    @Scheduled(cron = "0 0/1 1-23 * * ?")
//    public void testTask(){
//        LocalTime time = LocalTime.now();
//        System.out.println("哈哈,我执行了!"+"当前时间=" + time);
//        //广播出去
//        ServerManager.broadCast("数据库更新数据了"+"当前时间=" + time);
//    }
}
index.jsp文件
<%@ page language="java" pageEncoding="UTF-8" %>
<!DOCTYPE html>
<html>
<head>
    <title>用WebSocket实时消息推送,监控mysql数据表变化</title>
</head>
<body>
<div style="width:400px;margin:20px auto;border:1px solid lightgray;padding:20px;text-align:center;">
    实时消息推送,监控mysql数据表变化:
<%--    <span style="color:#FF7519" id="price">10000</span>--%>
<%--    <div style="font-size:0.9em;margin-top:20px">查看的人数越多,价格越高, 当前总共 <span id="total">1</span> 个人在线</div>--%>
    <div style="color:silver;font-size:0.8em;margin-top:20px" id="data">正在等待数据</div>
</div>
</body>
<script type="text/javascript">
    var websocket = null;
    //判断当前浏览器是否支持WebSocket
    if ('WebSocket' in window) {
        websocket = new WebSocket("ws://localhost:8080/SpringMvc_WebSocket_war_exploded/ws/bitcoinServer");
        //连接成功建立的回调方法
        // websocket.onopen = function () {
        //     websocket.send("客户端链接成功");
        // }
        //接收到消息的回调方法
        websocket.onmessage = function (event) {
            setMessageInnerHTML(event.data);
            console.log(event)
        }
        //连接发生错误的回调方法
        // websocket.onerror = function () {
        //     alert("WebSocket连接发生错误");
        // };
        //连接关闭的回调方法
        websocket.onclose = function () {
            alert("WebSocket连接关闭");
        }
        //监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。
        window.onbeforeunload = function () {
            closeWebSocket();
        }
    } else {
        alert('当前浏览器 Not support websocket')
    }
    //将消息显示在网页上
    function setMessageInnerHTML(data) {
        // var bitcoin = eval("("+innerHTML+")");
        document.getElementById('data').append(data);
        // document.getElementById('total').innerHTML = bitcoin.total;
    }
    //关闭WebSocket连接
    function closeWebSocket() {
        websocket.close();
    }
</script>
</html>

启动程序后可访问:

http://localhost:8080/SpringMvc_WebSocket_war_exploded/

出现如下图所示的界面就成功了

Python代码

import time
import test
# import test
url = "G:/soft/phpStudy/PHPTutorial/MySQL/log/mysql_log.txt"  #监控的mysql日志的地址
file = open(url,encoding='UTF-8') #打开日志文件
# ws = test.sendMessage()
while 1:  #一直监控
    where = file.tell()
    line = file.readline()
    if not line:
        time.sleep(1)
        file.seek(where)
    else:
        # print(line)
        # 如果最新的一行包含了insert这个语句,就主动连接websocket服务器,并告知服务器有新数据
        if line.find("INSERT INTO `course`")>=0 or line.find("insert into course")>=0:
            print("数据库有新数据了,正在向socket服务发送请求消息,请求接收数据")
            ws = None
            try:
                ws = test.CG_Client('ws://localhost:8080/SpringMvc_WebSocket_war_exploded/ws/bitcoinServer')
                ws.connect()
                ws.run_forever()
            except KeyboardInterrupt:
                ws.close()
                print("出错了")

启动py文件

新增数据测试

测试第二条:

测试直接在数据库中插入新数据

相关实践学习
每个IT人都想学的“Web应用上云经典架构”实战
本实验从Web应用上云这个最基本的、最普遍的需求出发,帮助IT从业者们通过“阿里云Web应用上云解决方案”,了解一个企业级Web应用上云的常见架构,了解如何构建一个高可用、可扩展的企业级应用架构。
MySQL数据库入门学习
本课程通过最流行的开源数据库MySQL带你了解数据库的世界。 &nbsp; 相关的阿里云产品:云数据库RDS MySQL 版 阿里云关系型数据库RDS(Relational Database Service)是一种稳定可靠、可弹性伸缩的在线数据库服务,提供容灾、备份、恢复、迁移等方面的全套解决方案,彻底解决数据库运维的烦恼。 了解产品详情:&nbsp;https://www.aliyun.com/product/rds/mysql&nbsp;
目录
相关文章
|
JavaScript 前端开发 Java
通义灵码 Rules 库合集来了,覆盖Java、TypeScript、Python、Go、JavaScript 等
通义灵码新上的外挂 Project Rules 获得了开发者的一致好评:最小成本适配我的开发风格、相当把团队经验沉淀下来,是个很好功能……
2091 103
|
9月前
|
机器学习/深度学习 JSON Java
Java调用Python的5种实用方案:从简单到进阶的全场景解析
在机器学习与大数据融合背景下,Java与Python协同开发成为企业常见需求。本文通过真实案例解析5种主流调用方案,涵盖脚本调用到微服务架构,助力开发者根据业务场景选择最优方案,提升开发效率与系统性能。
2025 0
|
9月前
|
jenkins Shell 测试技术
|
9月前
|
安全 jenkins Java
Java、Python、C++支持jenkins和SonarQube(一)
Jenkins 是一个开源的 持续集成(CI)和持续交付(CD) 工具,用于自动化构建、测试和部署软件项目。它基于 Java 开发,支持跨平台运行,并拥有丰富的插件生态系统,可以灵活地扩展功能
519 5
|
9月前
|
jenkins Java Shell
Java、Python、C++支持jenkins和SonarQube(全集)
Jenkins 是一个开源的持续集成(CI)和持续交付(CD)工具,用于自动化构建、测试和部署软件项目。它基于 Java 开发,支持跨平台运行,并拥有丰富的插件生态系统,可以灵活地扩展功能
777 1
|
9月前
|
jenkins Java 持续交付
Java、Python、C++支持Jenkins和SonarQube(三)
Python与Jenkins和SonarQube
435 1
|
10月前
|
前端开发 Java 开发者
Java新手指南:在Spring MVC中使用查询字符串与参数
通过结合实际的需求和业务逻辑,开发者可以灵活地利用这些机制,为用户提供更丰富而高效的Web应用体验。
245 15
|
人工智能 安全 Java
Java和Python在企业中的应用情况
Java和Python在企业中的应用情况
501 7
|
11月前
|
JSON 前端开发 Java
Java新手指南:如何在Spring MVC中处理请求参数
处理Spring MVC中的请求参数是通过控制器方法中的注解来完成的。这些注解包括 `@RequestParam`, `@PathVariable`, `@ModelAttribute`, `@RequestBody`, `@RequestHeader`, `@Valid`, 和 `@RequestMapping`。使用这些注解可以轻松从HTTP请求中提取所需信息,例如URL参数、表单数据或者JSON请求体,并将其转换成Java对象以供进一步处理。
639 17
|
9月前
|
jenkins Java 测试技术

推荐镜像

更多