ARTICLE DETAIL

资讯详情

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

Java+JSP+MySQL毕业设计选题系统实战指南

Java+JSP+MySQL毕业设计选题系统实战指南 简介本资源是一套基于Java Web技术栈开发的毕业设计选题管理系统面向高校计算机类专业师生解决毕业设计课题发布、分配与过程管理中的多角色协同难题。系统采用JSPServletMySQL架构部署于Tomcat环境完整实现管理员、教师、学生三类角色的权限隔离与核心业务流程管理员可维护用户与课题信息并执行系统维护教师可发布及查看课题学生可浏览并自主选题。资源包共221个文件含98个JSP页面实现前后端交互、58个GIF图标界面资源、24个Class字节码编译后的业务逻辑、12个Java源码含TopicManager、TeacherManager等核心管理类、7个XML配置文件及SQL初始化脚本等整体压缩后仅5.57MB结构清晰、模块分明。已有2416人学习下载提供开箱即用的完整工程、可直接运行的数据库脚本及典型Web分层架构实践范例适合Java Web初学者巩固MVC开发流程也便于课程设计或毕设快速原型搭建。1. 为什么用 JavaJSPMySQL 做毕业设计选题系统不是“过时”而是稳扎稳打的工程选择你手头正赶着计算机专业本科毕业设计导师说“必须是 Web 系统”同学在卷 Spring Boot Vue而你翻到一份写着「JavaJSPMySQL」的毕设模板——第一反应可能是这玩意儿是不是该进博物馆了但现实是全国高校计算机类毕设答辩现场每年仍有超 65% 的 Web 类选题系统教务选课、论文管理、实验室预约、实习双选跑在 Tomcat 9 JSP MySQL 5.7/8.0 这套组合上。它不炫技但胜在零外部依赖、单机可部署、调试链路透明、答辩老师一眼看懂架构。尤其对没接触过微服务、没配过 Nginx 反向代理、连mvn clean install都要查三次命令的新手这套技术栈意味着不用猜 jar 包冲突、不用调跨域、不用啃 YAML 配置玄学、数据库报错直接贴堆栈就能定位到 SQL 拼写。它解决的不是“高并发秒杀”而是“300 个学生同时刷选题页面不卡死、管理员改一个状态字段立刻生效、导出 Excel 表格格式不乱码”这种真实、琐碎、但答辩必问的落地问题。如果你的目标是两周搭出可演示、可截图、可写进论文第三章系统设计的完整闭环系统而不是花三周调通 Spring Security 的权限拦截器——那这套组合不是退而求其次而是精准卡点。2. 从零建起用最简路径跑通选题系统骨架2.1 环境准备只装这 4 个东西别碰任何“一键安装包”提示所有工具必须用稳定长期支持版LTS拒绝最新版。MySQL 用 5.7.44兼容性最好Tomcat 用 9.0.83JSP 2.3 兼容无坑JDK 用 1.8.0_391不是 17不是 21。这些版本在各大高校机房、答辩演示机上预装率最高避免答辩当天因 JDK 版本报Unsupported major.minor version直接翻车。JDK 1.8官网下载jdk-8u391-windows-x64.exe安装后配置JAVA_HOME指向C:\Program Files\Java\jdk1.8.0_391PATH加%JAVA_HOME%\binTomcat 9.0.83解压到D:\tomcat9不要放 C 盘 Program Files 下Windows 权限坑多启动bin\startup.bat浏览器访问http://localhost:8080出现猫图标即成功MySQL 5.7.44用官方 MSI 安装器安装时勾选 “Add to PATH” 和 “Configure MySQL as a service”root 密码设为123456答辩演示用非生产环境Eclipse IDE for Enterprise Developers2023-09 版不是 VS Code不是 IntelliJ是 Eclipse。原因内置 Tomcat 插件成熟、JSP 编辑器语法高亮准、Servlet 向导一键生成、Debug 时变量值实时可见——这对新手 debugrequest.getParameter(title)返回 null 这种问题效率提升 3 倍验证命令行java -version # 必须输出 java version 1.8.0_391 mysql -uroot -p123456 -e SELECT VERSION(); # 必须输出 5.7.442.2 数据库建模3 张表撑起核心业务拒绝过度设计选题系统本质是“多对多关系管理”学生选题、教师出题、管理员审核。别一上来就建 10 张表、加外键级联、搞视图存储过程。先跑通主干再迭代。以下是答辩通过率最高的最小可行结构SQL 直接复制执行-- 创建数据库注意字符集答辩机常因 utf8mb4 导致中文乱码 CREATE DATABASE thesis_selection CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; USE thesis_selection; -- 教师表存工号、姓名、职称、可带学生数上限 CREATE TABLE teacher ( id INT PRIMARY KEY AUTO_INCREMENT, emp_id VARCHAR(20) UNIQUE NOT NULL, -- 工号登录账号 name VARCHAR(20) NOT NULL, title VARCHAR(10) DEFAULT 讲师, -- 职称 max_students INT DEFAULT 5 -- 最多带几个学生 ); -- 学生表存学号、姓名、专业、年级、已选题目ID冗余字段加速查询 CREATE TABLE student ( id INT PRIMARY KEY AUTO_INCREMENT, stu_id VARCHAR(12) UNIQUE NOT NULL, -- 学号登录账号 name VARCHAR(20) NOT NULL, major VARCHAR(30) DEFAULT 计算机科学与技术, grade YEAR DEFAULT 2024, -- 入学年份用于筛选应届生 selected_topic_id INT DEFAULT 0 -- 当前已选题目ID0未选 ); -- 题目表存题目ID、标题、描述、指导教师ID、状态0待审核1已发布2已选满 CREATE TABLE topic ( id INT PRIMARY KEY AUTO_INCREMENT, title VARCHAR(100) NOT NULL, description TEXT, teacher_id INT NOT NULL, status TINYINT DEFAULT 0, -- 0:待审核 1:已发布 2:已选满 created_time DATETIME DEFAULT NOW(), FOREIGN KEY (teacher_id) REFERENCES teacher(id) );参数说明utf8mb4是必须项否则 JSP 页面提交中文标题会变???selected_topic_id在 student 表中冗余存储省去每次查选题状态都要 JOIN topic 表降低答辩演示时页面加载延迟status用TINYINT而非ENUM因为 MySQL 5.7 对 ENUM 排序和 JDBC 读取有兼容性问题答辩老师用 Navicat 查数据时可能显示异常。2.3 项目结构Eclipse 里手动建 Web Project不走 Maven为什么不用 Maven因为毕设答辩环境大概率没配 Maven 镜像源pom.xml里一个spring-webmvc依赖下载失败整个项目红叉你当场崩溃。手动管理 jar 包反而可控。在 Eclipse 中File → New → Dynamic Web Project项目名填ThesisSelectionSystemTarget runtime 选你装好的 Tomcat 9点击Finish后右键项目 →Properties → Deployment Assembly确认WebContent映射到/手动创建目录结构ThesisSelectionSystem/ ├── WebContent/ │ ├── index.jsp ← 首页登录入口 │ ├── login.jsp ← 登录页区分学生/教师/管理员 │ ├── student/ ← 学生功能页 │ │ ├── dashboard.jsp ← 学生首页显示可选题目列表 │ │ └── select.jsp ← 选题提交页 │ ├── teacher/ ← 教师功能页 │ │ ├── add_topic.jsp ← 发布题目页 │ │ └── manage.jsp ← 管理自己题目页 │ └── admin/ ← 管理员页简单审核 │ └── audit.jsp ├── WEB-INF/ │ ├── web.xml ← 核心配置定义 Servlet 和欢迎页 │ └── lib/ ← 手动放 jar 包的地方 └── src/ ← Java 类放这里关键 jar 包全部从 Tomcat 自带或 MySQL 官网下载不搜第三方servlet-api.jar从D:\tomcat9\lib\复制过来不要删这是编译 JSP 必需mysql-connector-java-5.1.47.jarMySQL 官网下载的 5.1.x 版不是 8.0.xJSP 用 JDBC 4.05.1.47 兼容性最好jstl-1.2.jar用于c:if等标签从 Jakarta 官网下载血泪经验mysql-connector-java-8.0.33.jar在 JSP 中Class.forName(com.mysql.cj.jdbc.Driver)会报ClassNotFoundException因为驱动类名变了而老式 JSP 写法没适配。用 5.1.47一行代码搞定Class.forName(com.mysql.jdbc.Driver);3. 核心功能实现3 个 Servlet 5 个 JSP覆盖全部答辩场景3.1 登录控制用 Filter 拦截未登录请求比 Session 判断更可靠很多同学用session.getAttribute(user) null做登录校验结果在多标签页切换时 session 丢失页面空白。用 Filter 是更底层、更稳定的方案。新建src/filter/LoginFilter.javapackage filter; import javax.servlet.*; import javax.servlet.http.*; import java.io.IOException; public class LoginFilter implements Filter { Override public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException { HttpServletRequest request (HttpServletRequest) req; HttpServletResponse response (HttpServletResponse) resp; // 放行静态资源和登录页 String uri request.getRequestURI(); if (uri.contains(/login.jsp) || uri.contains(/css/) || uri.contains(/js/) || uri.contains(/images/)) { chain.doFilter(req, resp); return; } // 检查 session 中是否有 user 属性登录后存的 HttpSession session request.getSession(false); if (session null || session.getAttribute(user) null) { response.sendRedirect(request.getContextPath() /login.jsp); return; } chain.doFilter(req, resp); } Override public void init(FilterConfig filterConfig) throws ServletException {} Override public void destroy() {} }在WEB-INF/web.xml中注册必须放在servlet标签之前filter filter-nameLoginFilter/filter-name filter-classfilter.LoginFilter/filter-class /filter filter-mapping filter-nameLoginFilter/filter-name url-pattern/*/url-pattern /filter-mapping逻辑说明Filter 在请求到达 Servlet 前执行比在每个 JSP 顶部写% if(session.getAttribute(user)null) response.sendRedirect(login.jsp); %更干净。它统一拦截所有请求且对/student/dashboard.jsp和/teacher/add_topic.jsp一视同仁避免漏掉某个页面导致未登录也能访问。3.2 学生选题JSP 表单 Servlet 处理 JDBC 更新三步闭环student/dashboard.jsp显示可选题目列表status1 且未满% page contentTypetext/html;charsetUTF-8 languagejava % % taglib prefixc urihttp://java.sun.com/jsp/jstl/core % html headtitle可选题目/title/head body h2请选择毕业设计题目/h2 table border1 trth题目编号/thth题目名称/thth指导教师/thth操作/th/tr c:forEach items${topicList} vart tr td${t.id}/td td${t.title}/td td${t.teacherName}/td tda hrefSelectTopicServlet?id${t.id}选择/a/td /tr /c:forEach /table /body /htmlsrc/servlet/SelectTopicServlet.java处理点击事件package servlet; import dao.TopicDao; import dao.StudentDao; import model.Student; import javax.servlet.ServletException; import javax.servlet.http.*; import java.io.IOException; public class SelectTopicServlet extends HttpServlet { Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { int topicId Integer.parseInt(request.getParameter(id)); Student student (Student) request.getSession().getAttribute(user); // 1. 检查该题目是否可选状态1且未满 if (!new TopicDao().canSelect(topicId)) { request.setAttribute(msg, 该题目暂不可选请刷新页面重试); request.getRequestDispatcher(/student/dashboard.jsp).forward(request, response); return; } // 2. 检查学生是否已选题 if (student.getSelectedTopicId() ! 0) { request.setAttribute(msg, 您已选择题目不可重复选择); request.getRequestDispatcher(/student/dashboard.jsp).forward(request, response); return; } // 3. 执行选题更新 student 表 selected_topic_id更新 topic 表选中人数隐含在 canSelect 里 boolean success new StudentDao().selectTopic(student.getId(), topicId); if (success) { // 刷新 session 中的学生对象 student.setSelectedTopicId(topicId); request.getSession().setAttribute(user, student); request.setAttribute(msg, 选题成功); } else { request.setAttribute(msg, 选题失败请重试); } request.getRequestDispatcher(/student/dashboard.jsp).forward(request, response); } }dao/StudentDao.java中的selectTopic()方法关键事务控制public boolean selectTopic(int studentId, int topicId) { String sql UPDATE student SET selected_topic_id ? WHERE id ?; String sql2 UPDATE topic SET status 2 WHERE id ? AND (SELECT COUNT(*) FROM student WHERE selected_topic_id ?) (SELECT max_students FROM teacher WHERE id (SELECT teacher_id FROM topic WHERE id ?)); try (Connection conn DBUtil.getConnection(); PreparedStatement ps1 conn.prepareStatement(sql); PreparedStatement ps2 conn.prepareStatement(sql2)) { conn.setAutoCommit(false); // 开启事务 ps1.setInt(1, topicId); ps1.setInt(2, studentId); int rows1 ps1.executeUpdate(); ps2.setInt(1, topicId); ps2.setInt(2, topicId); ps2.setInt(3, topicId); int rows2 ps2.executeUpdate(); conn.commit(); // 两步都成功才提交 return rows1 0; } catch (SQLException e) { try { conn.rollback(); // 任一步失败回滚 } catch (SQLException ex) { ex.printStackTrace(); } e.printStackTrace(); return false; } }参数说明conn.setAutoCommit(false)是防止“学生选上了但题目状态没更新”这种数据不一致sql2中嵌套子查询判断是否已达教师带生上限避免手动查再更新带来的并发问题两个学生同时点同一个题目DBUtil.getConnection()是封装好的工具类确保每次获取连接都用utf8mb4字符集代码略需保证?useUnicodetruecharacterEncodingutf8mb4在 URL 中。3.3 教师发布题目JSP 表单校验 Servlet 参数清洗防 SQL 注入teacher/add_topic.jsp表单必须做前端校验防误操作 后端清洗防注入form actionAddTopicServlet methodpost label题目名称input typetext nametitle required maxlength100/labelbr label题目描述textarea namedescription rows4 cols50 required/textarea/labelbr input typesubmit value发布题目 /formAddTopicServlet.java中的关键清洗逻辑protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding(UTF-8); // 防止中文乱码 String title request.getParameter(title).trim(); String description request.getParameter(description).trim(); // 【关键清洗】移除危险字符保留中文、字母、数字、常见标点 title title.replaceAll([^\\u4e00-\\u9fa5a-zA-Z0-9\\s\\-\\_\\.,;:!?], ); description description.replaceAll([^\\u4e00-\\u9fa5a-zA-Z0-9\\s\\-\\_\\.,;:!?\\n\\r], ); // 长度校验 if (title.length() 5 || title.length() 100 || description.length() 20) { request.setAttribute(msg, 题目名称需5-100字描述需不少于20字); request.getRequestDispatcher(/teacher/add_topic.jsp).forward(request, response); return; } Teacher teacher (Teacher) request.getSession().getAttribute(user); boolean success new TopicDao().addTopic(title, description, teacher.getId()); if (success) { request.setAttribute(msg, 题目发布成功等待管理员审核); } else { request.setAttribute(msg, 发布失败请重试); } request.getRequestDispatcher(/teacher/add_topic.jsp).forward(request, response); }为什么不用 PreparedStatement 防注入PreparedStatement 确实能防 SQL 注入但 JSP 场景下用户输入还会渲染到页面如题目描述展示若没清洗scriptalert(1)/script就会 XSS。所以清洗是双重保险既防 DB 层注入也防前端 XSS。此处正则[^\\u4e00-\\u9fa5a-zA-Z0-9\\s\\-\\_\\.,;:!?]保留中文、英文字母、数字、空格及安全标点其他一律剔除——答辩演示时哪怕学生输一堆乱码页面也不会崩。4. 避坑指南答辩前必查的 5 个致命细节4.1 现象JSP 页面中文显示为??数据库里却是正常中文原因JDBC 连接 URL 缺少useUnicodetruecharacterEncodingutf8mb4或 Tomcat 的server.xml中 Connector 缺少URIEncodingUTF-8解决DBUtil.java中连接字符串必须为jdbc:mysql://localhost:3306/thesis_selection?useUnicodetruecharacterEncodingutf8mb4useSSLfalseD:\tomcat9\conf\server.xml中找到Connector port8080添加属性URIEncodingUTF-8JSP 文件顶部必须声明% page contentTypetext/html;charsetUTF-8 %4.2 现象登录后跳转到index.jsp但页面空白控制台无报错原因web.xml中welcome-file-list未配置或配置了index.html却没这个文件解决在web.xml的web-app标签下添加welcome-file-list welcome-filelogin.jsp/welcome-file /welcome-file-list注意不要写index.jsp因为你的首页就是login.jsp避免多一层跳转。4.3 现象点击“选择题目”后报HTTP Status 404 – /ThesisSelectionSystem/SelectTopicServlet原因Servlet 没在web.xml中注册或 URL 映射路径写错解决必须在web.xml中显式声明JSP 时代不支持注解自动注册servlet servlet-nameSelectTopicServlet/servlet-name servlet-classservlet.SelectTopicServlet/servlet-class /servlet servlet-mapping servlet-nameSelectTopicServlet/servlet-name url-pattern/SelectTopicServlet/url-pattern /servlet-mapping血泪经验路径大小写敏感SelectTopicServlet和selecttopicservlet是两个东西。4.4 现象管理员审核题目后学生页面不刷新仍显示“待审核”原因JSP 页面缓存浏览器读了旧 HTML没发新请求解决在所有 JSP 页面head中加入强制不缓存头% response.setHeader(Cache-Control, no-cache, no-store, must-revalidate); response.setHeader(Pragma, no-cache); response.setDateHeader(Expires, 0); %玄学补充答辩演示前用 Chrome 无痕窗口打开避免本地缓存干扰。4.5 现象导出 Excel 功能报java.lang.NoClassDefFoundError: org/apache/poi/ss/usermodel/Workbook原因POI jar 包没放进WEB-INF/lib/或版本冲突用了 POI 5.x但 JDK 1.8 不支持解决下载poi-3.17.jar、poi-scratchpad-3.17.jar、poi-ooxml-3.17.jar3.17 是 JDK 1.8 兼容的最后稳定版全部放入WEB-INF/lib/不要只放 poi-3.17.jarpoi-ooxml依赖xmlbeans必须一起放代码中用HSSFWorkbookxls而非XSSFWorkbookxlsx避免xmlbeans版本问题5. 答辩加分技巧3 个让老师眼前一亮的轻量优化5.1 给 JSP 页面加“最后更新时间”证明你真写了代码很多同学交的系统页面 footer 写着©2024但老师一问“这个时间怎么来的”答“手动改的”。其实只要一行 JSP 表达式!-- 在所有 JSP 页面底部 -- div stylefont-size:12px; color:#999; text-align:center; margin-top:20px; 系统最后更新% new java.text.SimpleDateFormat(yyyy-MM-dd HH:mm:ss).format(new java.util.Date()) % /div为什么有效它证明你理解 JSP 的表达式% %是运行时执行 Java 代码不是静态文本。老师可能会追问“如果服务器时间不准怎么办”你可以答“实际项目中会对接 NTP 服务毕设环境以本地时间为准”。5.2 用 CSS 实现“选题成功”绿色弹窗比 alert() 更专业把原始的alert(选题成功)替换成内嵌样式弹窗代码少、效果稳、不打断流程!-- 在 dashboard.jsp 底部 -- c:if test${not empty msg} style .toast { position:fixed; top:20px; right:20px; background:#4CAF50; color:white; padding:12px 24px; border-radius:4px; z-index:9999; box-shadow:0 2px 10px rgba(0,0,0,0.2); } /style div classtoast${msg}/div script setTimeout(() document.querySelector(.toast).remove(), 3000); /script /c:if参数说明z-index:9999确保弹窗盖在所有元素上setTimeout3 秒后自动消失避免遮挡按钮box-shadow加阴影提升质感。这个技巧不需要额外 JS 库纯原生答辩时老师点选题弹窗滑入他点头说“嗯交互做了”。5.3 导出学生选题汇总 Excel用 POI 写真实业务逻辑别只导空表头。按答辩要求老师常要看“各专业选题分布”、“教师带题数量统计”。用 POI 写一个真实报表// src/servlet/ExportReportServlet.java protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { ListObject[] reportData new ReportDao().getTopicDistribution(); // 返回 [专业, 题目数, 平均难度] HSSFWorkbook workbook new HSSFWorkbook(); HSSFSheet sheet workbook.createSheet(选题分布报表); // 表头 HSSFRow headerRow sheet.createRow(0); String[] headers {专业, 题目数量, 平均难度}; for (int i 0; i headers.length; i) { headerRow.createCell(i).setCellValue(headers[i]); } // 数据行 for (int i 0; i reportData.size(); i) { HSSFRow row sheet.createRow(i 1); Object[] data reportData.get(i); row.createCell(0).setCellValue((String) data[0]); row.createCell(1).setCellValue((Integer) data[1]); row.createCell(2).setCellValue((Double) data[2]); } // 设置列宽 sheet.setColumnWidth(0, 5000); sheet.setColumnWidth(1, 3000); sheet.setColumnWidth(2, 4000); response.setContentType(application/vnd.ms-excel); response.setHeader(Content-Disposition, attachment; filenametopic_report.xls); workbook.write(response.getOutputStream()); }落地价值这个功能在答辩 PPT 里放一张 Excel 截图老师会认为“这学生真把系统当产品做了不是 Demo”。而且代码里HSSFWorkbook是 POI 3.17 的标准写法不会因版本问题报错。我带过 12 届毕设最常看到的翻车是学生花三周调通 Spring Cloud Gateway结果答辩机没装 Docker连镜像都拉不下来而用这套 JavaJSPMySQL 的只要环境配对Tomcat 一启页面就出来debug 时断点打在SelectTopicServlet第 15 行变量值清清楚楚。它不教你最潮的架构但它教会你一个能跑、能讲、能改、能答的系统才是毕业设计的本质。希望帮到你。本文还有配套的精品资源点击获取
返回列表