SCADA/HMI电力监控系统源码解析:从Proxool连接池到实时曲线

发布时间:2026/10/29 0:35:52
SCADA/HMI电力监控系统源码解析:从Proxool连接池到实时曲线 简介压缩包内包含一套面向电力行业监控领域的人机界面HMI系统源代码适合电力后台与监控系统开发人员、SCADA初学者及需要二次集成的技术团队使用。该套代码以电力监控系统的数据采集、实时展示与远程控制为核心涵盖了从设备连接到前端交互的完整链路并针对多类监控曲线与后台数据管理提供了实现示例。文件共计51个压缩后大小2.45MB主要构成包括11个动态页面、9个编译后类文件、8个基础源码文件以及若干依赖库、图标与项目配置。其中基础源码与类文件实现业务逻辑动态页面负责曲线展示与操作界面依赖库包含数据库连接池等组件整体是可导入开发工具直接运行的电力监控前后端工程项目。目前已有563人参与学习下载。通过这份源代码可以了解电力监控人机界面的分层设计思路与前后端协作方式尤其是数据库持久化、连接池管理以及基于网页的交互组件实际应用方便在此基础上进行功能扩展或迁移到具体生产环境作为原型参考。1. 电力监控系统源码包没你想的那么神秘SCADAHMI 到底能解决什么电力监控系统这个名词听起来像电网公司专用的东西但工厂配电、数据中心、园区能耗管理里到处都在用许多项目只是把“设备状态”换成“可远传的测点数据”而已。SCADAHMI.rar 是一份用 Java 写的 SCADA/HMI 后台源码代码里没有花哨的微服务框架全是监控后台、监控连接系统真正绕不开的组件一组曲线 JSP 页面、PostgreSQL 数据库、Proxool 连接池以及一个负责浏览器端互动的 URLApplet。它适合三类人刚接手旧电力项目的维护工程师想搞懂实时采集链路的技术负责人以及想在电力监控方向找一个能落地改造起点的开发者。下面按工程结构、运行配置、数据链路和常见翻车点逐层拆开帮你判断这套源码值不值得下载、下完怎么让它先跑起来。2. 导入环境与工程结构让这套 Java Web 监控后台在本地跑起来2.1 先认识 .mymetadata这是 MyEclipse 工程的身份证从压缩包解出来的内容里.mymetadata、.classpath、.project三者同时出现基本能断定这是个 Eclipse 系列 IDE 导出的 Java Web 工程。很多人一上来就用 IDEA 的File Open打开根目录结果页面打不开、依赖飘红原因是 IDEA 不读.mymetadata不知道 Web 根目录是WebRoot而不是WebContent。文件/目录在工程里的实际作用.project / .classpathEclipse 的工程描述和 Java 构建路径.mymetadataMyEclipse 部署信息记录 Web 根目录和上下文名srcJava 源码通常放 Servlet、DAO、数据库工具类WebRoot/xxxCurve.jsp电力曲线展示页如 gjtCurve、lcCurve、blzCurve 等WebRoot/META-INF应用元数据老工程常在这里做数据源描述WebRoot/WEB-INF放 web.xml、lib 和页面模板.settings/org.hibernate.eclipse.console.prefsIDE 里残留下来的 Hibernate 控制台配置这个结构里WebRoot相当于现代工程的src/main/webapp。压缩包首页的多个*Curve.jsp并不是独立系统而是不同监测量在不同设备或者不同画面下的曲线入口。换句话说CurveJsp.jsp更像是所有曲线页面的公共入口模板业务上通过 URL 参数决定读取哪个点位。注意一个小陷阱.settings目录里的 Hibernate 配置只说明开发者曾在 IDE 里试过 Hibernate 工具不说明全项目都走了 ORM。很多老电力后台的实际查询是 JDBC 直连曲线页面为了速度宁愿手动拼 SQL。看代码时不要被.settings带偏判断。2.2 环境搭配JDK、Tomcat、PostgreSQL 的版本别太新这种工程大多诞生在 JDK 1.6/1.7 时代用的是 JSP Servlet JDBC PostgreSQL Proxool。我的建议是先按老环境搭不是不能用新版本而是不值得花时间调兼容性。实际部署时常用搭配组件建议版本选型说明JDK1.7老代码没有模块化高版本 JDK 可能遇到非法反射访问Tomcat7.0.xServlet 3.0JSP 编译兼容性最稳PostgreSQL9.2 或 9.4和旧版 PostgreSQL 驱动行为一致IDEEclipse JEE WTP识别 .mymetadata 最省事IDEA 需手工配 Web 目录数据库驱动postgresql-9.2/9.4 对应 jar要和数据库小版本匹配太新的驱动有时不认老库配置这套工程不是 Maven依赖 jar 全在WebRoot/WEB-INF/lib。解压之后先检查这个目录看看postgresql.jar和proxool.jar是否还在。曾经有不止一个项目因为 SVN 提交时把 lib 目录忽略了导致代码拿到手后所有 JDBC 类全部报ClassNotFoundException环境检查的第一步永远是确认 jar 存在。2.3 数据库准备建库、建用户、调权限下面是 PostgreSQL 建库命令按这个过程走能少踩很多权限坑sudo -u postgres psql -c CREATE USER scada WITH PASSWORD scada; sudo -u postgres psql -c CREATE DATABASE power_scada OWNER scada ENCODING UTF8;第一行创建和工程连接串同名的用户第二行建库并把 owner 给这个用户。旧工程里连接串常写在proxool.xml或src下的配置文件里用户名、库名、密码必须三者一致。PostgreSQL 默认认证常见为md5或scram-sha-256遇到连接报错时优先看pg_hba.conf确认本地连接用的是md5否则密码校验会在底层失败表现却是“连接超时”或“password authentication failed”。建完库后用psql -U scada -h localhost -d power_scada -W试连一次能进入命令行再往下走。这个检查只要几十秒却能排除掉一半的“数据库连接池初始化失败”。如果项目里有初始化 SQL 脚本记得一并执行光有库没有表后面页面能开但曲线是空的。2.4 导入工程与部署启动两种 IDE 的操作路径Eclipse/MyEclipse 的常规流程File Import Existing Projects into Workspace选中解压目录。如果项目不被识别右键工程名选择 MyEclipse 的Convert to Web Project。在Window Preferences Server Runtime Environments里添加 Tomcat 7。右键工程Run As Run on Server选择 Tomcat 7。IDEA 的流程略有区别File Open打开工程根目录。在Project Structure Modules里把src标记为 Sources把WebRoot标记为 Web Resource Directory。在 Web 模块里把 Web 根目录设为WebRoot并把 Deployment 的 Application context 设置为/SCADAHMI。添加 Tomcat 配置后启动。部署后看日志是默认动作tail -f /opt/tomcat/logs/catalina.out日志里出现Deploying web application archive和Server startup in xxx ms说明工程已经启动。此时用curl -I快速验证curl -I http://localhost:8080/SCADAHMI/CurveJsp.jsp如果返回 200说明 JSP 被编译并响应如果 404先查上下文名如果 500打开异常栈多半是数据库连接串或连接池配置问题。第一次验证不要直接看曲线先确认“Web 容器能编译 JSP”这是最小闭环。别省略这一步数据库配置错误密密麻麻的时候先把“页面能跑”和“数据能取到”两件事切分开排查会快很多。3. Proxool 连接池到实时曲线监控后台里最值得读的一段链路3.1 SCADA 数据为什么要连接池高并发写库不是靠多开连接解决电力监控后台的压力模型很特殊测点数量多、采集周期短每分钟可能成百上千条记录要写库。如果用裸 JDBC 每次都新建ConnectionPostgreSQL 需要建进程、做认证压力一大连接建立本身就成了瓶颈。连接池的做法是预先把若干物理连接准备好业务线程反复借用和归还。Proxool 是早期 Java 生态里很简单的一种配置在 XML 里运行时给出jdbc:proxool.别名的 URL易读、易排错。Proxool 为什么适合这种旧工程它不依赖 Spring 容器可以脱离框架单独使用配置项非常直接适合没人长期维护的小团队。反过来讲它的监控和 SQL 统计能力比 HikariCP 差不少所以今天新写的系统不会再用它。但在 SCADAHMI 这个源码包里Proxool 就是监控后台连接 PostgreSQL 的桥梁理解它的配置方式几乎等于理解了整个后台的数据通道。3.2 Proxool 配置与 JDBC 代码别名和连接串必须对上在WEB-INF或者工程配置目录下通常能找到proxool.xml。常见写法如下proxool aliaspower/alias driver-urljdbc:postgresql://localhost:5432/power_scada/driver-url driver-classorg.postgresql.Driver/driver-class driver-properties property nameuser valuescada/ property namepassword valuescada/ /driver-properties maximum-connection-count20/maximum-connection-count minimum-connection-count2/minimum-connection-count house-keeping-sleep-time30000/house-keeping-sleep-time simultaneous-build-throttle5/simultaneous-build-throttle /proxool几个参数值得说明alias决定应用层连接 URL 中的名字driver-url才是 PostgreSQL 的真实 JDBC 地址maximum-connection-count是池的最大连接数不设置默认可能过高house-keeping-sleep-time是 Proxool 后台保洁线程的检查间隔单位毫秒设太短会让 CPU 频繁扫描池。simultaneous-build-throttle控制连接池同时建立连接的线程数设太大数据库刚起来时会突然涌出一堆连接。对应 Java 代码里取连接的方式Class.forName(org.logicalcobwebs.proxool.ProxoolDriver); Connection conn DriverManager.getConnection(jdbc:proxool.power);这里jdbc:proxool.power中的power必须和配置里的aliaspower/alias一致。很多人在这行卡住把别名写成数据库名启动时直接报No such alias。别问我是怎么知道的这种错误藏得深日志里只写“无法找到别名”不告诉你是谁写错了。3.3 曲线页面读库一个可复用的 DAO 查询片段曲线画面最底层的操作是把采样值按时间取出来。最近 100 条采样值并拼接文本的示例import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; public class CurveDao { public String getLatestSeries(int pointId) { String sql SELECT record_time, value FROM scada_sample WHERE point_id ? ORDER BY record_time DESC LIMIT 100; StringBuilder sb new StringBuilder(); Connection conn null; try { Class.forName(org.logicalcobwebs.proxool.ProxoolDriver); conn DriverManager.getConnection(jdbc:proxool.power); try (PreparedStatement ps conn.prepareStatement(sql)) { ps.setInt(1, pointId); try (ResultSet rs ps.executeQuery()) { while (rs.next()) { sb.append(rs.getTimestamp(record_time)) .append(,) .append(rs.getDouble(value)) .append(\n); } } } } catch (Exception e) { throw new RuntimeException(查询监控曲线数据失败, e); } finally { if (conn ! null) { try { conn.close(); } catch (Exception ignore) {} } } return sb.toString(); } }说明LIMIT 100控制返回条数ORDER BY record_time DESC保证取的是最新数据。拼接成逗号分隔文本是给页面绘图用的老 JSP 页面通常直接用这个字符串初始化 Applet 或简单前端图表。conn.close()在 Proxool 里并非物理关闭而是把连接归还到池所以 finally 里的写法是安全的。提示这里的连接用户和密码只是示例值。真实部署时建议单独建一个只读账号给后台查询用不要把 PostgreSQL 的超级用户写进 proxool.xml否则一旦 Web 应用被上传了恶意 JSP等于把数据库权限直接送出去。3.4 JSP 侧的参数调整点号、时间窗口和刷新周期工程里的gjtCurve.jsp、lcCurve.jsp、wjjCurve.jsp、blzCurve.jsp等页面虽然名字不同内部结构几乎一致。JSP 从 URL 参数里拿pid查库再输出一段包含图表的 HTML。典型片段% String pointId request.getParameter(pid); CurveDao dao new CurveDao(); String series dao.getLatestSeries(pointId null ? 101 : Integer.parseInt(pointId)); % applet codecn.curve.CurveApplet.class width900 height400 param namedata value% series % param namerefreshInterval value2000 /applet这里几个参数在实际现场最常被改参数作用经验值pid点位 ID决定画哪条曲线按点位表配置limit采样条数影响曲线长度100 到 500 之间refreshInterval刷新毫秒数影响实时性2000 到 5000数据格式逗号分隔文本或 JSON和前端 Applet 解析逻辑必须一致刷新太短会造成频繁查询太长看不清实时data直接塞进 HTML 的做法在数据量大时会让页面体积膨胀一次传几千条点会明显卡顿。这个设计很脆弱但确实是那个年代常见做法。4. 监控连接系统与 HMI 通信从现场 PLC 到浏览器曲线的完整通道4.1 SCADA 如何与 PLC 连接先分清“采集链路”和“展示链路”监控连接系统这个关键词在电力后台里指的是“后台服务怎么和设备层通信”。很多人以为 SCADA 系统直接用 JDBC 连 PLC这是不对的。常见套路是三层现场 PLC/RTU 提供 Modbus TCP 或 IEC 60870-5-104 接口前置机或采集服务读规约把通信号映射成点位值点位值写入 PostgreSQLWeb 后台再从库里取数展示。厂里的中控 SCADA 系统基本都是这个链路差别只是规约和点表。所以“SCADA 如何与 PLC 连接”的答案不是一句“网线连通就行”而是要先确定通信规约。Modbus TCP 最常见的操作是读保持寄存器请求里要带事务标识、协议标识、长度、单元标识、功能码、起始地址和数据长度。这些术语看起来繁琐却是真正“监控连接系统”的核心。看懂这个链路后再回头看 SCADAHMI就会发现压缩包里那些类名和 JSP 页面处于“采集完之后的数据处理与展示段”不是直接跟 PLC 拽数据的那段。4.2 URLApplet 的定位网络化 HMI 的历史组件压缩包里的URLApplet值得单独说。Applet 是嵌在网页里的小 Java 程序URLApplet 的典型做法是去读取一个 URL拿到服务端返回的实时数据再在浏览器里画曲线或刷状态灯。在还没有 WebSocket 的年代它解决了“浏览器页面轮询数据并且不整页刷新”的需求。HTML 嵌入片段如下applet codecn.scada.urlapplet.URLApplet.class archiveSCADAHMI.jar width800 height300 param namedataUrl value/SCADAHMI/servlet/RealDataServlet?pointId101 param namerefresh value2000 /appletdataUrl就是要轮询的地址refresh是轮询间隔。实际项目中dataUrl会指向一个 ServletServlet 内部查 PostgreSQL 再返回文本或 XML。这样 Applet 不需要自己连数据库安全边界是清晰的。你可以把这个 Applet 理解成“HTTP 长轮询前端”。注意现代浏览器不再支持 Java 插件所以这套代码拿到今天更多是参考业务链路而不是直接上线用。判断一个 SCADA 源码包是否值得学习关键不在 Applet 还能不能用而在于数据流是否完整采集层、存储层、展示层是不是都给你留了修改入口。4.3 点表和采样表设备到画面的最小数据落点为了让链路看得更清楚通常需要一张点位表和一张采样表。CREATE TABLE scada_point ( point_id INTEGER PRIMARY KEY, point_name VARCHAR(64) NOT NULL, unit VARCHAR(20) ); CREATE TABLE scada_sample ( id BIGSERIAL PRIMARY KEY, point_id INTEGER NOT NULL REFERENCES scada_point(point_id), record_time TIMESTAMP NOT NULL, value DOUBLE PRECISION NOT NULL ); CREATE INDEX idx_sample_time ON scada_sample(point_id, record_time DESC);点位表是静态台账采样表是时序记录。idx_sample_time索引直接支撑“查最近 N 条曲线”的 SQL。采集服务拿到 PLC 数据后先到点表里查这个点是否登记再写采样表。JSP 页面读采样表Applet 画曲线。这就是监控连接系统的完整闭环。理解了这个闭环再去看源码包里的文件你会知道哪个文件负责数据访问、哪个负责页面展示、哪个只是历史遗留的过渡组件。Modbus 和 IEC 104 的选型也影响后台设计。Modbus TCP 适合局部接线盒和单个设备按寄存器地址读IEC 104 适合变电站和调度侧按遥测/遥信对象地址收发。许多电力后台会把两套规约同时部署在一个前置服务里数据统一进 PostgreSQL页面上并不关心数据来自哪种协议。这也是为什么 SCADAHMI 只关心数据库和展示不关心底层 PLC 品牌的原因。5. 避坑与排查PostgreSQL、JSP 编码和连接池的五类翻车记录5.1 现象启动时直接报 ClassNotFoundException: org.postgresql.Driver原因WebRoot/WEB-INF/lib目录下的 PostgreSQL 驱动 jar 丢失。很多老工程通过 SVN 同步.classpath里有 jar 名但 jar 本身被忽略换到新机器后依赖就断了。另外不同 PostgreSQL 驱动的类名相同但驱动版本和数据库版本不匹配时会出现连接握手失败报错却故意绕到 ClassNotFoundException。解决先把lib目录补全确认存在postgresql-9.x.jar和proxool-x.x.jar。再检查 Tomcat 的lib目录有没有旧驱动残留Tomcat 全局 lib 里的 PostgreSQL 驱动会和 Web 应用里的旧 jar 冲突轻则告警重则驱动类被重复加载。稳妥做法是只在WebRoot/WEB-INF/lib放一套驱动Tomcat 全局目录不放数据库驱动。5.2 现象配置了 proxool.xml连接池还是报初始化失败原因分三类很多人一上来就改最大连接数结果问题不在这里。第一个原因是alias和代码里jdbc:proxool.xxx不一致第二个原因是 PostgreSQL 的pg_hba.conf认证规则不认当前连接方式第三个原因是连接串里的库名或端口写错导致 Postgre 直接拒绝。解决按顺序排查。先执行psql -U scada -h localhost -d power_scada -W手动连一次数据库层通了再看 Proxool。再把jdbc:proxool.power和aliaspower/alias对齐。然后看启动日志里的原始异常是连接池问题还是认证问题。很多“连不上数据库”的假象其实只是密码里的特殊字符没有在 XML 中转义。5.3 现象JSP 页面能打开但中文全部变成乱码原因老工程多数在 Eclipse 里以 GBK 编码编写 JSP页面上却声明了 UTF-8或者反过来。Tomcat 6/7 默认URIEncoding也不是 UTF-8URL 里传中文参数时就会乱。PostgreSQL 数据库编码如果不是 UTF8查询结果回到页面又会被再转一次三方编码不一致乱码就成了必然。解决统一编码。先确认每个 JSP 文件的物理编码用file命令看file *.jsp如果是iso-8859或GBK开头而页面pageEncoding写的是 UTF-8就把文件转成 UTF-8iconv -f GBK -t UTF-8 gjtCurve.jsp gjtCurve_utf8.jsp mv gjtCurve_utf8.jsp gjtCurve.jsp同时把数据库编码固定为 UTF8连接串里再加?characterEncodingUTF-8。Tomcat 的server.xml里给 Connector 加URIEncodingUTF-8。这三处全部对齐乱码问题才算根治。5.4 现象曲线页能打开但点线不刷新甚至一片空白原因最常见的是页面直接读缓存没有请求后台。Applet 被浏览器拦截后整个画布区域是空白的看起来像“没有数据”。另一个原因是 JSP 的参数名不匹配页面请求pid后台代码读的却是pointId返回默认点位而默认点位在库里没有数据。解决先用浏览器开发者工具看网络面板确认请求是否发出、状态码是多少。再打开日志看有没有 SQL 异常。然后把 JSP 里的request.getParameter(pid)和前端传入参数对齐。对于缓存问题在 JSP 响应头里加% response.setHeader(Cache-Control, no-cache); %这行代码放到曲线页面顶部能解决大部分“数据不刷新”的假象。5.5 现象Applet 在浏览器里被拦曲线区域空白报 Java plug-in 不支持原因不是业务代码问题而是运行环境问题。JDK 8 之后的版本不再提供浏览器 Java 插件Chrome、Edge 和 Firefox 也彻底移除了 npapi 支持。这个源码包的 HMI 部分确实依赖 Applet 做前端绘制拿现代浏览器直接开必然失败。解决临时验证用低版本 JDK 和 IE 模式或者干脆把前端换成现代方案。最省事的替换是写一个 Servlet 返回 JSON页面用 ECharts 或 uCharts 画曲线。业务链路不变只把“Applet 拉数据”改成“JavaScript 拉数据”。这一步改完后这套电力监控后台才能在新环境里继续用而不是停在“能跑但只能老浏览器跑”的境地。6. 一个验证技巧用本地仿真数据源代替 PLC 快速打通全链路接手这套源码时我最怕的是现场 PLC 还没准备好后台页面又是空白状态根本分不清是前端问题、数据库问题还是连接池问题。从那以后我每次都会在本地先起一个仿真采集器用定时任务往scada_sample里写模拟数据先把“采集到存储到展示”这条链路打通再对接真实 PLC。仿真采集器最简单的写法是用 Java 的Timerimport java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.util.Random; import java.util.Timer; import java.util.TimerTask; public class SimulatedCollector { public static void main(String[] args) throws Exception { Class.forName(org.logicalcobwebs.proxool.ProxoolDriver); Timer timer new Timer(SimulateCollector, true); timer.scheduleAtFixedRate(new TimerTask() { private final Random random new Random(); private int seq 0; Override public void run() { String sql INSERT INTO scada_sample(point_id, record_time, value) VALUES (101, now(), ?); try (Connection conn DriverManager.getConnection(jdbc:proxool.power); PreparedStatement ps conn.prepareStatement(sql)) { ps.setDouble(1, 220.0 random.nextDouble() * 10); ps.executeUpdate(); if (seq % 10 0) { System.out.println(已写入 seq 条仿真数据); } } catch (Exception e) { e.printStackTrace(); } } }, 0, 2000); Thread.sleep(Long.MAX_VALUE); } }这段代码的作用是每两秒向scada_sample表插入一条电压仿真值点位 ID 固定为 101。random.nextDouble() * 10让数据在 220 到 230 附近波动接近真实电压读数。TimerTask里的try-with-resources自动关闭语句和连接连接还回池不会漏。运行仿真采集器后打开曲线页面传参pid101观察曲线是否按两秒一次的节奏跳动。如果页面有数据但卡住先看刷新参数如果没有任何数据先查scada_sample表psql -U scada -h localhost -d power_scada -c SELECT count(*) FROM scada_sample;表里有数据但页面空白问题在 JSP 或 Applet表里没有数据问题在采集器或连接串。这一步把整个黑匣子拆成了两段排查范围立刻缩小。这个习惯我一直保留着现在接手任何带实时曲线的老系统第一件事都是先塞一批仿真数据让页面动起来再碰真实通信协议少走了大量白屏焦虑的弯路。希望帮到你。本文还有配套的精品资源点击获取

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询