资讯动态

基于JSP的高校实验课表管理系统:从需求分析到部署实战

发布时间:2026/10/18 17:00:40 来源:尧图企业网站定制
做过高校项目的人都懂一个画面每学期初教务员手里拿着一张写满奇怪符号的Excel表办公室里排着长队老师在问我周四下午的实验课怎么和隔壁实验室冲突了学生在群里刷屏这周实验到底在哪个机房。实验课表的复杂度向来被严重低估普通课表系统根本处理不了一个实验室在多个时间段分配给不同班级、一个教师跨校区上课、设备类型决定机房这种多维度约束。所以我当时接到这个基于JSP的高校实验课表管理系统项目代号VY32G时第一反应是这东西的难点不在写代码而在把排课规则想明白。这篇文章我会完整拆解这个项目的设计思路、数据库结构、核心功能实现和从源码到运行的全部部署过程。不管你是正在做JavaWeb课程设计的学生还是第一次接触课表类管理系统的开发者照着这个思路做下来遇到的大部分坑都能提前避开。我先把话说在前面这套系统用的技术虽然不是最前沿的但它在真实高校场景里能跑得稳恰恰是因为选型克制、结构清晰。1. 实验课表管理系统的痛点为什么教务员需要一个专门的排课工具很多第一次接触这类需求的人会觉得课表不就是时间地点课程老师四个字段吗做一张表CRUD不就行了。但等你真正动手整理需求会发现实验课表远不止这么简单。我当初和某高校负责实验教学多年的教务员连续聊了几个下午才把需求梳理到能落地的粒度这里面的细节值得先说清楚。1.1 实验课和普通理论课的区别普通理论课的排课单位是教室一个教室容纳一个班桌椅固定讲师站前面讲就行。实验课完全不同它排课的核心资源是实验室而实验室有非常硬性的属性约束。比如说某高校的电工电子实验室只有40台工位其中带示波器的只有24台计算机组成原理实验室装的是旧版教学软件只能开特定的实验项目还有一间实验室的位置在另外一个校区教师和学生往返需要二十分钟。这些信息在普通课表系统里是没有办法体现的。所以实验课表管理系统本质上是一个带资源属性约束的排课系统。另一个区别在于时间粒度。理论课通常一次就是两小节连堂实验课却经常出现上午做不完下午接着做的情况也有部分实验项目要求学生分批进入每批一小时轮换。课表里的每个时间段在实验场景下还可能被拆成多个小组批次。如果所有信息都塞进一张星期几第几节的表结构里后面必然要返工。还有一个关键点实验课往往有专业特殊性。同一个班的学生可能分成A/B两组一组做硬件实验另一组做软件仿真下一周互换。这个周次轮换逻辑是普通课表系统几乎都不会考虑的。1.2 主要角色都想从这个系统里得到什么我梳理过这个系统的用户角色最终定为四类每一类的诉求都不一样系统管理员负责维护实验室信息、课程基础数据、用户账号。最关心的是能不能把实验室资源管清楚比如每个实验室当前被占用情况、设备状态是否正常。教务员排课管理员负责生成和调整实验课表。最关心的是排课有没有冲突包括实验室、教师、班级三个维度任何一个维度冲突都不能保存。教师查看自己的实验课表、所负责课程的选课学生名单。有的老师还希望能在系统里提交调课申请而不是跑到教务处交纸质单子。学生查看自己的实验课表、上课地点、第几周上什么内容。由于学生经常同时参加多个组的实验按班级和学号过滤查询是刚需。调研完这些诉求我把功能清单列成了几个模块用户登录与角色权限管理、实验室管理、实验课程管理、排课管理含冲突检测、课表查询与导出、选课名单管理。整个项目最终的程序、源码、数据库文件和部署文档都是围绕着这几个模块搭建的。实际开发的编码工作只占一半另一半全在业务规则设计上。2. 技术选型与项目结构JSPServletMySQL经典组合的实际存续理由现在做JavaWeb项目很多人第一反应就是Spring Boot加MyBatis再配个Vue。但你看这个项目标题就知道它用的是JSP。别急着觉得过时这套技术在高校课表类管理系统里仍然有非常强的生命力我仔细说下原因。2.1 为什么不选更新潮的框架先讲一个事实JavaWeb这门课在相当多的高校里教学主线仍然是从JSP和Servlet开始讲起结课作业也要求必须用JSPServlet完成。不是说学校不教Spring Boot而是JSP方案对课程设计来说够用且好理解——学生能把MVC思想、JDBC操作、Session管理这些底层东西全部亲手写一遍而不是在Spring Boot的自动配置里被包起来看不见。从实际项目角度讲这个实验课表管理系统的规模并不大。核心表就七八张业务逻辑集中在排课和查询并发量级是一个学院几百个学生同时使用。在这种量级下JSP服务端渲染页面的方式反而简单直接不需要前端工程化、不需要接口联调、不需要跨域处理一个Tomcat把页面和接口一起跑完。另外部署环境也决定了技术选型不能太激进。某高校的实验中心和课程服务器常年运行着老版本操作系统装的还是Tomcat 8系列你拿一个需要JDK 17的Spring Boot 3项目过去对方机房根本跑不起来。JSP项目只要打包成war丢进Tomcat就能运行运维负担最小。我做技术选型时非常看重这一点系统能不能在目标环境里稳定跑起来比用什么框架更重要。2.2 项目目录结构与分层思想这个项目的目录结构我按经典三层架构来组织但刻意控制类和包的数量避免过度设计。源码仓库的根目录大概是这样的src ├── main │ ├── java │ │ └── com │ │ └── schedule │ │ ├── dao // 数据访问层每个表对应一个Dao │ │ ├── entity // 实体类和数据库表字段一一对应 │ │ ├── service // 业务层排课冲突检测等核心逻辑 │ │ ├── servlet // 控制层接收请求并跳转页面 │ │ ├── filter // 登录与角色权限过滤器 │ │ └── util // 工具类数据库连接、日期处理 │ └── webapp │ ├── admin // 管理员和教务员页面 │ ├── teacher // 教师页面 │ ├── student // 学生页面 │ ├── common // 登录页、公共样式 │ └── WEB-INF │ └── web.xml // Servlet与Filter注册配置 └── sql └── vy32g_schedule.sql // 数据库初始化脚本这个分层的核心思想很简单客户端请求到达Servlet控制层Servlet调用Service业务层Service调用Dao数据层Dao操作MySQL数据库返回结果后Servlet把数据放进Request域转发到JSP渲染页面。每一层只做自己该做的事出了问题你也能很快定位——页面显示不对查JSP逻辑不对查Service数据不对查SQL。2.3 开发环境的具体版本搭配关于开发环境这个项目我实测过的组合是组件推荐版本说明JDKJDK 1.8兼容性最好Tomcat 8/9都支持TomcatTomcat 8.5 或 9.0稳定war包直接部署MySQLMySQL 5.7如果学校服务器是老系统别用8.0IDEEclipse或IntelliJ IDEAIDEA社区版就够用数据库驱动mysql-connector-java 5.1.49对应MySQL 5.7构建工具Maven或手动导入jar教程类建议手动导入一次以理解原理一个小提醒如果用IDEA创建JSP动态Web项目建议勾选Web Application模板然后手动把Tomcat配置到Run Configuration里。很多人卡在代码写完了但点击运行没法访问页面基本都是Tomcat集成配置出了问题后面第5节我会专门讲部署。3. 数据库设计实验课表的实体关系与建表思路数据库是整个项目里最不能糊弄的部分。我见过不少课程设计代码写了一堆数据库却只有用户表和课表一张表结果排课冲突检测根本写不出来。这个系统我设计了七张核心表下面对关键结构做一次完整还原。3.1 核心表结构与字段说明先讲用户相关的表。系统里存在学生、教师、管理员三类自然身份但我没有把账号密码分散到三张表而是统一放在一张sys_user表里用role字段区分角色。学生姓名、学号、班级这些信息放在student表教师信息放在teacher表通过user_id关联这样登录认证和业务查询可以分离也方便以后扩展新角色。sys_user表的关键字段CREATE TABLE sys_user ( id INT PRIMARY KEY AUTO_INCREMENT, username VARCHAR(50) NOT NULL UNIQUE, password VARCHAR(64) NOT NULL, role VARCHAR(10) NOT NULL, -- admin/teacher/student real_name VARCHAR(50), status TINYINT DEFAULT 1 -- 1正常 0禁用 );然后是实验室表lab。我把实验楼的楼号房间号容量适用课程类型都放进去并且加了一个equipment字段记录设备描述方便教务员在排课时知道这间实验室能承担什么实验CREATE TABLE lab ( id INT PRIMARY KEY AUTO_INCREMENT, lab_name VARCHAR(100) NOT NULL, location VARCHAR(100), -- 例如实验楼A区302 capacity INT NOT NULL, -- 工位总数 equipment VARCHAR(255), -- 主要设备说明 lab_type VARCHAR(50), -- 硬件类/软件类/综合类 status TINYINT DEFAULT 1 -- 1可用 0维护中 );实验课程表course记录每门课的基本信息注意这里存的是课程模板具体哪个班什么时候到实验室上课是由schedule表决定的CREATE TABLE course ( id INT PRIMARY KEY AUTO_INCREMENT, course_name VARCHAR(100) NOT NULL, course_code VARCHAR(20) NOT NULL, credit DECIMAL(3,1) DEFAULT 1.0, teacher_id INT, -- 授课教师 lab_type_required VARCHAR(50), -- 需要的实验室类型 weeks_total INT DEFAULT 8 -- 实验周数 );3.2 这几张表之间的关联关系核心中的核心是排课表schedule。给一张实验课排课你需要同时确定哪门课、哪个老师、哪个班级、哪间实验室、哪一周、星期几、第几节。这六七个维度缺一个学生就不知道该去哪上课。我的schedule表结构如下CREATE TABLE schedule ( id INT PRIMARY KEY AUTO_INCREMENT, course_id INT NOT NULL, -- 关联course表 class_name VARCHAR(50) NOT NULL, -- 教学班例如 计科2401 teacher_id INT NOT NULL, -- 实际授课教师 lab_id INT NOT NULL, -- 关联lab表 week_start INT NOT NULL, -- 起始周 week_end INT NOT NULL, -- 结束周 week_interval INT DEFAULT 1, -- 周间隔例如 1表示每周2表示隔周 day_of_week INT NOT NULL, -- 1-7周一至周日 section_start INT NOT NULL, -- 开始节次1-6 section_end INT NOT NULL, -- 结束节次 student_capacity INT, -- 本次课可容纳人数 group_info VARCHAR(100), -- A/B组等分组说明 status TINYINT DEFAULT 0 -- 0未发布 1已发布 );这张表几乎包含了所有排课冲突判定需要的信息。后面写冲突检测时只需要组合条件做查询不需要再做复杂关联这个设计后来在实际调试中帮我省了大量时间。最后还有一张选课表student_course用于教师查看选课名单和学生查看个人课表。它把student和schedule关联起来CREATE TABLE student_course ( id INT PRIMARY KEY AUTO_INCREMENT, student_id INT NOT NULL, schedule_id INT NOT NULL, status TINYINT DEFAULT 0, -- 0待确认 1已确认 create_time DATETIME DEFAULT CURRENT_TIMESTAMP, UNIQUE KEY uk_student_schedule (student_id, schedule_id) );3.3 从ER设计到建表SQL的注意点我要强调一个非常容易踩的细节周次存储。很多第一次做课表的人会把第1周到第16周拆成16个字段或者用逗号拼接字符串这两种方案都是灾难。用week_start、week_end加week_interval组合既能表示连续周1-16周也能表示隔周week_interval2比字符串解析可靠得多。另外day_of_week和section_start/section_end我都用整数而不是字符串。好处有两个排序自然周一永远在周二前面计算重叠时间段时直接比较大小不用处理中文或英文星期字符串。这个惯例我强烈建议保留。建表时的字符集问题也要注意。在MySQL里建库一定要显式指定字符集CREATE DATABASE IF NOT EXISTS schedule_db DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;全程使用utf8mb4。曾经就是因为有人图省事用了默认latin1数据写入中文后全部变成问号排查了半天才发现是数据库字符集问题。项目里提供的vy32g_schedule.sql脚本把建库、建表、初始数据都写好了导入即可但我建议你自己重新执行一遍建表语句弄清楚每张表的用途后面调试SQL时心里才有底。4. 核心功能实现排课冲突检测、课表渲染与权限控制这个项目真正的技术含量集中在三个地方排课冲突的判定逻辑、课表的动态渲染方式、以及基于角色的访问控制。三个问题想明白整个系统就通了一大半。4.1 排课冲突检测双重校验逻辑排课冲突是实验课表系统最核心的业务规则。我实现了两个层次的校验底层的SQL条件查询加上层的Java业务判断。以保存一条新排课记录为例核心思路是查出所有和这条记录时间、地点、教师有关联的已有记录逐条判断是否有重叠。先看最关键的一条SQL。检查同一时段同一间实验室是否被占用public boolean checkLabConflict(Connection conn, Schedule schedule) throws SQLException { String sql SELECT COUNT(*) FROM schedule WHERE lab_id ? AND day_of_week ? AND section_start ? AND section_end ? AND status 1; PreparedStatement ps conn.prepareStatement(sql); ps.setInt(1, schedule.getLabId()); ps.setInt(2, schedule.getDayOfWeek()); ps.setInt(3, schedule.getSectionEnd()); ps.setInt(4, schedule.getSectionStart()); ResultSet rs ps.executeQuery(); rs.next(); return rs.getInt(1) 0; }这段代码里的条件可能有人看不懂我解释一下新排课占用的是第3节到第4节那么已有记录如果从第2节上到第4节section_start2, section_end4它满足section_start 4且section_end 3说明两个区间有交集冲突。这种区间重叠判断比枚举每个节次再逐次匹配要高效得多也不用循环写一堆if。教师冲突同理把lab_id换成teacher_id再查一遍。教学班冲突也按这个思路扩展。我最终把三种冲突检查统一封装成了一个ScheduleConflictChecker类每次保存排课记录前按实验室、教师、班级三个维度依次校验任何一个维度冲突都返回对应的中文提示信息。补充一个很多人忽略的点排课冲突校验必须考虑周次。同一间实验室如果在单周被占用双周是可以再排的。所以最终的SQL还要加上周次判定我建议把周次展开到Java层处理——查出该实验室在目标星期和节次的所有记录后在Java里判断两个时间范围是否存在重叠周这样逻辑更清晰。4.2 课表视图渲染二维数组与HTML表格映射课表的展示是本项目里最直观、也最容易写乱的模块。很多人的第一版代码是在数据库查出记录后丢给JSP然后在JSP里嵌套三层循环去匹配单元格结果数据一多页面渲染逻辑变成一团麻。我的做法是在Servlet层就把课表组织成二维数组JSP只负责循环打印不做任何业务计算。UML类或伪代码不需要直接看核心逻辑。以学生个人课表为例在Servlet里执行查询后把结果映射成一个table[day][section]的结构String[][] weekTable new String[7][7]; // [星期][节次]0下标空闲不用 ListSchedule schedules scheduleService.findStudentSchedule(studentId); for (Schedule s : schedules) { String info s.getCourseName() s.getLabName(); for (int sec s.getSectionStart(); sec s.getSectionEnd(); sec) { weekTable[s.getDayOfWeek()][sec] info; } } request.setAttribute(weekTable, weekTable);然后JSP页面用一个双层循环把二维数组渲染成HTML表格table border1 cellpadding8 cellspacing0 tr th节次/th th周一/th th周二/th th周三/th th周四/th th周五/th /tr c:forEach varsec begin1 end6 tr td第${sec}节/td c:forEach varday begin1 end5 td c:choose c:when test${not empty weekTable[day][sec]} ${weekTable[day][sec]} /c:when c:otherwise空闲/c:otherwise /c:choose /td /c:forEach /tr /c:forEach /table这套方案的好处非常直观Servlet把数据准备好JSP只负责展示。改样式不会碰到逻辑改逻辑不会弄乱HTML。我在这个项目里前后改了三次课表样式从纯表格到加色彩标记每次都是只动JSPService层一次没碰。4.3 基于Filter的角色权限控制系统有管理员、教师、学生三种角色权限必须严格分开。学生进来不能打开排课管理页教师不能修改系统用户。这个需求用Servlet Filter实现最合适。我写了一个登录和角色校验的过滤器统一切入点拦截所有请求WebFilter(/*) public class AuthFilter implements Filter { public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException { HttpServletRequest request (HttpServletRequest) req; HttpServletResponse response (HttpServletResponse) resp; String uri request.getRequestURI(); String contextPath request.getContextPath(); // 登录页、静态资源直接放行 if (uri.endsWith(/login.jsp) || uri.contains(/static/)) { chain.doFilter(request, response); return; } // 判断是否登录 User user (User) request.getSession().getAttribute(loginUser); if (user null) { response.sendRedirect(contextPath /login.jsp); return; } // 角色白名单校验访问路径前缀必须匹配角色 if (uri.contains(/admin/) !admin.equals(user.getRole()) !operator.equals(user.getRole())) { response.sendRedirect(contextPath /error/denied.jsp); return; } if (uri.contains(/teacher/) !teacher.equals(user.getRole())) { response.sendRedirect(contextPath /error/denied.jsp); return; } chain.doFilter(request, response); } }这个Filter的设计思想是先认证后授权先检查有没有登录再检查登录角色的访问范围。特别注意WebFilter(/*)会把JSP页面本身也拦截住所以放行规则里要把登录页和静态资源单独排除否则会出现打开登录页却被拦截跳转到登录页的死循环。在web.xml里也可以配置Filter两种方式都能跑通。如果你用的Servlet版本较老不支持WebFilter注解那就老老实实去web.xml配置filter和filter-mapping。我在调试中发现不少同学在Filter里绕了半天出不来最后发现是映射路径写错把/*写成了/只拦了根路径其它请求全部放行权限控制等于没有。5. 从源码到运行调试部署全流程实录拿到一个完整项目之后怎么把它跑起来这也是很多人卡住的点。这个项目的程序、源码、数据库、部署文档都是一起交付的但如果你不按正确顺序操作还是可能启动失败。我按实际部署顺序把整个流程过一遍。5.1 环境准备清单部署前先确认环境。我建议按这个清单逐项核对不要凭感觉装检查项要求验证方式JDK1.8命令行执行java -versionTomcat8.5或9.0启动后访问http://localhost:8080看到默认页MySQL5.7或8.0mysql -uroot -p能登录IDEIDEA或Eclipse已配好Tomcat运行时连接器mysql-connector-java放在WEB-INF/lib下IDE配置Tomcat这一步我多说一句。以IDEA为例需要在File → Project Structure → Artifacts里确认项目打包方式是Web Application: Exploded然后在Run Configurations里新增一个Tomcat Server → Local把Deployment里的Artifacts添加进来才会出现那个绿色的启动按钮。如果你点了Tomcat的启动按钮却弹窗报Unable to ping server多半是Tomcat的端口或JMX端口和本地已有程序冲突或者Tomcat home目录选错了。5.2 数据库导入与应用配置数据库导入相对无脑但也要注意顺序。打开命令行进入MySQLmysql -u root -p source D:/path/to/vy32g_schedule.sql;建议使用绝对路径避免因为中文目录问题导致source失败。导入完成后检查一下sys_user表确认管理员账号存在。项目里数据库连接信息通常在src/main/java/com/schedule/util/DBUtil.java里或者如果你用了连接池则在c3p0-config.xml文件中。修改成你本机的MySQL账号密码private static final String URL jdbc:mysql://localhost:3306/schedule_db?useSSLfalsecharacterEncodingutf8; private static final String USER root; private static final String PASSWORD 你的数据库密码;这里有个经典坑MySQL 8.0以上的JDBC驱动类名和URL参数和MySQL 5.7完全不同。MySQL 5.7用com.mysql.jdbc.DriverMySQL 8.0用com.mysql.cj.jdbc.Driver还要加serverTimezoneAsia/Shanghai参数。所以如果你的数据库是8.0注意把驱动jar包和URL同步换成8.0版本。如果驱动和数据库版本不匹配最常见的就是Communications link failure或者时区报错。5.3 启动过程中最常见的四个报错我把这个项目调试过程中遇到的最高频报错整理成一张表每个我都实际踩过报错现象根本原因解决方案ClassNotFoundException: com.mysql.jdbc.Driver驱动jar没放到WEB-INF/lib下载对应驱动jar并放入WEB-INF/libPort 8080 already in useTomcat默认端口被占用改server.xml里端口或关掉占用进程页面中文显示??数据库字符集不是utf8确认建库语句utf8mb4确认连接URL带characterEncodingutf8HTTP 404访问不到页面Servlet映射路径或页面路径不对检查WebServlet注解值和浏览器访问路径是否一致排查404问题时我有个非常实用的习惯访问页面时报404先看一眼Tomcat控制台有没有打印Servlet初始化异常再看IDEA的Artifact输出目录里WEB-INF/classes下有没有编译出.class文件。很多时候代码源文件改了但IDEA没有自动编译你跑的其实是旧的class。这个时候Project → Build → Rebuild Project一下问题立刻解决。如果你用的是Maven构建部署前执行mvn clean package生成war文件再扔到Tomcat的webapps目录下也能运行。这也是最接近真实环境的一种部署方式适合最后验收时用。本地开发和测试阶段用IDEA的Tomcat集成方式更方便调试断点也更顺手。6. 我在这个系统上踩过的坑与调试经验最后这部分是纯经验输出。我在做这个实验课表管理系统时前前后后调试了两周有些问题折磨了我好几天才找到根因写下来帮大家少走弯路。6.1 中文乱码问题的根源中文乱码这个事大多数情况下不是一处问题而是三个环节同时没做对。第一数据库连接URL没有带characterEncodingutf8第二JSP页面顶部没有设置contentTypetext/html; charsetUTF-8和pageEncodingUTF-8第三Servlet接收POST请求时没有执行request.setCharacterEncoding(UTF-8)。这三个默认值在JavaWeb规范里都是请自行设置你不设置就按平台默认编码来系统是中文环境还好Linux服务器上默认UTF-8Windows本地默认GBK页面编码和数据编码一混乱码就出现了。我的建议是在项目一开始就固定一个规则所有涉及文本传输的地方全部显式指定UTF-8。数据库连接串、JSP指令、Servlet开头一个都不能少。顺手分享一个排查技巧如果只有存入数据库的中文乱而页面显示正常基本可以锁定是数据库字符集问题检查建库语句和连接URL即可。如果页面上的中文全是问号那是JSP编码问题居多。如果表单提交到后台再显示就乱先看Servlet有没有设置请求编码。按这个链路排查十分钟内必出结果。6.2 数据库连接泄漏JDBC操作时忘记关闭连接这个问题在大学项目里几乎人人都有但后果可能比你想象得严重。Tomcat默认的连接池大小有限如果你每次查询都new Connection且用完不关高并发下连接数很快耗尽页面会随机报连接超时而且这种bug特别难复现。我后期给这个系统做了整改把所有数据库操作统一收口到一个DbUtil工具类并且利用JDK 7的try-with-resources语法确保连接自动关闭public static T T query(String sql, ResultSetHandlerT handler, Object... params) { try (Connection conn getConnection(); PreparedStatement ps conn.prepareStatement(sql)) { for (int i 0; i params.length; i) { ps.setObject(i 1, params[i]); } try (ResultSet rs ps.executeQuery()) { return handler.handle(rs); } } catch (SQLException e) { throw new RuntimeException(数据库操作失败, e); } }这样每个Dao方法里就不用重复写try-catch-finally了连接也不容易泄漏。如果你用的是连接池记住一个原则你打开的连接必须由你在同一个方法里关闭千万别想着等别的类帮我关那样基本等于不关。6.3 时间与星期字段的存储设计教训我第一次设计schedule表时用的week字段是字符串1,3,5,7这样的格式来表示隔周上课结果写冲突检测时需要在Java里把字符串拆开再循环比较不仅代码难看还容易漏判。后来全部改成week_start、week_end加week_interval三个字段冲突判断的SQL才变得清晰。这个教训其实反映了一个通用规律表达一个范围概念时一定要用结构化的字段组合而不要用字符串塞一堆信息。排课记录本质是时间范围第几周到第几周和空间范围哪个实验室、哪几个节次的交叉如果你用字符串存储后期做任何数值判断都要先做字符串解析维护成本直线上升。项目里提供的vy32g_schedule.sql是按最终设计写的建议照着理解不要自己改回字符串方案。6.4 给后来者的几条建议最后分享几条我一直很受用的实操经验第一先跑通最小闭环再扩展功能。拿到这个项目后第一步不要急着做排课管理先把登录模块跑通然后用管理员账号进首页看看基本页面再做一张实验室的CRUD最后才碰排课。每一步都能看到效果调试信心会稳很多。第二排课模块单独花时间设计测试用例。我给这个项目做过一张测试表专门列了各种冲突场景同一老师同一时间不同实验室、同一实验室不同老师、同一班级同一时间两个实验、跨周连续周的冲突、隔周上课与单周上课的冲突。每修完一个bug就把这些用例重新跑一遍防止改一处坏一处。第三源码里的注释和文档不要删。这个项目交付时带了完整的部署文档和源码注释很多人拿到手先CtrlA全部删除重写结果把自己坑了。原注释里很多都是针对实际环境写的说明比如哪个配置是某高校服务器的特殊设置删掉之后再出问题就只能靠自己猜。第四多看Tomcat日志而不是只看页面。页面报500错误浏览器里可能只有一行HTTP Status 500完整堆栈都在Tomcat的logs目录或者IDEA控制台。学会看异常堆栈定位到具体代码行才是调试的正确姿势。我见过太多人在页面报错后原地发懵实际上往下滑两行日志答案就出来了。这个实验课表管理系统做下来我最大的体会是所谓管理系统难点从来不在增删改查而在业务规则怎么翻译成数据和逻辑。实验课排课课表背后其实是资源调度问题一旦把实验室、时间段、教师、班级这几个维度之间的关系理清楚了代码不过是水到渠成的事。希望这份从需求到数据库再到部署的完整复盘能让你少踩几个我已经踩过的坑把精力放在真正有意思的业务逻辑上。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑