news 2026/10/7 11:21:04

Java+JavaScript+HTML水质检测系统:毕设课设完整源码部署详解

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Java+JavaScript+HTML水质检测系统:毕设课设完整源码部署详解

简介:面向高校计算机及相关专业的毕业设计、课程设计与项目开发场景,这套基于Java、JavaScript与HTML技术栈实现的水质检测系统提供完整可运行的项目源码与配套数据库,解决水质数据采集、检测结果展示及相关管理流程的Web端实现问题。系统涵盖水质数据录入与处理、检测结果可视化、前端交互响应等功能模块,覆盖从后端Java逻辑与JSP动态页面、到前端JavaScript交互脚本及CSS样式布局的完整开发链路,贴合相关课程实训与毕设答辩要求。资源包共297个文件,压缩后约3.91MB,主要包含37个Java源文件、16个JSP页面、50个JavaScript脚本、34个CSS样式表及1个SQL数据库脚本,连同xml配置文件与页面图片素材一并打包,目录结构清晰、便于按模块查阅;配套SQL脚本可帮助快速初始化数据库环境。项目源码已经过严格测试,可直接部署运行,并可在现有基础上做二次功能扩展。目前已有50人学习下载,适合需要快速上手完整Web项目或完成毕业设计、课程设计任务的读者参考。

1. 这套 Java + JavaScript + HTML 水质检测系统源码包:毕设课设直接能用的完整闭环

如果你正在找毕业设计或课程设计的题目,水质检测系统大概率是老师推荐过的类型:业务不复杂、前后端都覆盖、数据库有参与,答辩时能讲清楚的东西足够多。这套基于 Java + JavaScript + HTML 实现的水质检测系统源码包,正是按这个需求组织起来的完整项目——后端用 Java 处理业务逻辑,前端用 HTML 搭页面、用 JavaScript 做交互,数据库脚本单独给出,导入即可跑通。它适合三类人:一是要交毕设但时间紧、需要一份能复现能讲清的项目;二是课程设计要求前后端分离结构的学生;三是想快速起一个管理类脚手架、在上面二次开发的初学者。接下来我把这套项目的结构、数据库、代码实现、部署顺序和常见坑逐一拆开,你拿到手后能照着走通,也能在答辩时把每段逻辑说清楚。

2. 技术栈与模块分工:Java、JavaScript、HTML 在这个系统里各管什么

2.1 为什么这种前后端组合在课设里最常见

很多初学者拿到这套源码包后第一反应是问:为什么不直接用 Spring Boot?答案是毕业设计和课程设计场景里,老师更看重的是你能否讲清楚一次请求从前端页面到数据库、再返回页面的完整链路。这套系统用的是最朴素也最好解释的三层结构:JSP/HTML 负责展示,JavaScript 负责页面上不提交给服务器的数据校验和异步交互,Java 的 Servlet 负责接收请求,DAO 负责访问数据库。

从工程角度看,这种结构的代码量适中,没有 Spring 那一堆注解和依赖注入需要解释,答辩时从LoginServlet到UserDao再到 MySQL,每一行逻辑都是看得见的。另一个原因是课程设计往往只给几天到两周时间,Spring Boot 全家桶虽然在工业界是标配,但对赶工期的学生来说,理解成本和工作量都偏大。这套源码包的定位就是「够用、能跑、讲得清」,而不是「生产级架构示范」。

2.2 系统的功能清单与请求数据流向

从项目标题和源码目录能看出,这套水质检测系统的功能围绕「检测数据管理」展开,典型模块包括:用户登录、检测点信息维护、水质检测记录录入、水质指标查询与超标判断。数据流向是标准的 MVC 模式流程:用户在 HTML 页面上填写表单,JavaScript 先做基础校验,通过后由表单提交或异步请求发给 Servlet,Servlet 解析参数调用 DAO 层,DAO 执行 SQL 操作 MySQL 数据库,结果再返回给页面。

这里有一个我在课设里反复强调的点:JavaScript 的校验只能减少无效请求,不能作为数据安全边界。比如 pH 值填了 20 这种明显超范围的数据,前端要拦住;但真正决定这条记录能不能入库的,是后端的判定逻辑。这套源码里两端都写了校验,你看代码时可以对照着看同一件事在前端和后端各做了一次,这也是答辩时老师喜欢问的「重复校验的必要性」。数据表之间是一对多关系,一个监测点有多条检测记录,一条主记录对应多条指标明细,后面讲数据库设计时会详细展开。

2.3 源码包里你应该重点关注的目录和文件

拿到源码包后不用从头到尾泛读,按运行顺序打开这几处即可。数据库脚本db_water_quality.sql是第一步要看的,它决定了表结构;然后是src/com/xxx/util/DBUtil.java,这是数据库连接入口;接着是servlet包下的各个控制类;最后打开WebRoot目录下的页面文件。

我一般会先 grep 一遍代码里的Class.forName确认 JDBC 驱动版本,再查web.xml里配的 Servlet 映射路径,这两个地方是首次部署最容易出错的位置。如果你要在现有项目上加功能,比如新增一个「水质达标率统计」,就照着现有 Servlet + DAO + JSP 的写法复制一套,保持分层不要破坏。

3. 数据库设计:这套系统的表结构和关系,直接决定你的代码怎么写

3.1 四张核心表的字段设计与建表脚本

这套水质检测系统的数据库围绕「用户—监测点—检测记录—指标明细」四个维度建表。先看用户表,它支撑登录功能,字段包含主键、用户名、密码和角色类型;监测点表存点位名称、位置和状态;检测记录表是核心业务表,记录一次采样的时间、采样人员和监测点;指标明细表则存具体的 pH 值、浊度、余氯等检测结果。

-- 用户表 CREATE TABLE `t_user` ( `id` INT PRIMARY KEY AUTO_INCREMENT, `username` VARCHAR(50) NOT NULL UNIQUE, `password` VARCHAR(100) NOT NULL, `role` VARCHAR(20) DEFAULT 'admin' ); -- 监测点表 CREATE TABLE `t_monitor_point` ( `id` INT PRIMARY KEY AUTO_INCREMENT, `point_name` VARCHAR(100) NOT NULL, `location` VARCHAR(200), `status` TINYINT DEFAULT 1 ); -- 检测记录主表 CREATE TABLE `t_water_record` ( `id` INT PRIMARY KEY AUTO_INCREMENT, `point_id` INT NOT NULL, `sample_time` DATETIME NOT NULL, `tester` VARCHAR(50), FOREIGN KEY (`point_id`) REFERENCES `t_monitor_point`(`id`) ); -- 检测指标明细表 CREATE TABLE `t_water_detail` ( `id` INT PRIMARY KEY AUTO_INCREMENT, `record_id` INT NOT NULL, `indicator_name` VARCHAR(50) NOT NULL, `indicator_value` DECIMAL(10, 3) NOT NULL, `standard_value` DECIMAL(10, 3), `qualified` TINYINT, FOREIGN KEY (`record_id`) REFERENCES `t_water_record`(`id`) );

这里的关键设计是主表和明细表分离。一次水质采样会同时检测多个指标,如果全部塞进一张表,每条记录会有大量重复的采样时间和采样人信息,而且后期加指标要改表结构。拆成两张表后,加一个检测指标只需要往明细表插记录,主表完全不用动。字段类型有几个细节要注意:indicator_value用 DECIMAL 不用 FLOAT,因为水质数据要比较精度,FLOAT 在 MySQL 里会存在近似值问题;qualified用 TINYINT 存 0 或 1,方便统计超标率时直接SUM(qualified)。

3.2 主表和明细表拆分的实际收益

有同学问过:检测记录为什么非要拆两张表,直接用一张宽表放所有指标不行吗?这个问题如果能在答辩时主动讲出来,反而是加分项。一张宽表的典型问题是数据冗余和扩展困难:假设现在有 20 个监测点、每个点有 100 条历史记录,宽表要存 2000 行数据,每一行都有 20 个指标字段,大部分是空值;而且标准变更时需要批量更新所有历史数据的标准字段。拆分成主从表后,标准值只存在明细表当前记录里,查某次采样的数据只需WHERE record_id = ?,非常干净。

当然拆分也有代价,就是取数据时要做一次 JOIN:

SELECT r.id, p.point_name, r.sample_time, d.indicator_name, d.indicator_value FROM t_water_record r JOIN t_monitor_point p ON r.point_id = p.id JOIN t_water_detail d ON r.id = d.record_id WHERE p.point_name = '城东水厂' ORDER BY r.sample_time DESC;

这次 JOIN 涉及的三个表字段不多、数据量也就在几千行级别,索引只要建立在主键和外键上就足够快,没必要提前优化。我在课上讲过一条原则:对于课程设计这个量级,先求结构清晰,不要为了「未来可能要处理一百万条数据」去设计复杂的分区表,那反而是过度设计。

3.3 初始化数据与测试账号

数据库脚本最后一段通常会包含预设的测试数据。你需要确认的有两个:登录账号是哪组用户名密码,以及监测点表里预置了几个点位。常见做法是插入一个admin / admin123的管理员账号和三到五个监测点数据。

INSERT INTO `t_user` (`username`, `password`, `role`) VALUES ('admin', 'admin123', 'admin'); INSERT INTO `t_monitor_point` (`point_name`, `location`, `status`) VALUES ('城东水厂', '城东工业园区', 1), ('城南泵站', '城南路12号', 1), ('滨河采样点', '滨河公园东侧', 1);

注意密码在真实项目里应该是 MD5 或 BCrypt 加密存储,但这套课设源码为了演示方便通常直接用明文,你可以在答辩时主动说明「生产环境不会这么做,这里是为了方便课设演示」。这句话虽然简单,但能展示你区分教学代码和工程代码的认知,老师印象分会不一样。初始化数据本身也是黑盒测试的输入源——后续章节验证查询功能时,你会发现没有这组预设数据,很多页面查出来是空列表,容易误判为程序 bug。

4. 从请求到响应:Servlet 处理流程与 JavaScript 数据交互的实现细节

4.1 后端分层结构的代码落地:DBUtil、DAO、Servlet

后端代码遵循经典的 JSP/Servlet 分层,包结构按util、dao、servlet、entity划分。连接数据库的工具类通常是第一个要看的类,它决定了你数据库账号密码配错时错误信息长什么样。我见过太多同学把这个类里的连接串改成自己的密码后,忘记改驱动名导致整晚都在查 ClassNotFound,先把这个类读通,后面部署能省一半调试时间。

public class DBUtil { private static final String URL = "jdbc:mysql://localhost:3306/water_quality?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai"; private static final String USER = "root"; private static final String PASSWORD = "123456"; static { try { Class.forName("com.mysql.cj.jdbc.Driver"); } catch (ClassNotFoundException e) { e.printStackTrace(); } } public static Connection getConnection() throws SQLException { return DriverManager.getConnection(URL, USER, PASSWORD); } }

连接串里有几个参数是容易踩坑的重灾区。第一是characterEncoding=utf-8,少了它,往数据库写入中文点位名称时大概率出现乱码;第二是serverTimezone=Asia/Shanghai,MySQL 8.x 不带这个参数会直接报时区错误;第三是useSSL=false,本地开发不需要加密连接,省略它会有版本兼容警告。你的 MySQL 是 5.7 还是 8.0,驱动名和这些尾参都要对应调整。

DAO 层的写法保持传统 JDBC 的PreparedStatement方式,没有引入 MyBatis,这样每一条 SQL 都在你的可控范围内。以用户登录为例,核心查询长这样:

public User checkLogin(String username, String password) { String sql = "SELECT id, username, role FROM t_user WHERE username = ? AND password = ?"; try (Connection conn = DBUtil.getConnection(); PreparedStatement ps = conn.prepareStatement(sql)) { ps.setString(1, username); ps.setString(2, password); try (ResultSet rs = ps.executeQuery()) { if (rs.next()) { User u = new User(); u.setId(rs.getInt("id")); u.setUsername(rs.getString("username")); u.setRole(rs.getString("role")); return u; } } } catch (SQLException e) { e.printStackTrace(); } return null; }

这里必须强调PreparedStatement的两个作用:一是预编译会话能防止 SQL 注入,这是答辩必问点;二是用?占位符然后setString赋值,避免了字符串拼接 SQL 时引号嵌套的语法错误。你去看一些网上的旧代码,直接用Statement拼"SELECT ... WHERE username='" + name + "'"的写法,要么跑不通、要么是安全隐患,这套源码里没有这种做法,可以放心参考。

Servlet 作为控制层,职责非常窄:取参数、调 DAO、跳转或输出。看完下面的代码你会发现,Servlet 里绝对不写 SQL,这是界线和习惯问题,也是后面加功能时最好复用的结构。

@WebServlet("/login") public class LoginServlet extends HttpServlet { private UserDao userDao = new UserDao(); @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String username = req.getParameter("username"); String password = req.getParameter("password"); User user = userDao.checkLogin(username, password); if (user != null) { req.getSession().setAttribute("loginUser", user); resp.sendRedirect("index.html"); } else { req.setAttribute("errorMsg", "用户名或密码错误"); req.getRequestDispatcher("login.html").forward(req, resp); } } }

注意这段代码里的两个细节。一是用sendRedirect跳转首页而不是forward,因为登录成功后要避免刷新页面时重复提交表单;二是错误信息用setAttribute+forward回登录页,这样登录页能通过EL表达式把错误提示显示出来。如果你的源码包里web.xml时代较旧、用的是<servlet>标签映射而不是@WebServlet注解,也是正常的,两者效果等价,部署时不要两种方式混用。

4.2 前端页面:HTML 表单 + JavaScript 数据校验与提交

前端页面由 HTML 搭建结构和样式,JavaScript 负责两件事:提交前的数据合法性检查,以及用异步请求向 Servlet 传数据。这套设计对课设来说够清晰了。以检测记录录入页面为例,pH 值的输入框需要限制范围在 0 到 14 之间,浊度不能为负数,采样时间不能晚于当前时间——这些规则如果不拦截,要么后端判断报错、要么数据库落了一条脏数据。

function validateRecordForm() { var ph = document.getElementById("phValue").value; var turbidity = document.getElementById("turbidity").value; var sampleTime = document.getElementById("sampleTime").value; if (ph === "" || turbidity === "" || sampleTime === "") { alert("所有字段均为必填项"); return false; } if (isNaN(ph) || parseFloat(ph) < 0 || parseFloat(ph) > 14) { alert("pH 值必须在 0~14 之间"); return false; } if (parseFloat(turbidity) < 0) { alert("浊度不能为负数"); return false; } return true; }

这段校验是所有表单提交前的前置闸门。值得注意:isNaN(ph)拦截非数字字符,但如果用户输入的是空字符串,parseFloat会返回NaN,这个值既能通过isNaN判断也可能漏过范围判断,这就是为什么在判断前必须做空值检查。很多翻车现场都是只写了范围判断、没写空值判断,用户清空输入框直接提交,后端收到的参数变成空指针异常。

提交方式上,这套源码可能采用两种方案:一是表单直接action指向 Servlet,onsubmit返回校验结果;二是用XMLHttpRequest或fetch异步提交。第一种适合登录、录入这类刷新式页面,第二种适合查询时要保留当前页面的场景。我建议你在做「查询检测记录」功能时用异步方式,这样用户勾选监测点后点击查询,结果用回调函数更新表格容器,页面不会跳来跳去,体验好很多,答辩演示也更流畅:

fetch("servlet/QueryRecordServlet?pointId=" + pointId, { method: "GET" }) .then(resp => resp.json()) .then(data => { var tbody = document.getElementById("recordTbody"); tbody.innerHTML = ""; data.forEach(item => { var row = "<tr><td>" + item.pointName + "</td><td>" + item.sampleTime + "</td><td>" + item.phValue + "</td><td>" + item.qualified + "</td></tr>"; tbody.innerHTML += row; }); }) .catch(err => console.error("请求失败", err));

这里有几个参数细节需要注意。fetch默认的Content-Type在 GET 请求下是text/plain;charset=UTF-8,后端要按请求参数方式取值,Servlet 里getParameter不受影响;如果你改成 POST 并要用req.getParameter,前端必须显式设置Content-Type: application/x-www-form-urlencoded。另一个是老生常谈的resp.json()——后端返回的数据不能是普通字符串,Servlet 里要用response.setContentType("application/json")并输出 JSON 格式字符串。如果后端忘了设置 ContentType,前端解析 JSON 时会报语法错误,这是异步请求最常见的翻车点之一。

4.3 水质指标超标判定:把检测值跟标准比对并落库

水质检测系统的业务核心在于「判定是否合格」。河湖地表水、生活饮用水、污水排放执行的标准完全不同,这套课设一般内置一套简化规则:pH 值 6.5 到 8.5 为合格,浊度不超过 3 NTU,余氯不低于 0.05 mg/L。后端拿到指标明细后逐条比对,把结果写进qualified字段。

public int checkStandard(String indicatorName, double value) { switch (indicatorName) { case "pH": return (value >= 6.5 && value <= 8.5) ? 1 : 0; case "turbidity": return (value <= 3.0) ? 1 : 0; case "chlorine": return (value >= 0.05) ? 1 : 0; default: return 1; } }

这段逻辑虽然简单,但有两个扩展点值得拿出来讲。一是标准值应该读表而不是写死在代码里,比如把standard_value放到数据库里,你就能在页面上维护标准而不需要重新编译;二是「是否合格」和「超标倍数」建议分开存储,因为答辩老师很可能会问「超标了怎么评估严重程度」,你可以解释超标倍数 = 实际值 / 标准值,这些扩展都基于现有表结构很容易实现。

实际的代码里可能还有一条逻辑链:录入明细时先调这个判定方法,算出qualified值后连同明细一起插入t_water_detail表,然后在列表页用红色标记超标的行。整个流程前端和后端各写了一半,而真正的数据落库在后端。理解了这个链路,你去改「合格标准」时就知道动哪里、不动哪里,避免改了页面标准但后端不认的情况。

5. 部署到 Tomcat 的完整过程与常见问题排查:照着做不翻车

5.1 环境版本对应关系:JDK、Tomcat、MySQL 怎么选

这套水质检测系统的运行需要 Web 服务器支撑,源码里如果有 JSP 页面就要用 Tomcat,如果纯 HTML + Servlet 则任何支持 Servlet 3.0 的容器都行。最稳妥的课设环境组合是 JDK 1.8 + Tomcat 8.5 + MySQL 5.7,这个搭配经过了大量验证,兼容性最好。如果机器上已经装了 JDK 17,也不用重新装,但要在 IDE 里把项目编译级别改成 1.8,否则一些旧写法会触发编译警告。

三个版本的对应关系直接用表格说明:

组件推荐版本关键注意事项
JDK1.8兼容 Servlet 3.0 和 JSP 2.3,课设项目源码基本按此语法编写
Tomcat8.5 或 9.08.5 对应 Servlet 3.1,9.0 对应 4.0,本项目的注解方式两者都支持
MySQL5.7 或 8.05.7 用com.mysql.jdbc.Driver,8.0 必须换成com.mysql.cj.jdbc.Driver
数据库驱动mysql-connector-java 5.1.49 或 8.0.x驱动版本必须和 MySQL 大版本匹配,不匹配报CommunicationsException

非要总结一条血泪经验的话:驱动版本不匹配导致的报错信息极具迷惑性,第一次见会以为是网络问题。你如果连不上数据库,先别急着改防火墙,把驱动 jar 的版本和小版本号对一下再说。

5.2 从导入到启动的完整步骤

这套源码包拿到手后,部署顺序是一套固定流程,按顺序做能省很多时间。第一步,用 IDE 以Web Application方式导入源码,确认WebRoot或webapp目录被识别为 Web 根目录,Eclipse 和 IDEA 的导入方式有差异,但核心是别把源码当普通 Java 项目打开,否则运行按钮是灰的。第二步,在 MySQL 里执行数据库脚本建库建表,并核对DBUtil.java中的账号密码。第三步,把数据库驱动 jar 放进WEB-INF/lib目录,Tomcat 发布时自动加载。第四步,配置 Tomcat 运行环境,在 IDE 里关联本地 Tomcat 目录。第五步,启动后访问登录页,用预设账号测试。

下面用命令行方式描述 Tomcat 发布后的验证动作,这样即使在 IDE 里出了诡异问题,也能退回命令行确认环境本身是好的:

cd $CATALINA_HOME/bin ./startup.sh # 启动后查看日志 tail -f $CATALINA_HOME/logs/catalina.out # 确认端口占用情况 lsof -i:8080 # 发布后页面可达性检测 curl -I http://localhost:8080/water_quality/

注意两个细节:一是water_quality是上下文路径,取决于你的工程名和 IDEA 的Application context配置,不一致就会 404;二是startup.sh启动成功不等于项目发布成功,Tomcat 启动日志不报错但应用报错时,应用错误会打印在catalina.out尾部,所以看日志要看最后 50 行而不是只看启动横幅。

5.3 常见问题与排查记录

以下是我过去帮人调试这套系统时遇到频率最高的几个问题,每条按「现象 → 原因 → 解决」记录,你可以直接对号入座。

问题一:页面中文全部变成问号。现象是浏览器显示中文正常,但登录后首页的监测点名称、操作提示全是乱码。原因是 JSP 页面或 Servlet 响应没有设置 UTF-8 编码。解决方式分两处:页面头部加<%@ page contentType="text/html;charset=UTF-8" %>或<meta charset="utf-8">;Servlet 里在输出前执行resp.setCharacterEncoding("UTF-8")。两个都加上最保险,只改一处经常还有一半乱码。

问题二:Tomcat 启动后访问页面报 404。现象是 Tomcat 本身启动了,首页也能开,但访问/login或某页面时 404。原因通常是两个:应用没发布到webapps目录,或者 IDE 部署时上下文路径不对。解决方式是先确认能否访问http://localhost:8080/看到 Tomcat 默认页,能的话说明容器正常,再检查application context是不是少了项目名前缀。

问题三:报Communications link failure或Access denied for user。现象是程序启动后做任何和数据库有关的操作都抛异常。原因一般是数据库没启动,或账号密码授权不足。解决方式是命令行执行mysql -u root -p验证本地账号能登录,再检查DBUtil.java里的 URL 中的localhost:3306是否与你的 MySQL 端口一致。如果本机装了多个 MySQL 实例,3306 可能被更老的那个占用。

问题四:点击登录按钮页面无响应。现象是按钮按下去什么都没有,控制台也不输出异常。这种情况经常是 JavaScript 报错导致提交中断,打开浏览器开发者工具看 Console 面板,常见错误是getElementById返回 null,原因可能是表单元素的 id 写错或脚本在 DOM 渲染前执行。解决方式是确认 HTML 里的 id 和 JS 里的引用完全一致,并且把script标签放到body末尾。

6. 二次开发与验证:把课设作品打磨成能答辩展示的完整项目

6.1 功能回归清单:上线前必须走完的验证路径

一个课设项目在答辩前,至少要过一遍完整的验证路径,避免演示时冷场。按页面顺序来:用预设账号登录,成功进入首页;录入一条新的检测记录,所有字段填写合法值,提交后能在列表页查到新记录;录入一条 pH 为 10 的异常数据,确认页面提示不合格;再试一次空表单提交,确认 JavaScript 拦截不发出请求;最后退出登录,浏览器回退按钮不能重新进入首页——基于 Session 的登录通常天然满足这一点,如果没满足,说明权限控制的过滤链有问题,这也可能是答辩的翻车点。

6.2 低成本加分技巧:用原生 JavaScript 基于已有数据画趋势图

如果想把课设项目的完成度往上拉一个档次,又不想引入 ECharts 这种外部依赖,可以直接用 Canvas 画一个水质指标的走势图。数据来源是检测记录表里某个监测点近几天的 pH 值,按时间排序后在前端绘制折线。这段代码不需要改后端,只在前端新增一个展示页面就行。

function drawTrend(points) { var canvas = document.getElementById("trendChart"); var ctx = canvas.getContext("2d"); var width = canvas.width, height = canvas.height; ctx.clearRect(0, 0, width, height); // 坐标映射:pH 值范围 0-14,映射到画布右侧区域 var stepX = (width - 60) / points.length; ctx.beginPath(); ctx.strokeStyle = "#2d8cf0"; ctx.lineWidth = 2; ctx.moveTo(40, height - 20 - points[0] * (height - 40) / 14); for (var i = 1; i < points.length; i++) { var x = 40 + i * stepX; var y = height - 20 - points[i] * (height - 40) / 14; ctx.lineTo(x, y); } ctx.stroke(); }

这段代码有几个要点:映射公式y = height - 20 - value * (height - 40) / 14里的 20 是底部坐标轴的留白,40 是左侧留白,改这两个值可以调整图表的边距;坐标原点在画布左上角,所以 y 值要翻转,用height -来倒装;clearRect每次先清空画布是必须的,否则重复查询时旧折线和新折线叠加在一起。把这些细节讲清楚,答辩时反而是「我会考虑绘图坐标系转换」的证明。

6.3 建立自己的验证习惯:每次改配置强制走一遍完整链路

我刚做课设的那年吃过一次亏:答辩前一天晚上改了数据库密码,只改了DBUtil.java,自以为没问题,第二天演示时一登录就报错。从那以后我每次改任何一处配置——端口、密码、驱动、上下文路径——都强制走一遍完整链路:启动服务、访问登录页、录入一条数据、查询一条数据、查看日志确认无异常,五个动作全部通过才算完事。这个习惯后来在工作里也让我的联调效率高了不少。这套源码包的价值在于它把前后端和数据库完整地串在了一起,你不需要再为一个登录功能单独找三段代码来拼装,可以照着上面的步骤一路走下来,也能在它的结构上继续改出检测报告导出、按日统计之类的新功能。希望帮到你。

本文还有配套的精品资源,点击获取

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/7 11:19:09

新能源场站全景监控标准解读:从三层架构到次同步振荡与COMTRADE分析

简介&#xff1a;《新能源场站全景监控通用技术规范》&#xff08;Q/GDW 12056—2020&#xff09;是一份指导新能源场站监控系统建设的行业标准&#xff0c;适用于35kV及以上并网的40MW及以上风电场与光伏发电站&#xff0c;规范了全景监控系统的总体架构、功能要求、技术条件及…

作者头像 李华
网站建设 2026/10/7 11:18:46

C#语法糖从本质到实战:自动属性、LINQ与调优技巧

干上位机的朋友&#xff0c;十有八九都翻过网上那些开源串口助手、设备调试工具的源码。我第一次看别人写的C#代码时&#xff0c;心里就一个念头&#xff1a;这玩意儿怎么可以这么短&#xff1f;一个读写PLC数值的小功能&#xff0c;我写了三十行if-else&#xff0c;人家几行就…

作者头像 李华
网站建设 2026/10/7 11:18:46

MES级系统集成架构图设计与落地:从业务边界到避坑指南

简介&#xff1a;企业MES级系统集成架构是制造业信息化规划中的核心参考&#xff0c;本文档面向制造企业IT架构师、MES实施顾问、工厂数字化负责人及系统集成工程师。内容以架构图形式呈现统一门户访问、数据处理层、系统数据采集层、业务系统数据层、运维审计系统、管理运维支…

作者头像 李华
网站建设 2026/10/7 11:18:38

Java在线直播平台源码实战:从环境搭建到压测上线

简介&#xff1a;这是一套基于Java与Spring Boot开发的轻量级在线直播平台完整源码&#xff0c;面向Java后端开发者、全栈学习者及直播类项目实践者&#xff0c;旨在提供可快速部署、二次开发的业务型参考实现。资源包含201个文件&#xff0c;主体为194个Java类&#xff08;涵盖…

作者头像 李华
网站建设 2026/10/7 11:17:51

claude-mem 实战:为对话式 AI 构建持久记忆系统

1. 从“聊完就忘”说起&#xff1a;claude-mem 到底想解决什么如果你用 Claude 这类对话式 AI 做过稍微长一点的项目&#xff0c;大概率遇到过这种尴尬&#xff1a;昨天聊了半小时把架构敲定了&#xff0c;今天开个新会话&#xff0c;它一脸无辜地问你“请问你想做什么项目”。…

作者头像 李华
网站建设 2026/10/7 11:15:05

Agent-Reach 实战:AI Agent 工具调用与 CLI 集成指南

Agent-Reach 这个名字第一次看到的时候&#xff0c;我下意识以为是某个网络代理工具&#xff0c;毕竟"Reach"这个词在技术圈经常和连通性、可达性挂钩。但翻了一圈资料之后发现&#xff0c;它其实是一个面向 AI Agent 的 CLI 工具&#xff0c;核心定位是让 Agent 能够…

作者头像 李华