ARTICLE DETAIL

资讯详情

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

学生选课系统开发实战:从课程设计到简历项目经验

学生选课系统开发实战:从课程设计到简历项目经验 说实话看到shuyibin的作业这个标题的时候我第一反应是这又是一个在课程设计截止日期前被逼到墙角的年轻人。我在GitHub、Gitee和各种技术社区里见过太多类似的仓库了名字清一色是xxx的作业course-designfinal-project点进去要么是没写完的半成品要么是连README都没有的一堆乱码。shuyibin大概率是个学生的名字拼音这份作业十有八九是计算机方向的编程类课程设计或培训机构的结业项目。我自己做过课设、带过实习生也帮很多学弟学妹review过类似的项目今天就用一个最常见的学生选课管理系统为例把如何把一份编程作业从零做到能交差、敢写进简历这件事完整复盘一遍。这篇内容适合正在肝课设的高校学生、培训班学员以及想往简历里塞真实项目经验的转行新人。1. 拿到作业题目之后先别急着打开IDEA很多人的第一反应是作业嘛冲进机房就开始写代码。这个习惯非常糟糕至少我见过的所有高分作业都不是这么写出来的。拿到一个题目先花小半天把方向定清楚比多写几百行代码有用得多。1.1 先搞清楚老师到底要什么课程设计或者作业的评分标准通常不只有功能对不对。我把常见的评分点拆给大家看功能完整性核心流程能不能跑通边界情况有没有处理。界面与交互页面是不是能看按钮是不是好用这通常占10%到20%的分数。代码质量类名、方法名是否规范有没有明显的坏味道。文档与报告需求分析、数据库设计、核心代码说明、测试报告缺一不可。答辩表现老师会现场让你演示系统然后问几个为什么答不上来会被扣不少印象分。所以当你拿到一份写着实现一个学生选课管理系统的作业要求时不要只盯着选课两个字要把题目里的每一句话都拆成功能点。比如支持学生在线选课意味着至少要有学生登录、浏览课程列表、选课操作、选课结果查询教师可以录入成绩意味着还要有教师登录、成绩录入、成绩修改这些页面。拆完之后列成一张表格每完成一个就打个勾这样心里不慌写起代码也不会漏。1.2 技术选型怎么定才不容易翻车我见过不少人在课设里硬上微服务、上Redis集群、上消息队列最后把自己绕晕了还在调环境。作业项目的第一原则是选自己最熟、资料最多、万一卡住了能搜到答案的技术栈。如果是Java方向最稳妥的组合就是Spring Boot MyBatis MySQL前端用Thymeleaf模板或者直接丢几个Bootstrap页面进去。为什么是这个组合第一Spring Boot把大量配置简化了你不用像SSH时代那样写一堆XML第二这套技术栈的资料多到爆炸随便一个报错信息贴到百度或者Stack Overflow都有答案第三面试官和答辩老师都认识这个组合你解释起来成本低。有人问为什么不用Spring Cloud因为作业项目里没有微服务的业务场景硬拆服务反而是过度设计答辩时老师一问你为什么要拆就露馅了。为什么不推荐纯JSP Servlet不是我瞧不起Servlet而是手写Servlet处理请求转发、参数封装的效率太低课设时间本来就紧没必要在这种环节上耗。1.3 用一天时间做设计剩下的事就顺了所谓设计包含三件事功能模块划分、数据库表结构和页面流转。拿学生选课系统来说核心角色有三种学生、教师、管理员。每个角色能做的事不同学生注册/登录、浏览课程、选课、退课、查看已选课程和成绩。教师登录、录入成绩、修改成绩、查看自己教的课程。管理员管理学生账号、管理教师账号、维护课程信息、查看选课统计。把角色和操作列成矩阵页面结构自然就出来了。我建议同学们把这一步落在纸上画一个简单的页面流转图登录进来之后不同身份跳到不同的首页再从一个页面能点到哪些页面。不用画得多专业自己能看懂就行但它能让你的开发顺序特别清晰避免写到一半发现漏了功能。2. 数据库设计与项目骨架打个好地基到这一步开始碰真东西了。我批改过很多课设代码发现绝大多数翻车项目都死在同一个地方数据库表设计得一塌糊涂。表关系不对后面查询就是灾难。2.1 三张核心表外加两张辅助表学生选课系统最核心的关系是学生和课程的多对多关系一个学生可以选多门课一门课可以被多个学生选。这必须拆成三张表学生表、课程表、选课关系表通常叫sc表即student_course。学生表至少包含id主键、学号、姓名、密码、专业、班级、创建时间。课程表至少包含id主键、课程编号、课程名称、授课教师、学分、上课时间、上课地点、容量、已选人数。选课关系表至少包含id主键、学生id外键、课程id外键、选课时间、成绩——成绩放在这张表里而不是课程表里是因为同一个学生对同一门课只有一个成绩成绩属于选课这个行为。有同学要问教师信息放哪教师也是一个角色需要登录系统所以还应该有一张教师表id、工号、姓名、密码、职称、院系。这样课程表里的授课教师存的是教师id而不是直接存名字保证数据一致性。一些关键设计经验这里说细一点所有表都要有主键主键用自增long就行课设场景性能完全够。选课关系表的学生id 课程id要建一个唯一联合索引否则程序里就算写了判断也防不住两个人同时点选课时插进去两条重复记录。课程表的已选人数字段是冗余设计但非常实用选课时可以配合它做原子校验后面细说。字段命名统一用下划线风格比如student_nameJava实体里对应studentName配置好MyBatis的驼峰映射省掉一堆麻烦。建表SQL示例CREATE TABLE student ( id BIGINT PRIMARY KEY AUTO_INCREMENT, student_no VARCHAR(32) NOT NULL UNIQUE COMMENT 学号, name VARCHAR(32) NOT NULL COMMENT 姓名, password VARCHAR(128) NOT NULL COMMENT 密码, major VARCHAR(64) COMMENT 专业, class_name VARCHAR(64) COMMENT 班级, create_time DATETIME DEFAULT CURRENT_TIMESTAMP ); CREATE TABLE course ( id BIGINT PRIMARY KEY AUTO_INCREMENT, course_no VARCHAR(32) NOT NULL UNIQUE COMMENT 课程编号, course_name VARCHAR(64) NOT NULL COMMENT 课程名称, teacher_id BIGINT NOT NULL COMMENT 授课教师id, credit INT DEFAULT 2 COMMENT 学分, schedule VARCHAR(128) COMMENT 上课时间, location VARCHAR(128) COMMENT 上课地点, capacity INT DEFAULT 30 COMMENT 容量, selected_count INT DEFAULT 0 COMMENT 已选人数 ); CREATE TABLE student_course ( id BIGINT PRIMARY KEY AUTO_INCREMENT, student_id BIGINT NOT NULL, course_id BIGINT NOT NULL, score DECIMAL(5, 2) COMMENT 成绩, create_time DATETIME DEFAULT CURRENT_TIMESTAMP, UNIQUE KEY uk_student_course (student_id, course_id) );2.2 项目骨架搭建注意那两个最常见的环境坑技术栈确定之后骨架搭建其实很机械Spring Initializr生成项目引入spring-boot-starter-web、mybatis-spring-boot-starter、mysql-connector-java这些依赖。但这里有两个坑我几乎每次都会遇到必须提醒一下。第一个坑Maven下载依赖慢。默认的中央仓库在国外国内网络非常不稳定。解决方法是改成阿里云镜像在settings.xml里配置mirror idaliyunmaven/id mirrorOfcentral/mirrorOf name阿里云公共仓库/name urlhttps://maven.aliyun.com/repository/central/url /mirror改完镜像依赖下载速度立竿见影。第二个坑MySQL连接参数里的时区问题。用MySQL 8.x时连接URL里必须加上serverTimezoneAsia/Shanghai否则会报时区错误。spring: datasource: url: jdbc:mysql://localhost:3306/course_db?useUnicodetruecharacterEncodingutf-8serverTimezoneAsia/Shanghai username: root password: 123456骨架搭好后按entity、mapper、service、controller、config这样的包结构分好目录每个包只放对应类型的类。这个习惯越早养成越好因为答辩老师极有可能点开你的代码看一眼结构一个组织漂亮的工程印象分直接拉满。3. 核心功能实现登录、选课和成绩录入框架搭好之后真正耗时间的是业务功能。我把最常见的几个难点单独拿出来讲这里面的坑我当年全踩过。3.1 登录与权限控制用Session就够了课设里的登录没必要上Spring Security这种重框架自己写一个拦截器就行。流程是这样的用户提交账号密码Service层校验账号存在且密码正确成功后把用户信息id、角色、姓名存进Session然后通过一个拦截器拦截需要登录才能访问的请求每进来一个请求就先检查Session里有没有用户没有就跳回登录页。角色判断也简单把角色字段放进Session之后请求某个角色的接口时判断一下当前Session里的角色是不是对应的不对就拒绝访问。在课设评分里这已经算是考虑周全了。我自己review过的作业里很多人没有做权限控制学生登录之后可以直接访问管理员的页面这是比较严重的功能缺失答辩时如果被演示出来会很尴尬。密码存储一定要做哈希处理别存明文。课设里用MD5加盐或者BCrypt都行我更推荐BCrypt因为它自带盐值且不可逆而且Spring Security里直接封装好了引入一个spring-security-crypto依赖就能用。存储格式像这样String encodedPassword BCryptPasswordEncoder().encode(rawPassword);3.2 选课逻辑一条SQL解决超员和重复选课选课是学生选课系统的核心操作也是最容易出Bug的地方。很多人的实现方法是这样// 伪代码 Course course courseMapper.selectById(courseId); if (course.getSelectedCount() course.getCapacity()) { courseMapper.increaseSelectedCount(courseId); scMapper.insert(studentId, courseId); return 选课成功; }表面上看着没问题但如果两个学生同时选同一门只剩一个名额的课两个请求都读到了capacity - 1然后都执行了插入结果课程超员了。这就是经典的并发问题。课设里不一定真的会有人并发选课但答辩老师很喜欢问如果有100个人同时选课怎么办。正确的做法是把判断和更新合成一条SQL让数据库保证原子性UPDATE course SET selected_count selected_count 1 WHERE id #{courseId} AND selected_count capacity;如果这条SQL影响行数为1说明名额抢占成功再插入选课记录影响行数为0说明课程已满或者课程不存在直接返回选课失败。这条SQL能同时解决超员占用问题和丢更新问题属于教科书级别的解决方案。插入选课记录时也不要用普通的insert而是用INSERT IGNORE如果联合唯一索引已经存在重复记录插入会被忽略返回影响行数为0我们据此返回你已经选过这门课了。3.3 成绩录入与统计查询教师端录成绩是个简单的更新操作但要注意两点。第一只有教这门课的老师才能录成绩所以更新语句里一定要带上课程归属条件。第二前端表单里的成绩一般传的是字符串后端接收后要校验范围防止有人往里填-100或者200。成绩统计在SQL里做就行。比如计算某门课的学生平均分SELECT AVG(score) FROM student_course WHERE course_id #{courseId};统计每门课的选课人数SELECT c.course_name, COUNT(sc.id) AS selected_num FROM course c LEFT JOIN student_course sc ON c.id sc.course_id GROUP BY c.id;这里用LEFT JOIN而不是JOIN是为了把那些没有学生选所以不在选课表里的课程也统计出来。这种细节很多人注意不到但老师一眼就能看出你SQL水平。3.4 前端页面别自己造轮子直接套模板关于前端我的建议是不要浪费太多时间手写CSS和JS。你是一个交课程作业的学生不是专业前端把时间花在功能上更划算。用Bootstrap的现成模板或者找一套免费的后台管理模板比如AdminLTE把登录页、列表页、表单页改一改就能用。模板选好后页面之间跳转用Thymeleaf的th:href、th:action这些语法搞定。要注意的是Thymeleaf的依赖要加完整dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-thymeleaf/artifactId /dependency静态资源放在src/main/resources/static下面HTML页面放在templates下面。如果你用前后端完全分离的方式写那就前后端各做各的但课设时间有限我建议用模板渲染的方式省去处理跨域、Token传递这些麻烦。4. 测试、改Bug与写文档决定作业上限的部分代码写完不等于作业完成。我见过太多项目功能代码写完了但打开就是错误页的原因就是没做系统性的自测和调试。4.1 按功能点列表自测把之前需求分析时列的功能点清单拿出来逐项测试。注意要测的不仅是正常流程还有异常流程。我列个简单的自测清单大家照着做就行功能模块测试场景预期结果登录账号密码正确跳转到对应角色首页登录密码错误提示密码错误不跳转登录不登录直接访问后台页面拦截器拦截跳回登录页选课正常选课已选人数加1选课表插入记录选课课程已满再选提示课程已满选课重复选同一门课提示不能重复选课退课退课后选课表删除记录已选人数减1成绩教师录入非法分数提示分数范围不符权限学生访问教师页面拒绝访问每一项都真实点一遍发现问题就记下来修完再回归测试。这个过程很无聊但能避免你在答辩现场翻车。4.2 高频Bug实录踩坑经验直接抄第一中文乱码。这几乎是所有JavaWeb课设的标配问题。排查顺序是页面编码是不是UTF-8后端过滤器有没有设置编码数据库连接URL有没有加characterEncodingutf-8数据库表本身的字符集是不是utf8mb4。走完这四步99%的乱码都能解决。第二日期和JSON格式对不上。如果你用的是Spring Boot 2.x后端返回LocalDateTime给前端前端看到的是2024-12-05T10:30:00这种带T的格式页面显示很不美观。解决方法是加一个Jackson配置spring: jackson: date-format: yyyy-MM-dd HH:mm:ss time-zone: GMT8第三MyBatis查询结果字段为null。如果是字段名映射问题检查数据库下划线字段和实体类驼峰属性之间是否开了驼峰映射mybatis: configuration: map-underscore-to-camel-case: true如果开了映射还查不出来去MySQL客户端里手动执行一遍SQL看看是不是SQL本身写错了。很多代码查不到数据的问题其实是SQL条件写错不是Java代码的问题。第四修改代码后不生效。课设阶段大家经常改了Java代码重新启动应用发现还是老行为原因多半是IDEA的增量编译缓存或者浏览器缓存。第一时间mvn clean然后重启前端页面就强刷一次浏览器CtrlF5。这类问题不要瞎猜用排除法一个一个验。4.3 作业报告和演示准备文档不仅是作业要求也是给自己留的后路。答辩时你的记忆可能一片空白但文档里写了的东西多少能帮你找回思路。报告结构建议这样需求分析系统有哪些角色、每个角色能做什么。系统设计技术栈选择理由、数据库表结构说明、各表关系。核心功能实现挑两三个技术上最值得说的功能比如选课的并发处理、权限拦截贴核心代码配运行截图。测试报告自测清单和结果。总结与展望遇到的问题、怎么解决的以及未来可以扩展的方向比如接入Redis做缓存、用Spring Security重构权限。答辩前必须自己完整走一遍演示流程登录三个角色把每个角色的主要操作在浏览器里点一遍提前演练。很多人的系统写的时候能跑一到演示就连不上数据库十有八九是MySQL没启动或者端口被占这点真要重点检查。5. 从作业到项目经验还差这一步作业交上去、答辩完成这件事还没有结束。聪明的同学会把这份作业改造成自己简历上的项目经验这比证书更有说服力。5.1 把作业代码升级成可展示作品交作业用的代码和能写进简历的代码差在三个地方README、代码规范和演示环境。先写一个漂亮的README内容包括项目介绍、技术栈、如何部署运行、功能列表和截图。招聘方看你的GitHub仓库第一眼看的就是README一份清晰的README能让你的项目通过率提升一大截。我见过太多孩子写了非常好的代码但README完全是空的非常可惜。再检查一遍代码有没有把数据库密码写在硬编码里有没有测试代码残留有没有一堆out目录、target目录直接提交上去了该用的.gitignore用起来把target、.idea这些目录排除掉。最后如果条件允许把项目部署到云服务器上给一个线上演示地址。这一步非常加分。因为面试官不用自己拉代码跑环境直接点开链接就能看到你的系统体验完全不同。部署的本地安装Nginx、用mvn package打包、用java -jar启动一套流程并不复杂值得花时间。5.2 面试时怎么讲这个项目面试官看到你简历上有项目经验通常会问几个经典问题为什么要做这个项目你负责了哪些模块遇到过什么难点怎么解决的回答的原则是把重点放在你遇到的难题和你的思考过程上不要背流水账。比如选课的并发问题就是一个完美的面试素材先说你最初用先查再插的方式会出现超售然后说你意识到需要原子性操作改成一条update语句带条件判断再说数据库层面还加了唯一联合索引双保险。这个故事讲下来面试官就能判断出你有实际思考过问题而不是照着视频敲了一遍。如果简历上还没有项目经历这份学生选课管理系统稍微包装一下完全可以直接用。它不是多牛逼但它是你自己一行一行写出来的你对每个细节都了如指掌这一点本身就很有价值。5.3 最后几个值得养成的习惯回顾整个课设过程有几个习惯是我强烈建议每个人从这次作业就开始养成的第一用Git管理代码哪怕你自己一个人写。每天提交一次写清楚commit信息这样你永远有一个可以回退的版本不会出现改坏了但回不去的悲剧。第二备份数据库。课设期间数据库表结构可能改了又改每次改完都导出一份SQL文件存着。第三合理分配时间不要总想着最后一周冲刺。按我上面的功能点拆解法每天做一个模块能把突发情况的时间留足比熬夜通宵要稳妥得多。最后再分享一点我的个人体会。我带团队这些年看一个新人能不能用不是看他学校多好、考试多少分而是看他遇到问题愿不愿意自己先查、先试而不是张嘴就问。课设就是一次很好的自我训练机会独立完成一个完整的项目遇到问题自己查资料解决踩完坑之后做记录这个过程培养的能力比作业本身那点分数重要得多。把这份作业当成你软件开发生涯的第一个里程碑来做你的收获会远超预期。
返回列表