ARTICLE DETAIL

资讯详情

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

学生信息管理系统Java课设:从JDBC分页到答辩避坑全指南

学生信息管理系统Java课设:从JDBC分页到答辩避坑全指南 简介《学生信息管理系统》程序资源包面向学校教务部门、教师及初学者围绕学生信息录入、查找、删除、修改、排序、统计与显示等核心操作展开可帮助用户高效处理日常教务数据也适合作为课程设计、毕业设计或入门项目的参考。资源以zip压缩包形式提供共4个文件包含2份doc文档分别对应程序使用说明与配置说明、1个可直接运行的exe可执行程序以及1份py源程序整体仅5.96MB结构清晰、便于学习。截至目前已有142人学习下载。通过源码与配套文档读者可以实际学习数据库INSERT、UPDATE、SELECT等语句的运用理解查找、排序等算法在真实程序中的落地以及删除操作如何维护数据完整性和一致性也可直接运行exe体验完整流程再对照源码逐段分析有助于快速掌握小型管理系统从界面设计到业务逻辑的实现思路。1. 学生信息管理系统为什么代码会写了答辩还是翻车拿到《学生信息管理系统》的课程设计任务和一份“包含源码”的程序包大多数人第一反应是增删改查嘛跑起来录几条学生信息就行。但真正到了验收或答辩现场翻车的恰恰是那些看起来简单的点——分页第二页数据乱跳、中文变成问号、换台电脑就起不来老师随口问一句“你删掉的学号还能不能再录进来”你才发现自己用的是物理删除。这篇笔记按最常见的 Java 课程设计形态来讲Swing 桌面端 MySQL JDBC把技术栈选择、工程骨架、建表、连接层、登录、分页、批量导入和避坑一条线走完。适合正在做课程设计的学生也适合要把一堆零散源码整理成可交付程序的新手。2. 做这个程序前必须先定的三件事技术栈、工程骨架和源码目录2.1 三种技术栈怎么选Java Swing、Python Tkinter 还是 Web 版任何一套学生信息管理系统都绕不开“界面、业务、数据库”三层。先别急着写实体类先回答三个问题程序跑在哪、数据库用什么、答辩环境允不允许联网。这三件事直接决定后面是顺利收尾还是反复返工。技术栈典型场景课设风险我的建议Java Swing JDBC MySQL桌面课设单机演示依赖 JDK 和 MySQL 环境最稳逻辑全部在同一个 JVM 里便于答辩讲解Python Tkinter SQLitePython 课设轻量演示SQLite 和 MySQL 语法有差异换库要改 SQL适合没装 MySQL 的机器但不够“像企业项目”JavaWebServlet/JSP MySQLWeb 课设要装 Tomcat前端样式容易失控如果想引 MyBatis 加分复杂度会明显上升微信小程序 / 前后端分离展示型项目需要后端服务常驻演示链路长不推荐作为单门课设的主交付物网上找“java课程设计案例源码”或“php源码”能搜到大量同名项目但质量参差。常见问题是代码能编译却跑不通、数据库脚本缺失、依赖 jar 不完整。你会搜到的还有“免费python源码大全”里各类 Python 版学生管理系统大多用 Tkinter 或 Flask 写选型本身没问题但往往没有测试数据也没有打包说明真正跑起来才是分水岭。所以这篇笔记以 Java Swing 为例展开如果你拿到的源码是 Python 或 PHP后面关于建表、登录、分页、避坑的思路一样能用。2.2 初始化 Maven 工程一张能直接照抄的目录结构拿到手的第一件事不是双击运行而是把源码目录摊开看。如果 .java、.jar、.sql 全堆在一个文件夹里直接重建骨架别犹豫。这种“平面结构”后期改一个查询都要全局翻文件更别说在答辩时跟老师讲清楚模块划分。student-info-system/ ├── pom.xml ├── src/ │ ├── main/ │ │ ├── java/com/course/stu/ │ │ │ ├── App.java # 程序入口只负责启动 │ │ │ ├── ui/ # Swing 界面层 │ │ │ ├── service/ # 业务逻辑层 │ │ │ ├── dao/ # 数据访问层 │ │ │ ├── entity/ # 实体类 │ │ │ └── util/ # DBUtil、PasswordUtil 等 │ │ └── resources/ │ │ ├── jdbc.properties │ │ └── log4j2.xml │ └── test/java/ ├── sql/ │ ├── schema.sql │ └── data.sql └── README.md这套结构的好处是各层职责一眼能看出来UI 不写 SQLDAO 里不弹窗口service 夹在中间做校验和事务。App.java 只做一件事——初始化界面。测试数据统一放 sql/data.sql数据库建好后执行一次就有几十条学生记录可演示省去录入时间。我一般会在 README 里写清楚三件事JDK 版本、MySQL 版本、从建库到启动的五个步骤。很多源码包没有 README等于把“如何跑起来”的成本全部甩给了使用者这是最容易被扣分的地方。2.3 pom.xml 里的五个关键坐标驱动、版本和打包方式Maven 不是课设强制要求但建议用。它能帮你固定依赖版本更重要的是能打出“带依赖的可执行 jar”。否则你本机能跑把源码发给同学或考到答辩电脑上就报 NoClassDefFoundError。properties maven.compiler.source8/maven.compiler.source maven.compiler.target8/maven.compiler.target /properties dependencies dependency groupIdmysql/groupId artifactIdmysql-connector-java/artifactId version8.0.33/version /dependency dependency groupIdcom.opencsv/groupId artifactIdopencsv/artifactId version5.9/version /dependency /dependencies build plugins plugin groupIdorg.apache.maven.plugins/groupId artifactIdmaven-shade-plugin/artifactId version3.5.1/version executions execution phasepackage/phase goalsgoalshade/goal/goals /execution /executions configuration transformers transformer implementationorg.apache.maven.plugins.shade.resource.ManifestResourceTransformer mainClasscom.course.stu.App/mainClass /transformer /transformers /configuration /plugin /plugins /build几个参数别乱改。maven.compiler.source和target固定成 8是防止本机 JDK 17 编译出的 class 文件在老师旧 JDK 上跑不起来。mysql-connector-java 的版本要跟着数据库走MySQL 5.7 用 5.x 驱动MySQL 8 用 8.0.x两者驱动类名不一样。shade 插件负责把 MySQL 驱动和 opencsv 全部打进同一个 jar这样java -jar时不需要额外配 classpath。如果只是批量导入 CSV用 opencsv 比 POI 干净得多。POI 读写 .xlsx 功能强但依赖体积大、API 复杂课设里非要用 Excel 文件再考虑它。3. 学生表与登录表的设计把数据库建成不用返工的样子3.1 建表 SQL 里必须有的五个字段学号索引、软删除、时间戳“建表”看起来是体力活但大部分返工都出在表结构上。很多初版设计只有 student_no、name、gender、class_name 四个字段等做到“删除学生”和“批量导入”时才发现学号重复检查做不了、删除后无法恢复、搜索班级没有索引。下面这份 SQL 是常见的课设落地方案可以直接执行CREATE DATABASE stu_info DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; USE stu_info; CREATE TABLE student ( id BIGINT PRIMARY KEY AUTO_INCREMENT, student_no VARCHAR(20) NOT NULL COMMENT 学号, name VARCHAR(50) NOT NULL, gender TINYINT NOT NULL DEFAULT 1 COMMENT 1男 0女, birthday DATE, phone VARCHAR(20), class_name VARCHAR(50), created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, deleted BIGINT NOT NULL DEFAULT 0 COMMENT 0未删除删除时写入id, UNIQUE KEY uk_student_no (student_no, deleted), KEY idx_class_name (class_name) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4; CREATE TABLE sys_user ( id BIGINT PRIMARY KEY AUTO_INCREMENT, username VARCHAR(50) NOT NULL UNIQUE, salt VARCHAR(32) NOT NULL, password_hash VARCHAR(64) NOT NULL, role VARCHAR(20) NOT NULL DEFAULT admin ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;重点说说deleted字段。这里的 deleted 不是常用的 TINYINT 0/1而是 BIGINT默认 0。逻辑删除执行的是UPDATE student SET deleted id WHERE id ?。配合唯一索引uk_student_no (student_no, deleted)可以保证同一学号在“未删除”状态只能存在一条已删除的旧记录因为 deleted 等于各自 id互不冲突学号可以重新录入。这是逻辑删除里一个很容易踩的设计细节如果 deleted 固定写 1同一学号删除两次就会触发唯一键冲突。created_at和updated_at建议加上虽然增删改查里用不到但答辩时展示数据变化时间或者排查重复录入都靠它。class_name 加普通索引是因为按班级筛选是最常见的查询路径否则数据量到几千条后全表扫描会很慢。字符集统一 utf8mb4排序规则用 utf8mb4_unicode_ci避免中文排序和比对出问题。3.2 JDBC 连接层把数据库账号密码从代码里挪出去你会见到很多课设源码把数据库用户名密码直接写在 DBUtil 类里像这样DriverManager.getConnection(url, root, 123456)。在本机跑没问题可一旦源码发给别人、或者放到答辩电脑上改密码就得重新编译。更麻烦的是代码评审老师一眼就会问配置和代码为什么不分离正确做法是把连接信息放 resources 下的 jdbc.propertiesjdbc.drivercom.mysql.cj.jdbc.Driver jdbc.urljdbc:mysql://localhost:3306/stu_info?useUnicodetruecharacterEncodingutf8useSSLfalseserverTimezoneAsia/ShanghaiallowPublicKeyRetrievaltrue jdbc.usernameroot jdbc.password123456然后写一个静态工具类package com.course.stu.util; import java.io.InputStream; import java.sql.Connection; import java.sql.DriverManager; import java.util.Properties; public class DBUtil { private static String url; private static String username; private static String password; static { try (InputStream in DBUtil.class.getClassLoader() .getResourceAsStream(jdbc.properties)) { Properties props new Properties(); props.load(in); Class.forName(props.getProperty(jdbc.driver)); url props.getProperty(jdbc.url); username props.getProperty(jdbc.username); password props.getProperty(jdbc.password); } catch (Exception e) { throw new ExceptionInInitializerError(初始化数据库连接失败请检查 jdbc.properties); } } public static Connection getConnection() throws Exception { return DriverManager.getConnection(url, username, password); } }这段代码里有几个参数值得注意。characterEncodingutf8决定 JDBC 与 MySQL 之间用 UTF-8 传输中文少了它最容易出现乱码。serverTimezoneAsia/Shanghai是因为 MySQL 8 的 JDBC 驱动会校验时区不设置可能直接抛异常。allowPublicKeyRetrievaltrue主要用于 MySQL 8 默认的 caching_sha2_password 认证插件下首次连接获取公钥加了之后能少一类“Public Key Retrieval is not allowed”的报错。用类加载器读取 properties而不是用文件绝对路径好处是打包成 jar 后资源依然能被读到。如果以后想换数据库比如切到 SQLite只需要改 properties不用动 Java 代码。3.3 用 PreparedStatement 代替 Statement一个参数位省掉整张表的灾难课设源码里最常见的坏味道是字符串拼接 SQLStatement stmt conn.createStatement(); stmt.executeQuery(SELECT * FROM student WHERE name name );这种写法的直接后果是姓名里带单引号就报错更严重的是存在 SQL 注入风险。老师只要演示一次在搜索框输入 or 11整个表的数据就被拖出来场面很难看。不要赌答辩老师不会试用 PreparedStatement 成本极低。public Student findByStudentNo(String studentNo) throws Exception { String sql SELECT id, student_no, name, gender, birthday, class_name FROM student WHERE student_no ? AND deleted 0; try (Connection conn DBUtil.getConnection(); PreparedStatement ps conn.prepareStatement(sql)) { ps.setString(1, studentNo); try (ResultSet rs ps.executeQuery()) { if (rs.next()) { Student s new Student(); s.setId(rs.getLong(id)); s.setStudentNo(rs.getString(student_no)); s.setName(rs.getString(name)); s.setGender(rs.getInt(gender)); s.setBirthday(rs.getDate(birthday)); s.setClassName(rs.getString(class_name)); return s; } } } return null; }?占位符配合setStringJDBC 驱动会负责转义特殊字符参数永远不会被当成 SQL 指令执行。try-with-resources 写法保证 Connection、PreparedStatement、ResultSet 在退出 try 块时自动关闭避免连接泄漏。对于程序长时间开着的桌面应用连接泄漏会导致运行几个小时后突然报“Too many connections”这是很典型的隐藏故障。需要说明的是这里每次查询都新建连接在“课设规模”几百人、单机演示下完全够用。如果以后数据量上来或要做 Web 版再考虑引入连接池比如 HikariCP。课设阶段不要为了炫技引入一堆框架核心 SQL 都走 PreparedStatement已经能体现工程意识了。4. 登录、分页、批量导入三个让源码“有含金量”的功能模块4.1 登录校验再也不要拿明文密码去数据库比对学生信息管理系统一般都有登录窗口。最常见的翻车写法是注册时把密码原样存进数据库登录时执行SELECT * FROM sys_user WHERE username ? AND password ?。问题是数据库一旦被导出所有账号等于裸奔而且只要在演示时打开数据库表老师看到明文密码印象分会直接掉一档。不要自己去发明加密算法。常见的做法是“随机盐 SHA-256”。每次注册都生成一个随机盐把盐和密码拼起来做哈希盐本身明文存在用户表里。登录时取出盐对输入密码做同样的哈希再比较结果。package com.course.stu.util; import java.nio.charset.StandardCharsets; import java.security.MessageDigest; public class PasswordUtil { public static String hashPassword(String rawPassword, String salt) throws Exception { MessageDigest md MessageDigest.getInstance(SHA-256); md.update(salt.getBytes(StandardCharsets.UTF_8)); byte[] hashed md.digest(rawPassword.getBytes(StandardCharsets.UTF_8)); StringBuilder sb new StringBuilder(); for (byte b : hashed) { sb.append(String.format(%02x, b)); } return sb.toString(); } }登录时的校验逻辑建议放在 service 层而不是 UI 层public boolean checkLogin(String username, String rawPassword) throws Exception { User user userDao.findByUsername(username); if (user null) { return false; } String actual PasswordUtil.hashPassword(rawPassword, user.getSalt()); return actual.equals(user.getPasswordHash()); }代码里每一步都有目的。先查用户而不是先讲密码是为了避免通过报错信息暴露“用户不存在”。盐每人不同即使两个用户密码相同哈希结果也不一样。为什么不用 MD5因为 MD5 计算速度太快配合彩虹表很容易被批量破解SHA-256 在课设场景下已经足够没必要再引 Spring Security。4.2 分页查询LIMIT 的偏移量为什么要自己算而不是猜分页是很多新手源码的“重灾区”。功能看起来正常但代码里用的是LIMIT page * pageSize。比如每页 10 条第一页应该取 0 到 9第二页如果从 10 开始那么第一页的第 10 条其实没被展示而第二页第 1 条正是它——数据被跳过了一行。正确公式是offset (page - 1) * pageSize。也就是第一页从头开始第二页跳过前 10 条。除此之外分页查询还必须带稳定的 ORDER BY否则 MySQL 返回顺序不固定翻页时会出现重复或遗漏。public PageResultStudent pageStudents(int page, int pageSize, String keyword) throws Exception { if (page 1) page 1; if (pageSize 100) pageSize 100; int offset (page - 1) * pageSize; String where WHERE deleted 0; if (keyword ! null !keyword.trim().isEmpty()) { where AND (student_no LIKE ? OR name LIKE ?); } String countSql SELECT COUNT(*) FROM student where; String dataSql SELECT id, student_no, name, gender, birthday, class_name FROM student where ORDER BY id DESC LIMIT ?, ?; try (Connection conn DBUtil.getConnection()) { long total 0; try (PreparedStatement ps conn.prepareStatement(countSql)) { if (keyword ! null !keyword.trim().isEmpty()) { String like % keyword.trim() %; ps.setString(1, like); ps.setString(2, like); } ResultSet rs ps.executeQuery(); if (rs.next()) { total rs.getLong(1); } } ListStudent list new ArrayList(); try (PreparedStatement ps conn.prepareStatement(dataSql)) { if (keyword ! null !keyword.trim().isEmpty()) { String like % keyword.trim() %; ps.setString(1, like); ps.setString(2, like); } ps.setInt(3, offset); ps.setInt(4, pageSize); ResultSet rs ps.executeQuery(); while (rs.next()) { // 映射 Student 对象并加入 list } } return new PageResult(total, list); } }注意两个 PreparedStatement 里的参数位置。count 语句先绑两个 LIKE 参数data 语句里同样是两个 LIKE 参数在前LIMIT 的 offset 和 pageSize 排在第 3、第 4 位。很多人只在 count 里绑了参数data 里忘了绑或者把偏移量和 pageSize 顺序写反运行时报Parameter index out of range。分页结果对象里至少包含 total 和 list。total 用于界面显示“共 N 条共 M 页”也是计算“下一页是否可用”的依据。page total / pageSize时按钮应该置灰。这套逻辑不复杂但能避免用户翻到空白页。4.3 批量导入Excel 行号、空值与重复学号的三个边界检查“批量导入学生名单”是课设源码里最能体现完整性的功能。老师通常会在答辩现场要求导入一份新的班级名单如果源码只能手工录入就少了一个亮点。常见的做法是用 opencsv 解析 CSV如果学校提供的模板是 .xlsx再考虑引入 POI。下面这段代码是 CSV 导入的核心骨架public int importStudents(File file) throws Exception { int successCount 0; try (CSVReader reader new CSVReader( new InputStreamReader(new FileInputStream(file), StandardCharsets.UTF_8))) { ListString[] rows reader.readAll(); if (rows.isEmpty()) { throw new IllegalArgumentException(文件为空); } for (int i 1; i rows.size(); i) { String[] row rows.get(i); if (row.length 4) { continue; } String studentNo row[0].trim(); String name row[1].trim(); if (studentNo.isEmpty() || name.isEmpty()) { continue; } if (!studentNo.matches(\\d{5,20})) { throw new IllegalArgumentException(第 (i 1) 行学号格式错误: studentNo); } if (studentDao.existsByStudentNo(studentNo)) { throw new IllegalArgumentException(第 (i 1) 行学号重复: studentNo); } studentDao.insertStudent(row); successCount; } } return successCount; }三个边界检查缺一不可。第一个是跳过表头i从 1 开始因为第 0 行是表头如果不跳第一行数据会被当成学号写进库。第二个是空行和字段不足有些表格末尾会有空行直接跳过而不是报错中断。第三个是重复学号插入前调用existsByStudentNo检查deleted 0的记录里是否已存在同样学号避免数据库唯一键冲突。报错信息里的行号必须用i 1。因为rows的索引从 0 开始但用户打开 CSV 看到的第一行是表头第二行才是第一条数据。你定位到 rows 的第 5 行文件里其实是第 6 行差一行会让使用者找半天。这类细节正是课设源码和“能交付的源码”之间的差距。导入大批量数据时还要考虑事务。比如 500 行数据第 300 行格式错误如果前面 299 行已经插入数据库就处于一半成功一半失败的状态。常见做法是整体回滚或者收集错误行号最后统一反馈。整体回滚的写法很固定Connection conn DBUtil.getConnection(); conn.setAutoCommit(false); try { // 循环插入 conn.commit(); } catch (Exception e) { conn.rollback(); throw e; } finally { conn.setAutoCommit(true); conn.close(); }把setAutoCommit(false)放在 try 块之前commit 放在循环全部结束后任何一个插入失败都会触发 rollback。这一步在答辩里很加分因为很多人连“事务是什么”都答不清楚。5. 学生信息管理系统避坑清单从跑不起来到答辩被问倒这章是我最想让你先看的部分。很多学生信息管理系统源码本身逻辑没问题真正让项目翻车的是环境、编码和外键这些细节。每一条都按现象、原因、解决来写对照着排查。5.1 连不上数据库驱动类找不到和认证失败是两回事现象程序启动后第一次点登录就报ClassNotFoundException: com.mysql.jdbc.Driver或者用户名密码都对却报Access denied for user rootlocalhost。原因驱动类名用错了。MySQL 5.x 时代的驱动类是com.mysql.jdbc.DriverMySQL 8 之后它被废弃新驱动类在com.mysql.cj.jdbc.Driver包下。还有另一种情况pom.xml 里写的驱动版本和本地 MySQL 服务器版本差异过大导致认证插件对不上。解决先确认jdbc.properties里 driver 和 pom 依赖版本匹配。MySQL 8 就用com.mysql.cj.jdbc.Driver加 8.0.x 驱动。连接串里建议保留useSSLfalseallowPublicKeyRetrievaltrue。如果是在本机开发不要用 localhost 之外的主机名避免 host 解析问题。5.2 中文乱码连接串里少了 characterEncoding 全表变问号现象界面和数据库里的中文全部变成??或者英文正常、中文乱码。往库里插入一段中文用命令行查看也是乱码。原因数据库字符集、连接串字符集、代码文件字符集三层没有统一。很多老教程用 GBK 建库或者连接串里不写characterEncodingJDBC 会按服务器默认字符集传输一旦默认不是 UTF-8 就会乱。解决数据库、表、列都用 utf8mb4连接串加characterEncodingutf8统一后的标准写法就是 3.2 节那份 jdbc.properties。另外源码文件本身要用 UTF-8 保存如果 IDE 默认是 GBK字符串常量也会变成乱码。判断时先用数据库命令行工具直接插一条中文如果能正常显示说明代码没问题问题在连接串。5.3 删除学生时外键卡住或把成绩表一起删没物理删除与级联删除现象执行DELETE FROM student WHERE id ?时报Cannot delete or update a parent row: a foreign key constraint fails。或者为了省事给外键加了ON DELETE CASCADE删掉一个学生后成绩表里他的所有记录也被连带删除。原因如果有成绩表或选课表外键指向 student.id主表记录就不能随便物理删除。CASCADE 看起来很顺手但它把“删除学生”变成了“清除该学生一切痕迹”答辩时老师问到数据完整性很难解释为什么历史成绩消失了。解决采用第 3 章设计的逻辑删除。删除学生时执行UPDATE student SET deleted id WHERE id ? AND deleted 0所有查询默认加AND deleted 0。如果系统确实允许物理删除也应该先删除子表记录再删除主表并且放在一个事务里。这是课设源码里最容易暴露设计缺陷的地方。5.4 换一台电脑就起不来Could not find or load main class 与环境变量现象源码在本机跑得挺好用 maven 打成 jar 后到答辩电脑执行java -jar xxx.jar报Could not find or load main class或者直接闪退连错误信息都看不到。原因没有使用 shade 插件打包出的 jar 里没有 MySQL 驱动和 opencsv 这些依赖或者 mainClass 配置指向了不存在的类。还有一种常见情况目标电脑根本没装 JRE双击 bat 文件就一闪而过。解决pom.xml 里配好 maven-shade-plugin指定mainClass为com.course.stu.App执行mvn clean package。启动脚本加一行pause让窗口停住报什么错都能看清echo off java -jar target\student-info-system.jar pause如果目标电脑连 JDK 都没有再多源码也白搭。交交付物清单时把 JDK 版本写进 README最稳妥的做法是演示前先到答辩机器上跑一遍启动脚本。5.5 分页第二页数据乱跳排序字段不稳定造成的重复与丢失现象第一页和第二页出现同一条记录或者有两页之间夹着一条没显示的数据。列表看起来总数对翻页就对不上。原因分页 SQL 只写了 LIMIT没写 ORDER BY或者写了ORDER BY name但班级里有两个同名同学排序不稳定MySQL 的返回顺序在两次查询之间可能变化。解决分页查询必须用唯一性强的字段排序一般用ORDER BY id DESC。如果要按姓名排序排序字段后面再加一个 id 做 tie-breaker比如ORDER BY name, id。另外count 查询和 list 查询的 WHERE 条件必须完全一致关键字搜索时两次都要绑定同样的 LIKE 参数否则总数对不上最后一页会出现空白。6. 让这份源码真正可以验收测试数据脚本、演示路径与收尾打包6.1 用一份 30 条的测试数据脚本代替手工点键盘演示时最怕冷场登录进去列表是空的现场录学生又慢又容易出错。我会在 sql/data.sql 里准备 5 个班、30 条以上学生记录班级名覆盖“软件2101、网络2202”等方便展示按班级筛选。数据里刻意安排两个同名不同班的学生用来演示分页搜索和排序。如果只用一条数据分页和搜索功能根本没有展示机会。6.2 演示前跑一遍「一分钟演示路径」固定演示顺序不要跳着点。我的习惯是登录 → 查看首页统计 → 按班级筛选 → 搜索姓名 → 翻到第二页 → 新增一条学生 → 批量导入 5 条 CSV → 删掉一条测试记录并解释逻辑删除。这条路径能覆盖登录校验、分页边界、查询速度、事务回滚四个老师最爱问的点。每次改完代码都按这条路径走一遍确认没有报错再收工。6.3 交付物清单至少包含这四样源码目录、pom.xml、sql 初始化脚本、README 运行说明四样缺一样都算不上“包含源码”的可交付程序。README 里要写清 JDK 版本、MySQL 版本、建库步骤、默认账号密码、启动命令。数据库脚本要保证在干净环境执行一次就能把表和测试数据全部建好而不是把你自己机器上的库导出一份交上去——那种导出文件里带着一堆历史脏数据老师一眼就能看出来。把这三件事养成习惯后源码包就不是一堆代码文件的堆叠而是别人拿到手能跑、能验收、能继续维护的东西。我之前见过太多本机正常、换环境就崩的例子根源大多是省掉了测试数据和启动说明。我现在每做一个课设项目都会先写 data.sql再写 README最后才写代码收尾。这个顺序能帮你提前发现自己缺了什么。希望帮到你。本文还有配套的精品资源点击获取
返回列表