资讯动态

毕业设计选题系统Java源码拆解:从数据库设计到并发控制

发布时间:2026/10/9 14:19:04 来源:尧图企业网站定制
简介一套基于Java/JSP的毕业选题系统完整源代码包主要面向计算机专业学生的毕业设计与课程设计场景。系统内置管理员、教师、学生三类角色管理员负责维护系主任信息和系统运行教师可录入题目并审核学生选题学生可在线完成选题。资源包共547个文件压缩后大小约8.65MB包含大量操作截图、JSP动态页面、CSS样式、JavaScript脚本以及Java类文件另附Word说明文档和CAJ参考论文便于对照工程结构理解实现过程。当前已有53人学习或浏览可直接作为毕业设计与课程设计的参考也可用于Java Web开发练习。压缩包内按功能模块组织文件前端页面与后端逻辑清晰分离结合说明文档可快速理清数据库表结构与部署流程Tomcat MySQL 5.7 JDK 1.8适合需要快速上手完整选题系统方案、以节省开发时间的读者参考。1. 毕业选题系统 Java 源码为什么这种“简单系统”最容易翻车毕业设计选题系统在 Java Web 课程设计里属于“看着最容易、交上去最心虚”的那一类。管理员管老师、老师管题目、学生在线选题三条业务线听起来几句话能说清可一旦进到数据库设计阶段问题就冒出来了学生选题被拒之后还能不能重选题目删掉了历史选题记录怎么办一个老师最多放几个题目、每个题目能被几个人选这些细节正是答辩时老师最爱追问的地方。这份基于 Java JSP MySQL 5.7 的毕业选题系统把管理员、老师、学生三条线做成了完整的前后端自带 MySQL 建表脚本、JSP 页面、Eclipse 工程文件和说明文档适合做 Java Web 课程设计或毕业设计的人直接拿来部署再按学校要求改业务。下面按拆项目的顺序把权限设计、表结构、部署全流程和踩坑记录完整过一遍。2. 权限三角三条业务线如何映射到 MySQL 表2.1 三个角色的动作边界与表关系管理员、老师、学生是三种完全不同的操作视角。管理员动作是新增系主任信息、负责系统维护老师动作集中在题目录入和选题审核学生动作只有网上选题。角色边界如果不先定清楚后面写代码就会出现“老师页面调用了管理员 Servlet”的低级耦合。先把摘要里的模块动作拆成一张映射表这张表可以直接写进毕业设计的数据库设计章节。| 角色 | 核心动作 | 关联表 | 关键字段 | | 管理员 | 新增系主任信息、系统维护 | admin / dean | username、password、role | | 老师 | 录入毕业设计题、审核学生选题 | teacher / title / selection | teacher_id、title_id、status | | 学生 | 网上选题 | student / title / selection | student_id、title_id、status |这张表其实是业务逻辑的地基。title 表用于存题目selection 表用于存“谁选了哪个题”如果把选题直接冗余到 title 表里审核状态一变整条记录都要跟着改。拿到源码之后我一般会先打开 SQL 文件看它是“单用户表加 role 字段”还是“分角色独立建表”。从这份源码的模块边界看它更接近分表设计管理员一个表、老师一个表、学生一个表再配上题目和选题两张业务表。分表的好处是字段互不污染老师有 dept、学生有 class各存各的坏处是登录校验要写三个查询后面讲过滤器时会专门说怎么统一收敛。课程设计阶段不建议为了省事做成单用户表加 role虽然登录好写但答辩时老师一句“你这个 role 字段怎么保证学生不能越权改老师资料”就能问住。2.2 核心表设计与状态流转按合格毕设的规模库里有学生、老师、管理员三张用户表再加题目、选题两张业务表就够。如果你按摘要里的需求还要做系主任管理就再加一张 dean 表。下面给一份常用建模脚本导入 SQL 前先对照一下表名或字段名不一致就按压缩包里的实际脚本为准这份脚本的目的是让你知道每张表在干什么。CREATE TABLE student ( id INT(11) NOT NULL AUTO_INCREMENT, stu_no VARCHAR(32) NOT NULL COMMENT 学号, stu_name VARCHAR(64) NOT NULL COMMENT 姓名, class_name VARCHAR(64) DEFAULT NULL COMMENT 班级, password VARCHAR(64) NOT NULL DEFAULT 123456, PRIMARY KEY (id), UNIQUE KEY uk_stu_no (stu_no) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4; CREATE TABLE teacher ( id INT(11) NOT NULL AUTO_INCREMENT, teacher_no VARCHAR(32) NOT NULL COMMENT 教师工号, teacher_name VARCHAR(64) NOT NULL COMMENT 姓名, dept VARCHAR(64) DEFAULT NULL COMMENT 院系, password VARCHAR(64) NOT NULL DEFAULT 123456, PRIMARY KEY (id), UNIQUE KEY uk_teacher_no (teacher_no) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4; CREATE TABLE title ( id INT(11) NOT NULL AUTO_INCREMENT, teacher_id INT(11) NOT NULL COMMENT 出题老师ID, title_name VARCHAR(200) NOT NULL COMMENT 题目名称, description TEXT COMMENT 题目要求, max_select INT(11) NOT NULL DEFAULT 1 COMMENT 最大可选人数, status TINYINT(4) NOT NULL DEFAULT 0 COMMENT 0待审核 1通过 2拒绝, create_time DATETIME DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (id), KEY idx_teacher (teacher_id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4; CREATE TABLE selection ( id INT(11) NOT NULL AUTO_INCREMENT, student_id INT(11) NOT NULL COMMENT 学生ID, title_id INT(11) NOT NULL COMMENT 题目ID, status TINYINT(4) NOT NULL DEFAULT 0 COMMENT 0待审核 1通过 2拒绝, remark VARCHAR(255) DEFAULT NULL COMMENT 审核意见, create_time DATETIME DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (id), UNIQUE KEY uk_student_once (student_id), KEY idx_title_status (title_id, status) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;这段脚本里有几个参数值得注意。max_select控制一个题目能被几个学生选默认 1 就是“一个萝卜一个坑”title.status管老师出题后要不要管理员审核selection.status管学生选完题后老师审核的进度。uk_student_once这个唯一索引保证一个学生同时只有一条选题记录防止学生反复提交把题库刷花。状态流转的完整链路是老师录入题目后title.status0管理员或老师自己审核通过后变为 1学生选了这个题selection.status0老师审核通过变为 1拒绝变为 2。这里有一个很多新手会掉进去的坑拒绝之后学生需要重新选题但uk_student_once还占着这条唯一索引直接 INSERT 会报 Duplicate entry。常见做法是重新选题前先把旧记录的status改成 2再允许学生插入新记录或者更简单直接在“重新选题”按钮里先执行一条 UPDATE 把旧记录置为拒绝再执行 INSERT。这个细节很小但答辩时主动说出来面试官会觉得你真的跑过数据。2.3 并发抢题与事务边界课程设计项目一般不聊高并发但“同一个热门题目被两个学生同时选”在演示现场真的可能出现。老师鼠标点得快学生那边同时提交就会出现超过max_select的情况。处理办法不复杂在插入选题记录前做一次条件查重用事务包起来。START TRANSACTION; SELECT id FROM title WHERE id 1 AND status 1 FOR UPDATE; SELECT COUNT(*) AS selected FROM selection WHERE title_id 1 AND status IN (0, 1); -- 如果 selected max_selectROLLBACK 并提示题目已满 INSERT INTO selection(student_id, title_id, status) VALUES (1001, 1, 0); COMMIT;FOR UPDATE在 InnoDB 下会对题目记录加行锁让两个并发请求排队执行第二个请求进来时selected已经等于 1就会回滚。这里要提醒一句JSP 老项目通常直接用 JDBC 连接事务必须绑定同一个 Connection如果项目中有人在每次查询时都重新getConnection()事务是失效的。拿到源码后搜一下setAutoCommit(false)没有的话这个并发保护大概率没做答辩前补上是一大亮点。3. 源码落地JDK1.8 MySQL 5.7 Tomcat 全流程3.1 拿到压缩包先看什么很多同学下载完源码第一件事就是双击.classpath或者直接往 Eclipse 里拖结果报错一堆。我的习惯是先把压缩包里的文件和文档列一遍心里有数再动手。这份资源里的核心文件大致如下。| 文件/目录 | 在工程里的作用 | 部署时怎么处理 | | 说明文档 / LW | 论文与使用说明 | 按学校模板改题目名别照抄 | | 多个 .caj 论文 | 参考文献与设计思路 | 用知网阅读器打开只借鉴思路 | | db.java / db.class | 数据库连接与 JDBC 封装 | 改成自己本机的库名、账号、密码 | | .classpath | Eclipse 工程描述文件 | 导入时自动加载不用手改 | | style.css / base.css / CssAdmin.css / editor.css | 前台与后台样式 | 不用动答辩时是加分项 |db.class是编译后的产物.classpath是 Eclipse 的工程配置这些文件都不需要手动编辑。如果导入时 Eclipse 提示“No projects are found to import”大概率是这个工程没有.project文件可以用 General File System 方式导入再通过 Configure Build Path 把 src 目录指为 Source Folder。3.2 MySQL 5.7 建库与脚本导入先用命令行或 Navicat 建一个空库字符集要指定为 utf8mb4不然导入老 SQL 脚本容易出现中文乱码。MySQL 5.7 的默认字符集是utf8和 JSP 页面里的UTF-8并不完全匹配最省事的方式是建库时直接定死。mysql -uroot -p CREATE DATABASE IF NOT EXISTS graduation DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; USE graduation; SOURCE /path/to/graduation.sql;用 Navicat 11 操作也可以连接上 MySQL右键点击“运行 SQL 文件”选择压缩包里的.sql前提是脚本里没有写死USE xxx否则库会跑到别的名下。导入完成后打开表列表确认 student、teacher、title、selection 等表都出现了再进表看一下数据有没有正常写入。这里补一个 MySQL 5.7 时代的老问题如果脚本是用 mysqldump 从 5.6 导出的可能带ENGINEMyISAMMyISAM 不支持事务和外键按 2.3 写的FOR UPDATE锁会完全失效。导入后用SHOW TABLE STATUS查一下Engine列如果是 MyISAM执行ALTER TABLE 表名 ENGINEInnoDB;批量改掉。3.3 Eclipse 导入与 Tomcat 部署环境版本先对齐JDK 1.8 对应 Eclipse 2019 之后的版本都可以Tomcat 建议用 8.5 或 9。Tomcat 10 开始包名从javax.servlet改成了jakarta.servlet老课程设计代码几乎全部启动失败这是传统 JSP 项目和现代容器之间最大的兼容性断层不要在这个上面白耗一下午。# 部署前把 MySQL 连接驱动放进 WEB-INF/lib # 老工程常见版本是 mysql-connector-java-5.1.x.jar # JDK1.8 下不要用 8.0.33 新版驱动部分老 JDBC 代码会报 SSL 连接警告 mysql-connector-java-5.1.49.jarEclipse 里导入File Import Existing Projects into Workspace选择解压后的目录。导入成功后找到数据库封装类比如DBUtil.java或db.java把连接串改成自己的配置。String url jdbc:mysql://localhost:3306/graduation ?useUnicodetruecharacterEncodingutf-8 serverTimezoneAsia/Shanghai; String user root; String password 你的数据库密码;useUnicodetruecharacterEncodingutf-8是 JSP 老项目最重要的两个连接参数少了它页面传过来的中文到数据库大概率变??。serverTimezoneAsia/Shanghai是 MySQL 8.x 才严格要求的5.7 加上也不报错顺手写。改完之后右键项目 Run As Run on Server启动成功后浏览器访问地址。项目名就是部署后 URL 里的路径比如http://localhost:8080/graduation/login.jsp。如果首页想直接访问可以检查 web.xml 里有没有配welcome-file没有就手动把login.jsp加进去否则访问根路径会 404这是老工程最常见的“我以为没启动成功”假象。4. 避坑指南JSP 项目从导入到答辩的高频问题4.1 定位报错的三层方法论导入后出了问题别急着打开 Java 文件逐行读先按层定位。部署层看 Tomcat 是否成功把项目加载进 webapps容器层看控制台有没有 ClassNotFound 或 Listener 异常数据层看数据库连接、字符集、表结构。这三层顺序固定从外往里查五分钟内就能把 90% 的问题缩小到具体文件。我见过最典型的浪费时间场景页面报 500同学直接去翻 Servlet 代码翻了两小时没找到问题最后发现是 lib 目录下根本没有 mysql 驱动 jar。所以下面的踩坑记录都按“现象发生在外层原因往往藏在配置里”来写。4.2 五条高频踩坑记录第一条ClassNotFoundException: com.mysql.jdbc.Driver。现象是启动后一登录就 500 错误控制台明确提示找不到 JDBC 驱动。原因是 mysql-connector-java 的 jar 没有放进WEB-INF/lib或者放进去了但没被编译发布到 Tomcat。解决方法是确认 jar 在构建路径里然后在 Eclipse 的 Deployment Assembly 里检查WEB-INF/lib是否包含这个 jar。老项目经常出现“Build Path 有但部署没有”的错位这是 JSP 工程特有的坑。第二条切换 Tomcat 10 后大量 Servlet 报错。现象是项目在 Tomcat 9 正常换到 Tomcat 10 直接启动失败报错指向javax.servlet.http.HttpServlet。原因是 Tomcat 10 迁移到了 Jakarta EEServlet 包名变成了jakarta.servlet老代码没有跟着改。解决方法是把部署容器固定为 Tomcat 8.5 或 9这是最省事的路径。如果学校强制要求 Tomcat 10就得全局替换 import 和 web.xml 里的命名空间工作量不小。第三条登录提交后数据库里中文全是问号。现象是页面显示正常但SELECT出来???或者老师录入的题目名称乱码。原因通常是三个地方没统一JSP 页面contentTypetext/html; charsetUTF-8、Servlet 里request.setCharacterEncoding(UTF-8)、JDBC 连接串characterEncodingutf-8。三个缺一个都会出问题优先级最高的其实是 JSP 页面和连接串因为 Student 表在插入前可能已经丢了编码信息。第四条访问根路径 404但手动输入/login.jsp能开。现象是http://localhost:8080/graduation/找不到页面加上 login.jsp 就正常。原因是老工程的web.xml没有声明欢迎页。解决是在web.xml里加welcome-filelogin.jsp/welcome-file或者部署时不改代码、直接约定访问带路径的地址。第二种方式虽然能跑但演示时显得不够专业建议改配置。第五条选题成功但列表不刷新总感觉系统没反应。现象是学生提交选题后页面上还是“未选”状态强刷一下才出现。原因多半是浏览器缓存了旧 CSS 或 JSP 页面老项目没有做缓存控制。解决是开发时用 CtrlF5 强制刷新也可以在 JSP 的head里加禁用缓存的 meta但这只对部分浏览器生效最省心的是改完 JSP 后重启 Tomcat。4.3 答辩前自检清单部署跑通之后别急着写论文先按角色走一遍完整路径。用管理员登录新增一个系主任账号确认权限里不能直接改学生成绩用老师登录录入两个题目一个正常、一个故意留空标题看看有没有校验用学生登录选一个老师刚录入的题目再回老师端审核通过。这五个动作串起来基本覆盖了系统所有核心表的关键字段。如果演示时只能演示一次我建议演示“学生选题 老师审核 管理员维护”这条主链路讲清楚selection.status从 0 到 1 的变化比展示十个页面都管用。老 JSP 项目的答辩重点从来不是页面多漂亮而是数据在表与表之间怎么流动这一点要在自检时顺手记下几句话术。5. 低成本进阶一个过滤器加一条唯一约束如果想让这份课程设计在答辩时有明显区分度我建议补两样东西一个登录状态过滤器把三个角色的登录校验统一起来一条唯一约束防止同一个学生重复选题。前者只要一个 Java 类后者就是一行 SQL但两个都命中评委最爱问的“安全性”和“数据一致性”。WebFilter(/*) public class LoginFilter implements Filter { Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletRequest req (HttpServletRequest) request; HttpServletResponse resp (HttpServletResponse) response; HttpSession session req.getSession(false); String uri req.getRequestURI(); if (uri.endsWith(login.jsp) || uri.contains(LoginServlet) || uri.endsWith(.css) || uri.endsWith(.js) || uri.endsWith(.png)) { chain.doFilter(request, response); return; } if (session null || session.getAttribute(role) null) { resp.sendRedirect(req.getContextPath() /login.jsp); return; } chain.doFilter(request, response); } }这个过滤器的核心参数是role登录成功时从数据库查询该用户的角色名放进 Session。放行名单要把静态资源和登录接口放出去否则项目一启动样式全丢、登录请求自己被拦死。老工程项目放src目录即可Servlet 3.0 以上支持注解配置不用在 web.xml 里手动加filter。配合唯一约束给selection.student_id补一个唯一索引这一步能用 SQL 直接说明数据一致性设计ALTER TABLE selection ADD UNIQUE KEY uk_student_once (student_id);之所以建议加索引不是加应用层判断是因为应用层并发时会有检查空隙数据库层的唯一约束才是最后一道保险。从那以后我每次拿到这类 JSP 老项目都会先做两件事扫一遍WEB-INF/lib下的 jar 确认 mysql 驱动和 Servlet 版本再查一遍所有建表语句确认字符集和唯一索引这两个动作比改业务代码更能避免临时出状况。希望这篇拆解能帮你在毕业选题系统上少走几步弯路祝答辩顺利。本文还有配套的精品资源点击获取

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

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

免费获取报价 →
↑