ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

设备维修管理系统JavaWeb课设源码解析:从Servlet到JDBC的完整实战

设备维修管理系统JavaWeb课设源码解析:从Servlet到JDBC的完整实战 简介设备维修管理系统是一份基于JavaWeb的课程设计/毕设参考源码采用原生Servlet与JDBC实现后端业务与数据访问适合计算机、电子信息等专业学生做项目实践时借鉴。资源包共248个文件压缩后仅2.84MB主要包含Java源码、编译后的class文件、SQL数据库脚本以及前端页面需要的JS、CSS、图片等静态素材其中DAO与Servlet类构成请求处理主线DB脚本可直接用于初始化表结构整体目录清晰方便按模块查阅。目前已有346人学习。开发者可围绕设备报修、维修记录、配件管理等典型业务理解从页面表单到Servlet路由、再到JDBC持久化的完整调用链也可在此基础上替换或新增功能模块作为期末作业或毕业设计的起步框架。1. 设备维修管理系统这套 JavaWeb 课设源码先看懂再动手设备维修管理系统是 JavaWeb 课程设计里出现频率最高的题目之一这包源码正好是原生 Servlet JDBC 的组合没有 Spring 全家桶的封装每个请求怎么走、每张表怎么查都摆在明面上。对于马上要交课程设计或者毕业设计、手头缺一套能跑通的完整代码的人来说这套源码的价值在于它把报修登记、工单生成、维修记录、配件核销、客户管理整条链路都串起来了而且是课设答辩老师最容易接受的经典分层结构。不过拿到压缩包先别急着点运行花十分钟把底层的表结构和请求流转看懂后面会省掉大量排错时间。2. 先读源码再动手从类名看懂整个系统的业务边界2.1 原生 Servlet JDBC 这个组合为什么反而更好答辩很多同学一看到不是 Spring Boot 就有点泄气觉得技术栈老了。但课设答辩和实际生产是两个逻辑。用 Spring Boot老师大概率会追问“框架帮你做了什么事”你答不上来就尴尬。而原生 Servlet 的每个请求都要你自己写 doGet/doPostJDBC 的每个查询都要自己写 Connection、Statement、ResultSet整个数据流是你亲手实现的老师问起来你能从头讲到尾。另一个实际原因是排错方便。框架会把错误藏得很深原生 Servlet 出错就是堆栈直接打在页面上哪儿断了改哪儿。这套源码把 Dao 类和 Servlet 类分得很清楚你拿到手之后先别急着改功能把每个类的名字看一遍业务边界就出来了。2.2 六个 Dao 类的业务映射一张表看懂系统在管什么这个压缩包里的 Dao 类数量不算多但每个都不是摆设。我拆包之后先把这些类按业务重新归了类下面这张表你可以对照着自己的源码看Dao 类对应业务核心职责ReportEquipmentDao报修设备登记设备信息录入、按 ID 查询ReportRecordDao报修记录报修单的提交、状态查询RepairRecordDao维修记录维修结果登记、维修历史查询PartDao配件信息主表配件种类、库存数量维护PartDetailDao配件出入库明细配件领用、消耗流水记录CustomerDao客户信息联系人和联系方式维护这个设计逻辑在课设里属于标准答案级别主表管现状明细表管流水。比如 PartDao 里有一个字段是配件当前库存数PartDetailDao 每次插入一条领用记录同时把 PartDao 里的库存数减掉一张主表加一张流水表的做法答辩时老师问到“库存怎么保证准确”你就可以说是通过两张表一起维护的。2.3 一个请求的完整生命周期从表单到数据库用维修记录提交这个场景来梳理整个链路浏览器提交表单Servlet 接收参数并封装成对象调用 Dao 方法完成数据库操作最后转发或重定向到结果页面。下面这段代码是核心 Servlet 的典型写法你拿到源码后对照着看就清楚了WebServlet(/addRepairRecord) public class AddRepairRecordServlet extends HttpServlet { private RepairRecordDao repairRecordDao new RepairRecordDao(); Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding(UTF-8); // 从请求参数中拿到表单提交的维修信息 Integer reportId Integer.valueOf(request.getParameter(reportId)); String repairContent request.getParameter(repairContent); String repairer request.getParameter(repairer); double cost Double.parseDouble(request.getParameter(cost)); // 封装成实体对象对应数据库的 repair_record 表 RepairRecord record new RepairRecord(); record.setReportId(reportId); record.setRepairContent(repairContent); record.setRepairer(repairer); record.setCost(cost); // 调用 DAO 层完成插入返回受影响行数 int result repairRecordDao.insert(record); if (result 0) { response.sendRedirect(listRepairRecord); } else { request.setAttribute(errorMsg, 添加维修记录失败); request.getRequestDispatcher(/error.jsp).forward(request, response); } } }这段代码有几个地方值得注意。WebServlet注解是 Servlet 3.0 之后的标准写法省掉了 web.xml 里的映射配置课设项目一般都用这个。request.setCharacterEncoding(UTF-8)必须放在读取任何参数之前否则中文必乱。response.sendRedirect是重定向浏览器地址栏会变避免表单重复提交forward是转发地址栏不变通常用在出错提示场景。有一点需要说明源码里的 PutDao 和 Servlet 命名可能与你在压缩包里看到的不完全一致这很正常——打包的人会根据自己当时的设计习惯调整类名。你只需要认准这个规律带 Dao 后缀的类一定操作数据库带 Servlet 后缀的类一定处理 HTTP 请求实体类不带后缀只存属性。3. 环境搭建与部署JDK、Tomcat、MySQL 版本怎么配才不翻车3.1 版本组合选型不是越新越好这套源码用的是原生 Servlet 和 JDBC对运行环境的兼容性其实很强但版本选不对依然会翻车。我最常用的组合是 JDK 1.8 Tomcat 8.5 MySQL 5.7这三个版本是 JavaWeb 课设圈里经过大量验证的稳定组合网上搜得到的调试经验也最多。如果你电脑上已经装了 JDK 17 或更高版本问题也不大但 Tomcat 必须注意Tomcat 10 及以上的版本把javax.servlet换成了jakarta.servlet这套源码里所有的import javax.servlet.*都会直接编译报错。如果你只有 Tomcat 10两个办法一是改所有 import 为jakarta.servlet二是干脆换回 Tomcat 9。我的建议是换 Tomcat 9因为有些老代码里不只是 import还可能在 web.xml 里写了 Servlet 映射牵一发动全身。MySQL 版本的影响主要出在驱动和连接参数上下面会单独说。3.2 IDEA 导入项目与 Tomcat 配置每个步骤的作用用 IDEA 打开源码文件夹会看到一个标准的 JavaWeb 工程结构src目录下是 Java 代码web目录下是 JSP 和静态资源。导入之后最关键的步骤是配置 Artifact 和 Tomcat这一步配错启动 Tomcat 后访问就是 404。# 在 IDEA 中依次点击 # File - Project Structure - Artifacts # 点 号选择 Web Application: Exploded # 在 Available Elements 中把项目所有依赖的 jar 包双击加入 WEB-INF/lib # 配置 Tomcat # Run - Edit Configurations - - Tomcat Server - Local # 选择 Tomcat 安装目录Deployment 选项卡中点击 号 # 选择 ArtifactApplication context 填 /repairArtifact 翻译过来就是“打包产物”IDEA 会把你的源码编译后按 Web 规范组装成一个可部署的目录结构。Exploded 类型是解压目录形式开发时改完代码热部署会快很多。Application context 填/repair意味着你启动后访问的根路径是http://localhost:8080/repair这里不填对Session 和跳转路径可能出问题。配置完成后启动 Tomcat 之前先确认一件事源码里是否已经带了 MySQL 驱动 jar 包。如果没有去 Maven 仓库下载mysql-connector-java-5.1.49.jar对应 MySQL 5.7或mysql-connector-java-8.0.30.jar对应 MySQL 8.0放到 WEB-INF/lib 目录下。放错版本你会在运行时看到ClassNotFoundException而不是编译错误。3.3 数据库初始化建库脚本与 JDBC 连接参数压缩包里如果有 SQL 脚本文件直接导入即可这里说一个判断脚本版本的方法打开 SQL 文件看一眼表名如果表名和 Dao 类名能一一对应上说明脚本和代码是配套的。脚本内容大致长这样CREATE DATABASE IF NOT EXISTS repair_system DEFAULT CHARACTER SET utf8mb4; USE repair_system; -- 设备报修主表 CREATE TABLE report_equipment ( id INT PRIMARY KEY AUTO_INCREMENT, equipment_name VARCHAR(100) NOT NULL, customer_id INT NOT NULL, report_date DATETIME DEFAULT CURRENT_TIMESTAMP, status VARCHAR(20) DEFAULT 待维修, description TEXT ); -- 维修记录表 CREATE TABLE repair_record ( id INT PRIMARY KEY AUTO_INCREMENT, report_id INT NOT NULL, repair_content TEXT, repairer VARCHAR(50), cost DECIMAL(10, 2) DEFAULT 0, repair_date DATETIME DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (report_id) REFERENCES report_equipment(id) ); -- 配件信息表 CREATE TABLE part ( id INT PRIMARY KEY AUTO_INCREMENT, part_name VARCHAR(100) NOT NULL, stock INT DEFAULT 0, price DECIMAL(10, 2) DEFAULT 0 ); -- 配件出入库流水表 CREATE TABLE part_detail ( id INT PRIMARY KEY AUTO_INCREMENT, part_id INT NOT NULL, change_count INT NOT NULL, change_type VARCHAR(20), create_time DATETIME DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (part_id) REFERENCES part(id) );注意DEFAULT CHARSETutf8mb4这是中文存储不出乱码的前提。datetime类型的DEFAULT CURRENT_TIMESTAMP是 MySQL 5.6 之后才支持的如果你用的还是老版本建表可能会报错。数据库建好后找到源码里的 JDBC 连接工具类通常是DBUtil.java或JdbcUtils.java把连接参数改成你本地的账号和密码。如果你用的是 MySQL 8.0除了驱动 jar 版本要换连接 URL 还要加时区参数否则会报Server returns invalid timezone的错误。// MySQL 5.7 写法 Class.forName(com.mysql.jdbc.Driver); String url jdbc:mysql://localhost:3306/repair_system?useUnicodetruecharacterEncodingutf8; // MySQL 8.0 写法注意驱动类名和时区参数 Class.forName(com.mysql.cj.jdbc.Driver); String url jdbc:mysql://localhost:3306/repair_system?useUnicodetruecharacterEncodingutf8serverTimezoneAsia/ShanghaiuseSSLfalse; // 通用的获取连接代码 Connection conn DriverManager.getConnection(url, root, 123456);这里有个占坑比较深的知识点MySQL 5.7 的驱动类名是com.mysql.jdbc.DriverMySQL 8.0 改成了com.mysql.cj.jdbc.Driver如果驱动包版本和类名不匹配报错信息看起来像ClassNotFoundException但实际是版本老化问题。另外useSSLfalse只是关掉 SSL 警告对本地开发没影响。3.4 首次启动验证清单环境配完启动 Tomcat别急着点功能先按下面这张表验证一遍哪儿断了改哪儿验证点操作预期结果项目部署成功访问http://localhost:8080/repair跳转到登录页或首页无 404数据库连接正常打开任意一个列表页页面有数据或正常空态无 500 报错中文显示正常在表单里录入中文并保存列表页显示中文不乱码静态资源加载浏览器 F12 看 Console无红色报错JSP 里的 JS/CSS 正常加载如果哪一步卡住了优先看 IDEA 底部的 Tomcat 日志里面会有完整的 Java 堆栈信息。这一步验证的意义在于把环境问题和代码问题剥离开你才能确定后面改功能时遇到的报错是代码逻辑引起的不是环境引起的。很多同学拿到源码启动后直接报错就慌了其实八成是上面说的版本或参数问题。4. 核心流程拆解报修、派单、维修、配件核销怎么串起来4.1 工单生成GenerateCheckServlet 做了什么GenerateCheckServlet这个名字里的Check可以理解成“检查/工单”它的职责是把客户报修的信息转换成一个正式的报修单同时写入报修主表和报修记录表。这个 Servlet 是整条业务链的入口后面维修、配件操作都要拿着这个报修单的 ID 继续往下走。WebServlet(/generateCheck) public class GenerateCheckServlet extends HttpServlet { private ReportEquipmentDao reportDao new ReportEquipmentDao(); private ReportRecordDao recordDao new ReportRecordDao(); Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding(UTF-8); // 从报修表单页面收集设备与客户信息 String equipmentName request.getParameter(equipmentName); Integer customerId Integer.valueOf(request.getParameter(customerId)); String description request.getParameter(description); // 先插入设备主表拿到自增主键 ReportEquipment equipment new ReportEquipment(); equipment.setEquipmentName(equipmentName); equipment.setCustomerId(customerId); equipment.setDescription(description); int equipmentId reportDao.insert(equipment); // 再插入报修记录表主表与记录表通过 equipmentId 关联 ReportRecord record new ReportRecord(); record.setEquipmentId(equipmentId); record.setStatus(待维修); recordDao.insert(record); // 完成后跳转到待维修任务列表 response.sendRedirect(queryPendingTasks); } }这里最值得学习的是“先插主表拿自增 ID再插记录表做关联”的顺序。自增主键在插入后能从PreparedStatement.getGeneratedKeys()里取出来如果不取你就要先去查一次多一次查询逻辑还容易查错。有些新手会直接把设备名和客户名都塞进记录表看起来省事但后续客户换了联系方式你就只能改记录表里那一堆冗余字段而不是改客户表一处。4.2 维修记录闭环RepairRecordDao 的增删改查维修工拿到报修单后需要登记“修了什么、谁修的、花了多少钱、用了哪些配件”。这部分逻辑全在RepairRecordDao里。它的核心不是单个insert方法而是和配件明细的联动// RepairRecordDao 里插入一条维修记录同时扣减配件库存 public int insertWithParts(RepairRecord record, ListPartDetail partDetails) { Connection conn null; PreparedStatement ps null; PreparedStatement psPart null; ResultSet rs null; int result 0; try { conn DBUtil.getConnection(); // 关键点开启事务维修记录和配件扣减要么都成功要么都回滚 conn.setAutoCommit(false); String sqlRecord INSERT INTO repair_record (report_id, repair_content, repairer, cost) VALUES (?, ?, ?, ?); ps conn.prepareStatement(sqlRecord, Statement.RETURN_GENERATED_KEYS); ps.setInt(1, record.getReportId()); ps.setString(2, record.getRepairContent()); ps.setString(3, record.getRepairer()); ps.setDouble(4, record.getCost()); ps.executeUpdate(); result 1; // 遍历配件明细逐条扣减库存 String sqlPart INSERT INTO part_detail (part_id, change_count, change_type) VALUES (?, ?, ?); String sqlUpdate UPDATE part SET stock stock - ? WHERE id ? AND stock ?; for (PartDetail detail : partDetails) { psPart conn.prepareStatement(sqlPart); psPart.setInt(1, detail.getPartId()); psPart.setInt(2, detail.getChangeCount()); psPart.setString(3, 领用); psPart.executeUpdate(); // 扣库存时带上库存充足条件防止库存扣成负数 psPart conn.prepareStatement(sqlUpdate); psPart.setInt(1, detail.getChangeCount()); psPart.setInt(2, detail.getPartId()); psPart.setInt(3, detail.getChangeCount()); int rows psPart.executeUpdate(); if (rows 0) { throw new RuntimeException(配件库存不足回滚整笔维修记录); } } conn.commit(); } catch (Exception e) { if (conn ! null) { try { conn.rollback(); } catch (SQLException ex) { ex.printStackTrace(); } } e.printStackTrace(); } finally { // 先关结果集和语句再关连接顺序反了会报错 DBUtil.close(rs, psPart, conn); } return result; }这段代码里面有三个值得记进脑子里的习惯。第一是conn.setAutoCommit(false)手动开事务维修记录和库存扣减只要有一个失败整个操作回滚不会再出现“维修单记了但库存没减”这种账实不符。第二是扣库存的 UPDATE 语句里加了AND stock ?条件如果库存不够这次更新影响行数是 0代码主动抛异常回滚而不是让库存变成负数。第三是 finally 块里对psPart和conn的统一关闭老实说很多课设源码这一步都是走个形式甚至漏关但实际项目里连接不关跑个几十次就能把连接池撑爆页面直接卡死。4.3 配件管理PartDao 与 PartDetailDao 的主从表配合PartDao只管配件主数据管“目前有哪些配件、各剩多少”PartDetailDao管流水管“哪个维修单用了哪个配件、用了多少、什么时候领的”。这种主从表结构在答辩时非常好讲老师问怎么查库存你直接说主表查余额明细表查流水谁也替代不了谁。-- 查某个配件的当前库存走主表 SELECT part_name, stock, price FROM part WHERE id ?; -- 查某个配件的出入库流水走明细表 SELECT change_count, change_type, create_time FROM part_detail WHERE part_id ? ORDER BY create_time DESC LIMIT 20;如果你的源码里 PartDetailDao 只有 insert 方法而没有查询方法那说明这套代码只实现了“领用配件”这个方向的流水没有做“采购入库”的反向操作。这在课设里是允许的但你自己扩展的时候要把两条流水的方向都补上领用时change_type为“领用”库存减少入库时change_type为“入库”库存增加。库存恢复靠入库而不是反向改维修记录这个思路一定要从一开始就立住不然改着改着就把系统改成一本糊涂账。4.4 查询已完成任务QueryCompletedTasksServlet 的条件拼接QueryCompletedTasksServlet这个名字很直白就是把状态为“已完成”的报修单捞出来展示。它的实现逻辑里有一个在课设里很常见的坑——手工拼接 SQL 条件你拿到源码后可以注意一下这块是怎么写的WebServlet(/queryCompletedTasks) public class QueryCompletedTasksServlet extends HttpServlet { private ReportEquipmentDao reportDao new ReportEquipmentDao(); Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding(UTF-8); // 可选过滤条件设备名称模糊查询 String equipmentName request.getParameter(equipmentName); // 可选过滤条件客户 ID String customerId request.getParameter(customerId); // 使用 StringBuilder 动态拼接 SQL注意每个条件前都要加空格 StringBuilder sql new StringBuilder(SELECT * FROM report_equipment WHERE status 已完成); if (equipmentName ! null !equipmentName.trim().isEmpty()) { sql.append( AND equipment_name LIKE ?); } if (customerId ! null !customerId.trim().isEmpty()) { sql.append( AND customer_id ?); } sql.append( ORDER BY report_date DESC); // 执行查询并封装结果 ListReportEquipment list reportDao.queryByCondition(sql.toString(), equipmentName, customerId); request.setAttribute(finishedTaskList, list); request.getRequestDispatcher(/finishedTaskList.jsp).forward(request, response); } }动态条件拼接里最容易翻车的不是逻辑而是 SQL 字符串里少了空格。比如第一个条件拼接完末尾是已完成你直接写AND不加空格拼出来就是已完成ANDSQL 语法直接报错。另外这里用了占位符?而不是把参数直接拼进字符串这是好习惯能挡住一部分 SQL 注入。如果源码里是直接字符串拼接参数改功能的时候顺手改成PreparedStatement是性价比最高的安全改造。然后注意一个小细节这个 Servlet 末尾用的是forward而不是sendRedirect因为要把查出来的finishedTaskList带给 JSP 渲染。如果用重定向request 里的数据会丢页面拿到的是空列表。5. 避坑指南课设项目最常见的五个翻车现场5.1 一启动就编译报错javax.servlet 不存在现象IDEA 里所有import javax.servlet.*的代码行标红编译失败。原因你装的是 Tomcat 10 或更高版本Servlet 规范从javax迁移到了jakarta命名空间老代码的 import 全部失效。这个坑在网上下载的老课设源码里出现频率特别高因为很多资源是 2020 年之前打包的那时候 Tomcat 9 是主流。解决最省事的方法是去下载 Tomcat 9.0.x然后把 IDEA 里的 Tomcat Server 重新指向新目录。如果只用 Tomcat 10就得手动把所有javax.servlet改成jakarta.servlet注意不只是 importweb.xml 头部的命名空间也要改工作量大且容易漏。5.2 数据库驱动报错ClassNotFoundException 连环炸现象启动 Tomcat 后点任何需要查库的功能页面直接 500 错误日志里写着java.lang.ClassNotFoundException: com.mysql.jdbc.Driver。原因驱动 jar 版本和 MySQL 服务端版本不匹配或者驱动 jar 根本没放进 WEB-INF/lib 目录Tomcat 运行时找不到类。这个问题和代码本身无关纯粹是依赖缺失。解决先确认 MySQL 服务端版本5.7 用mysql-connector-java-5.1.49.jar8.0 用mysql-connector-java-8.0.30.jar。放进web/WEB-INF/lib目录后IDEA 里右键该 jar选择 Add as Library确保 Artifact 重新打包。5.3 页面中文全变问号编码问题现象表单提交中文后列表页显示???或乱码。原因三层编码不一致——浏览器发送的编码、Servlet 读取参数的编码、数据库存储的编码。缺一不可。常见情况是 Servlet 里忘了request.setCharacterEncoding(UTF-8)或者数据库表不是utf8mb4。解决在 Servlet 的 doPost 第一行加request.setCharacterEncoding(UTF-8)在 JDBC URL 里加useUnicodetruecharacterEncodingutf8建库时指定DEFAULT CHARSETutf8mb4。三层统一后这个锅基本就甩不掉了。5.4 页面越跑越慢最后点击没反应现象刚启动时一切正常操作几十次后页面请求越来越慢最后干脆卡死重启 Tomcat 又好了。原因数据库连接没关。有些源码里conn.close()只写在成功分支异常分支漏了关连接池或默认连接资源被耗尽新的查询拿不到连接全部阻塞在获取连接那一步。这是课设源码里最常见也最隐蔽的坑因为不是每次操作都报错是次数累积到一定程度才发作。解决用 try-with-resources 或统一的 finally 关闭模板确保 ResultSet、Statement、Connection 三个对象无论成功失败都关闭。我的习惯是写一个DBUtil.close(rs, ps, conn)工具方法所有 Dao 方法最后都只调这一句。5.5 启动 Tomcat 后访问 404现象Tomcat 启动日志没有报错但浏览器访问项目路径时显示 404。原因IDEA 里没有把 Artifact 部署到 Tomcat或者 Application context 配的和访问路径不一致。Tomcat 启动成功不代表你的项目部署成功这是两件事。解决Run - Edit Configurations - Tomcat Server - Deployment确认 Deployment 列表里有这个项目的 Artifact。既然右键点了 Run只要上下文是/repair访问路径就是http://localhost:8080/repair别多写或少写一层路径。6. 从能跑到能答辩四个低成本改造让项目上一个档次6.1 给报修单加一个状态机现在源码里的状态大概率就是一个字符串字段待维修、已完成之类。你可以把它升级成一个整型字段定义0-待派单、1-维修中、2-已完成、3-已取消在状态流转的入口加校验// 非法状态流转直接拒绝已完成不能跳回维修中 if (currentStatus 2 targetStatus 1) { throw new IllegalStateException(已完成工单不能重新进入维修状态); }这个改动很小但答辩时你能讲出“状态流转控制”这个点和单纯改字段完全是两个层次。6.2 用 Filter 做登录拦截课设项目九成没有权限控制你加一个最基础的登录拦截就赢了。写一个LoginFilter在doFilter里判断 Session 里有没有登录用户没有就重定向到登录页public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) { HttpServletRequest req (HttpServletRequest) request; HttpServletResponse resp (HttpServletResponse) response; Object user req.getSession().getAttribute(loginUser); if (user null) { resp.sendRedirect(req.getContextPath() /login.jsp); return; } chain.doFilter(request, response); }记得在 web.xml 或注解里配置拦截路径为/*但放行/login.jsp和登录处理 Servlet。6.3 把 SQL 拼接改成 PreparedStatement如果源码里有字符串拼接 SQL 的地方全部改成PreparedStatement参数占位。这既是安全改造也方便你加条件查询。改完之后你可以在答辩时主动提一句“参数都是预编译绑定的”这是个加分点。6.4 加一个按周统计维修量的报表在 Dao 里加一个统计方法按周分组统计维修单数量结果用ListMapString, Object返回JSP 页面上用表格展示SELECT DATE_FORMAT(repair_date, %Y-%u) AS week_num, COUNT(*) AS total FROM repair_record GROUP BY week_num ORDER BY week_num DESC LIMIT 10;改动量不大但你的系统从“能增删改查”变成了“能看数据趋势”课设报告里多一个亮点。我从这套源码里最大的收获不是它跑了多少功能而是它让我明白原生 ServletJDBC 这个组合把每个环节都暴露在阳光下没有框架替你遮掩。以前我拿到课设源码先跑通就急着交差后来答辩被老师问到“库存扣减失败怎么办”直接卡住——从那以后我每次拿到别人的 JavaWeb 项目都强制自己先把每个请求走一遍把事务边界画出来再动环境。这四个改造做完这套源码就不只是能交差而是能讲出东西。希望帮到你。本文还有配套的精品资源点击获取
返回列表