ARTICLE DETAIL

资讯详情

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

SSM框架+JSP学校运动会信息管理系统:从分层架构到部署排错全解析

SSM框架+JSP学校运动会信息管理系统:从分层架构到部署排错全解析 简介基于SSMSpring、SpringMVC、MyBatis框架的学校运动会信息管理系统毕业设计资源配有JSP前端页面和毕业论文文档适合Java方向毕设学生、SSM初学者也适合需要部署运动会管理系统的校方或开发者用于解决运动会项目设置、参赛人员管理、成绩录入与查询、统计分析等场景中的信息分散、统计效率低等问题。压缩包约67.57MB内含项目源代码、JSP页面、资源配置文件及论文文档源代码与页面构成可运行的Web应用论文文档辅助理解整体设计代码注释清晰、模块划分明确便于按模块查阅和二次开发。目前已有68人浏览学习。系统覆盖运动会信息管理的关键业务采用模块化和低耦合设计既可直接用于毕业设计答辩演示也可作为二次开发的参考基座深入研读可掌握SSM整合流程、JSP交互实现及数据库操作技巧还能从需求分析到系统实现获得完整的实战经验。1. 基于 SSM 框架 JSP 的学校运动会信息管理系统毕设选题到底在考察什么毕业设计题目里同时出现 ssm 和 jsp 的 Java 项目每年在各类源码站上的下载量都排得很靠前。这个标题看似只描述了一个再普通不过的信息管理系统实际上它同时考察了三层能力SSM 表明项目采用 Spring、Spring MVC、MyBatis 这种经典服务端组合JSP 承担服务器端页面渲染学校运动会管理则要求做真实业务建模——比赛项目维护、运动员报名、裁判录入成绩、团体总分排名。很多人的误区是把压缩包下载下来就直接打开 Eclipse 跑数据库等答辩老师问一次报名请求从 JSP 到数据库再返回页面中间经过哪些对象时就语塞。这篇博文顺着该标题把 SSM 运动会项目的分层原理、核心表设计、部署排错和论文互证讲清楚全部还原成一个可动手复现的方案。2. SSM 框架在这个运动会项目里的分工以及 JSP 为什么不该被换成模板引擎2.1 一次成绩录入请求如何穿过 Spring、Spring MVC 与 MyBatis运动会系统里最典型的一条请求链路是裁判登录后在 JSP 页面的表单里输入运动员编号、比赛成绩点击保存浏览器把请求提交到 web.xml 中配置的 DispatcherServletSpring MVC 根据 RequestMapping 找到对应 Controller 方法Controller 调用 ServiceService 调用 Mapper 接口MyBatis 把接口方法映射到 XML 中的 SQL最终写入 score 表。理解各层边界是答辩时第一个能展示动手写过的地方。一个 SSM 项目最简可运行的 Maven 依赖通常这样配properties maven.compiler.source1.8/maven.compiler.source maven.compiler.target1.8/maven.compiler.target spring.version5.2.22.RELEASE/spring.version /properties dependencies dependency groupIdorg.springframework/groupId artifactIdspring-context/artifactId version${spring.version}/version /dependency dependency groupIdorg.springframework/groupId artifactIdspring-webmvc/artifactId version${spring.version}/version /dependency dependency groupIdorg.mybatis/groupId artifactIdmybatis/artifactId version3.5.6/version /dependency dependency groupIdorg.mybatis/groupId artifactIdmybatis-spring/artifactId version2.0.6/version /dependency dependency groupIdmysql/groupId artifactIdmysql-connector-java/artifactId version5.1.49/version /dependency dependency groupIdjavax.servlet/groupId artifactIdjstl/artifactId version1.2/version /dependency /dependencies参数说明Spring 选 5.2.x 而不是 5.3.x主要考虑与旧项目里 javax.servlet 命名空间兼容用 JSP 时不需要引入 jakarta 替换。MySQL 驱动 5.1.49 适合 5.7 库本地若装 MySQL 8.0驱动类名要改成 com.mysql.cj.jdbc.Driver。JSTL 必须显式引入否则页面上 c:forEach 直接报 500。逻辑说明spring-webmvc 会传递依赖 spring-core、spring-beans不需要逐个手工加mybatis-spring 负责把 SqlSessionFactory 纳入 Spring 容器管理这一步配错会导致启动时提示找不到 mapper。2.2 JSP 在 SSM 项目里是视图层不是模板层JSP 本质上是一个特化 Servlet。第一次被访问时Tomcat 把 JSP 转译成 Java 文件再编译成 class产生的 .class 文件不在源码目录而是落在 work/Catalina/localhost/项目名/org/apache/jsp 下。开发期改了 JSP 没效果先找 JSP 编译后的 class 文件在哪再查 IDE 是否把新 JSP 发布到了 webapps最后清浏览器缓存。顺序不能反因为 Tomcat 是否重新编译由文件时间戳决定和浏览器缓存无关。页面层在运动会系统里通常只做三件事用 EL 表达式输出数据用 JSTL 做条件判断和循环用 form 表单发起请求。比如只有管理员能删除成绩c:if test${sessionScope.loginUser.role admin} a href${pageContext.request.contextPath}/score/delete?scoreId${score.scoreId} onclickreturn confirm(确认删除该成绩记录)删除/a /c:if不建议在 JSP 里写大段 Java 脚本片段。应付本地测试没问题答辩展示时容易被评委抓住问为什么不用 MVC 标签库。更稳妥的做法是 JSP 里只保留 EL 和 JSTL需要复杂逻辑时在 Controller 层组装好数据放进 Model。2.3 用 include 机制统一页面框架避免每个 JSP 都写重复头尾运动会系统的页面数量并不少登录页、后台首页、项目管理页、报名页、成绩录入页、排行榜页。每个页面都重复写head、css、js会很臃肿。常见做法是把公共部分拆成 header.jspf 和 footer.jspf然后静态引入% include file/common/header.jspf % div classcontent 当前页面自己的内容 /div % include file/common/footer.jspf %这里用静态 include 而不是jsp:include原因在于静态引入发生在 JSP 转译阶段公共变量和 taglib 指令能共享jsp:include是运行时请求转发适合内容需要动态计算的场景。公共页面一旦拆好后续加菜单权限、加统计脚本都只改一处。3. 学校运动会信息管理系统的数据库与状态流转从报名到成绩公示3.1 五张表的边界与字段设计运动会业务比普通 CRUD 复杂。学校运动会通常分个人项目和团体项目个人项目如 100 米、跳远团体项目如 4×100 接力、拔河。同一个学生可报多个个人项目一个班级在团体项目上只能报一支队伍。把个人和团体都放进一张项目表用 item_type 区分报名表再记录报名主体是比较省力的设计。推荐的最小表集合如下表名关键字段说明useruser_id, username, password, role, class_idrole 区分管理员 / 裁判 / 学生classclass_id, class_name班级维度用于团体总分排行sports_itemitem_id, item_name, item_type, limit_countitem_type 区分个人 / 团体signupsignup_id, user_id, item_id, team_name, status报名记录含个人或团体scorescore_id, item_id, signup_id, result, rank, is_disqualify成绩与名次最容易忽视的是 signup 表上的联合唯一索引。个人项目不允许同一人重复报名团体项目不允许同一班级重复报名。用数据库约束比业务层判断可靠CREATE TABLE signup ( signup_id INT PRIMARY KEY AUTO_INCREMENT, user_id INT NOT NULL COMMENT 报名人个人项目为学生ID团体项目为代表ID, item_id INT NOT NULL COMMENT 比赛项目, team_name VARCHAR(50) DEFAULT NULL COMMENT 团体项目队伍名称, status TINYINT DEFAULT 0 COMMENT 0-已报名 1-已检录 2-已完赛 3-已公示, create_time DATETIME DEFAULT CURRENT_TIMESTAMP, UNIQUE KEY uk_signup (user_id, item_id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;参数说明uk_signup 限制同一人不能重复报名同一项目。如果产品规则允许同一班级不同负责人分别报团体项目应把唯一键改成 (item_id, team_name)。status 的意义不只是展示还会被检录页面、成绩录入页面和成绩公示页面共用。若平时练习想增加工作量可以再加初赛复赛表但就毕业设计而言五张表已经能把论文里的 E-R 图和流程图撑起来。3.2 用 MyBatis 动态 SQL 实现多条件筛选和分页运动会后台几乎每个列表页都需要筛选按项目名模糊查、按赛事类型筛选、按报名状态筛选。如果把筛选条件用字符串拼接会有 SQL 注入风险MyBatis 的 where 标签可以自动处理多余的 ANDselect idselectSignupPage resultTypemap SELECT s.signup_id, u.username, i.item_name, s.status FROM signup s LEFT JOIN user u ON s.user_id u.user_id LEFT JOIN sports_item i ON s.item_id i.item_id where if testitemName ! null and itemName ! AND i.item_name LIKE CONCAT(%, #{itemName}, %) /if if testitemType ! null and itemType ! AND i.item_type #{itemType} /if if teststatus ! null AND s.status #{status} /if /where ORDER BY s.item_id, s.signup_id /select代码逻辑用 LEFT JOIN 而不是 INNER JOIN保证未录入成绩但已报名的记录也能被列表查出方便裁判补录。LIKE 参数用 CONCAT 拼接是为了让 #{} 预编译生效。分页在 SSM 项目里最常用 PageHelperController 中执行 PageHelper.startPage(pageNum, pageSize) 后再把查询结果包装成 PageInfo 返回。注意 PageHelper 的页码从 1 开始不是 0。3.3 成绩录入的 Service 事务与报名状态机录入成绩时系统要同时写入 score 表并更新 signup 表的 status这两步不能一个成功一个失败。这类业务必须用 Spring 声明式事务Service public class ScoreServiceImpl implements ScoreService { Autowired private ScoreMapper scoreMapper; Autowired private SignupMapper signupMapper; Transactional(rollbackFor Exception.class) public void saveScore(Score score, Integer signupId) { scoreMapper.insert(score); signupMapper.updateStatus(signupId, 2); // 若此处抛出 SQLExceptionscore 的写入也会回滚 } }参数说明rollbackFor Exception.class 必须写。Spring 默认只对 RuntimeException 回滚如果 SQL 执行时抛的是受检异常不写该参数会导致成绩表写入了、报名状态没更新。如果系统还要在录入成绩后重新计算班级团体总分这段重算逻辑也应放在同一个事务方法中避免总分和成绩明细不一致。答辩如果被追问事务可以补充一个观点Transactional 不要放在 Controller 层。Controller 的职责是接收参数、调用 Service、返回页面事务边界按照业务边界来划一个 Service 方法对应一个完整业务动作。这样既方便后续加缓存也方便做单元测试。3.4 团体总分排名一条聚合 SQL 替代页面里做循环运动会项目中团体总分排行是最容易被学生写成循环嵌套的查询。实际上用一条分组聚合 SQL 就能完成也方便论文中作为难点写SELECT c.class_name, SUM(CASE WHEN sc.rank 1 THEN 9 WHEN sc.rank 2 THEN 7 WHEN sc.rank 3 THEN 6 WHEN sc.rank 4 THEN 5 WHEN sc.rank 5 THEN 4 WHEN sc.rank 6 THEN 3 WHEN sc.rank 7 THEN 2 WHEN sc.rank 8 THEN 1 ELSE 0 END) AS total_score FROM score sc JOIN signup sg ON sc.signup_id sg.signup_id JOIN user u ON sg.user_id u.user_id LEFT JOIN class c ON u.class_id c.class_id WHERE u.role student GROUP BY c.class_id ORDER BY total_score DESC;这段 SQL 把名次转换为积分的规则集中在 CASE 表达式中后续如果学校规定破纪录多加 5 分只需要在 CASE 里增加分支不需要改动 Java 代码。GROUP BY 后只能查询 class_id、class_name 和聚合函数字段若想同时显示班级人数要新加一个 COUNT 聚合不能把 user_id 一块 SELECT 出来这是改这类 SQL 时最常踩的坑。4. 把源代码从压缩包变成可答辩项目Java 环境、JSP 编译与 Tomcat 部署排错4.1 源码导入前先核对 Java 环境变量、Maven 仓库和 MySQL 字符集很多源码无法启动问题不在代码而在环境基线。第一步配置 Java 环境变量设置 JAVA_HOME 指向 JDK 安装目录Path 里追加 %JAVA_HOME%\bin命令行里用 java -version 验证。第二步确认 Maven 的 settings.xml 是否配置了阿里云镜像SSM 项目依赖数量不算少没有镜像可能卡在下载依赖上。第三步创建空数据库执行项目里提供的 SQL 文件检查库名是否和 jdbc.properties 一致。典型数据库连接配置如下jdbc.drivercom.mysql.jdbc.Driver jdbc.urljdbc:mysql://localhost:3306/sports_meet?useUnicodetruecharacterEncodingutf8serverTimezoneAsia/Shanghai jdbc.usernameroot jdbc.password123456参数说明characterEncodingutf8 保证应用与 MySQL 交互时使用 UTF-8serverTimezone 是 MySQL 8.x 驱动必加参数否则启动时会报 time zone 相关错误。MySQL 5.7 数据库可以沿用 com.mysql.jdbc.Driver如果改成 MySQL 8.0建议把 driver 同步换成 com.mysql.cj.jdbc.Driver。这里最常见的现象是项目别人能跑你跑不了先别急着怀疑代码应该先用mysql --version确认数据库版本。4.2 JSP 改了不生效先找编译后的 class 文件再查缓存开发 SSM 项目时最典型的灵异事件是JSP 页面改了刷新浏览器还是旧页面。需要理解 JSP 的执行路径Tomcat 收到请求后发现某个 JSP 文件时间戳比已编译的 class 新就会重新把 .jsp 转译为 .java再 javac 编译成 .class写回 work 目录。排错时按以下顺序检查在 Tomcat 日志中搜索 compiling 或 reload确定 JSP 是否被重新编译。到部署目录下的 work 路径查找input_jsp.class比较文件时间戳。用浏览器无痕窗口重新访问页面。命令行查找 JSP 编译后的 class 文件find /opt/tomcat/work -name input_jsp.class 2/dev/null命令说明find 从 Tomcat 的 work 目录递归查找指定 JSP 对应的 class如果找不到说明该 JSP 还没有被访问过或者部署上下文路径不对。这里要注意的是IntelliJ IDEA 中使用 war exploded 部署时修改 JSP 后需要手动执行 Build - Rebuild不能只刷新浏览器。还有另一种少见情况项目里同时存在 /jsp/score/input.jsp 和 /pages/score/input.jsp请求路径映射到了旧页面造成改了不生效的错觉。4.3 Tomcat 上下文路径与静态资源 404毕设演示最后通常要打成 war 包部署。war 包命名会决定上下文路径例如 sports.war 部署后访问地址是http://localhost:8080/sports/。如果 JSP 里的 CSS、JS 路径写的是/static/css/main.css实际请求会变成http://localhost:8080/static/css/main.css自然 404。最稳妥的写法是在 JSP 中使用 EL 表达式拼接上下文路径link relstylesheet href${pageContext.request.contextPath}/static/css/main.css script src${pageContext.request.contextPath}/static/js/common.js/script这样无论项目以 root 方式部署还是以 sports 子目录方式部署静态资源路径都能自动适配。建议把这段公共资源引用放进 header.jspf而不是在每个 JSP 里重复手写。答辩演示换电脑、换 Tomcat 时这个细节最能避免现场翻车。4.4 常见启动失败原因速查表这几个问题在 SSM 项目中出现频率最高可以把它们写进论文的系统调试章节现象直接原因修法启动时报端口占用Tomcat 的 8080 被其他进程占用修改 server.xml 端口或结束占用进程提示找不到 UserMapperMyBatis 没有扫描到 mapper XML在 spring-mybatis.xml 中配置 mapperLocations页面中文乱码JSP 编码与数据库编码不一致JSP 头加 UTF-8JDBC URL 加 characterEncoding北京时间报错MySQL 连接未指定时区URL 添加 serverTimezoneAsia/Shanghai启动后访问 404context path 与访问路径不匹配访问 /war包名/ 前缀或设置 path/排查这类问题不要使用全部重新安装的思路。先看 Tomcat 的 localhost.log再逐层缩小范围通常两分钟内能定位到配置问题。这也是答辩时展示工程能力的好机会。5. 毕业论文里的系统测试章节用成绩导出 Excel 添一个可复现的验证用例5.1 导出接口与论文测试用例对应表毕业论文中的功能测试若只写点击按钮页面显示数据正确很难有说服力。一个常见做法是增加成绩导出 Excel 的功能在论文里用测试用例表描述预期结果。这里给出一个基于 Apache POI 的导出接口代码放在 ReportController 中Controller RequestMapping(/report) public class ReportController { Autowired private ScoreService scoreService; RequestMapping(/export) public void export(HttpServletResponse response) throws Exception { ListScoreVO list scoreService.listAllForReport(); response.setContentType(application/vnd.ms-excel); response.setHeader(Content-Disposition, attachment;filenamescores_ System.currentTimeMillis() .xls); Workbook workbook new HSSFWorkbook(); Sheet sheet workbook.createSheet(运动会成绩); String[] headers {项目, 班级, 姓名, 成绩, 名次}; Row headerRow sheet.createRow(0); for (int i 0; i headers.length; i) { headerRow.createCell(i).setCellValue(headers[i]); } int rowIdx 1; for (ScoreVO s : list) { Row row sheet.createRow(rowIdx); row.createCell(0).setCellValue(s.getItemName()); row.createCell(1).setCellValue(s.getClassName()); row.createCell(2).setCellValue(s.getStudentName()); row.createCell(3).setCellValue(s.getResult()); row.createCell(4).setCellValue(s.getRank()); } workbook.write(response.getOutputStream()); workbook.close(); } }代码逻辑该接口返回值定义为 void因为数据直接写入 HttpServletResponse 的输出流不需要返回视图名。Content-Type 让浏览器识别为 ExcelContent-Disposition 触发下载。这里还要在 pom.xml 中引入 Apache POI 依赖版本可以选择 3.17 或 4.1.2导出成绩时如果 result 字段是秒数建议在 SQL 里先拼成字符串避免 Excel 自动转为数字格式。论文中的对应测试用例可以这样设计用例编号前置条件操作步骤预期结果EXP-01成绩表至少有一条数据在成绩列表页点击导出 Excel浏览器下载 .xls 文件表头正确EXP-02成绩表为空点击导出下载文件只有表头无数据行EXP-03数据包含中文字段用 Excel 打开文件中文无乱码5.2 用 curl 对导出接口做一次可复现验证答辩演示时最怕页面点击弹下载框出问题可以在论文的系统测试部分补充一条 curl 验证命令把结果以文本形式留存curl -s -o /tmp/scores.xls \ -w HTTP状态码:%{http_code} 文件大小:%{size_download}\n \ -b JSESSIONID你的登录会话ID \ http://localhost:8080/sports/report/export参数说明-o 把下载内容保存到本地文件-w 输出 HTTP 状态码和文件大小-b 带上登录后的 Cookie。若返回状态码 200 且文件大小大于 0说明导出链路正常若文件大小为 0通常是后台异常被 Spring 捕获后返回 error 页面。打开 /tmp/scores.xls 确认表头与数据行数这份命令输出可以直接截图放进论文系统测试小节替代重复的界面截图。本文还有配套的精品资源点击获取
返回列表