ARTICLE DETAIL

资讯详情

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

JavaWeb体育竞赛管理系统:SSM+MySQL8配置与避坑全指南

JavaWeb体育竞赛管理系统:SSM+MySQL8配置与避坑全指南 简介面向JavaWeb课程设计或毕业设计人群的体育竞赛管理系统完整项目包基于jdk1.8、JSP/Servlet与MySQL 5.7实现覆盖运动员在线报名与成绩查看、管理员用户及参赛流程管理、裁判员成绩录入与排名公示等核心业务。资源共2662个文件含jsp/java/class等后端源码、html/css/js前端页面、sql数据库脚本及jar依赖库压缩包约29.37MB解压即可对照学习。系统通过自动化处理减少人工统计误差并提供成绩留存与公示机制适合需要快速理解JavaWeb分层架构、完成课程设计或论文支撑的读者。已有903人学习下载项目目录结构完整便于按模块定位代码与调试排错是一份可直接运行与二次开发的实战参考资料。1. JavaWeb体育竞赛管理系统为什么是毕设里最稳妥的一题毕设题“基于JavaWeb的体育竞赛管理系统”在每年的选题库里都不缺人因为它把用户、赛事、报名、检录、成绩、公告连成一条完整业务链能覆盖 JavaWeb 阶段绝大多数考点也天然适合拿 MySQL 做数据支撑。很多同学第一次跑通整套项目就是在做这类 JavaWeb 项目时完成的。题目本身不会太惊艳但胜在“安全”评审不会纠结工作量和原创性答辩时也能把每一个表、每一个接口讲清楚。这篇按我实际配环境和改项目时的顺序来写从技术选型、数据库设计、IDEA 运行配置到常见报错给出一套可以直接照着配完并继续扩展的方案适合 JSP SSM 栈还没完全理清的新手也适合答辩前想快速预演一遍的应届生。2. 技术栈重量级决策SSM JSP MySQL 8配比和理由2.1 为什么我用 SSM 而不是 Spring Boot答辩尺度和部署成本的平衡这个题目叫“JavaWeb”而 JavaWeb 课程体系的核心是 Servlet、JSP、Filter、Listener 以及 JDBC。很多案例一上来就是 Spring Boot结果答辩老师问“你讲讲 Servlet 生命周期”时学生只能答“我用的是 Spring Boot没直接写过 Servlet”。所以在毕设尺度下我一般会选择 SSM 组合Spring SpringMVC MyBatis外面套 JSP。这套组合里 SpringMVC 的 DispatcherServlet 本身就是 Servlet核心链路仍然要求你把 web.xml、Spring 容器、MyBatis 会话工厂串起来既能对上课程知识点又能体现项目规模。版本选择上建议这一套看起来老但在 JDK 8 环境下最不容易翻车组件推荐版本理由JDK1.8.0_202 或 8u291和 Tomcat 9 兼容且大多数电脑已经装了Maven3.6.3对中央仓库依赖解析最稳Tomcat9.0.65 左右Servlet 4.0支持 JavaWeb 项目标准目录结构Spring / SpringMVC5.3.x兼容 JDK 8 与 Tomcat 9别再升到 Spring 6MyBatis3.5.x配合 mybatis-spring 2.0.xMySQL8.0.x比 5.7 多了一点“技术时髦度”但要注意驱动类名变化mysql-connector-java8.0.33驱动类名是 com.mysql.cj.jdbc.Driver 而不是旧版 com.mysql.jdbc.Driver注意MySQL 8 的驱动类名和连接参数都和 5.7 不一样后面第 4 章里我会给出可直接用的 jdbcUrl 配置第 5 章会专门列一个因为驱动类名报错的案例。这套技术栈跑在毕设里论“内存消耗”和“部署复杂度”都比 Spring Boot MyBatis-Plus 低也更好手写演示。2.2 三层架构包结构与项目骨架清单项目骨架如果建对了后面每一层写起来都不会乱。我建议的包结构如下只放业务相关的不搞过度设计src/main/java └─ com.sports.contest ├─ controller # SpringMVC 控制器负责接收请求和返回视图 ├─ service # 业务接口 ├─ service.impl # 业务实现 ├─ mapper # MyBatis 的 Mapper 接口只写抽象方法 ├─ entity # 实体类对应数据库表 ├─ common # 通用返回体、分页参数、常量 ├─ interceptor # 登录拦截、权限拦截 └─ util # 赛程编排工具、日期工具 src/main/resources ├─ spring-mvc.xml ├─ spring-mybatis.xml ├─ mybatis-config.xml ├─ jdbc.properties └─ mapper ├─ UserMapper.xml ├─ EventMapper.xml ├─ SignupMapper.xml ├─ ScheduleMapper.xml └─ ScoreMapper.xml src/main/webapp/WEB-INF ├─ web.xml ├─ views # JSP 页面 │ ├─ admin │ ├─ user │ └─ common └─ lib # 如果不用 Maven 时手动放 jar常见做法是使用 Maven 管理依赖时不在 WEB-INF/lib 下手动放 jar所以我建议 pom.xml 一把梭后面排查依赖冲突也方便。三层架构里最容易被忽略的是 service 接口和 impl 分离很多同学图省事只写一个类答辩时被问“业务层为什么要分接口和实现”容易答不上来所以这个习惯最好留好。SpringMVC 的 Controller 层只做参数接收和视图跳转不写 SQLMapper 层只写一对一的 SQL 映射业务编排包括事务、赛程生成、成绩计算都放 Service 层。这套职责划分在答辩时可以直接展开讲本身也是 JavaWeb 项目完整案例里最吸引评审的细节。3. 数据库设计与核心业务表七张表怎么扛起一场运动会3.1 体育竞赛系统的实体关系与建表细节“体育竞赛管理系统”说到底是在管理一个完整的赛事流程管理员发布赛事运动员报名系统编排赛程裁判录入成绩系统自动算排名。和电商系统比它少了很多支付对账逻辑但多了一个“赛程编排”和“成绩排序”的业务难点这也是答辩时可以主动展示的部分。数据库设计我建议用 7 张表不多不少用户表、角色表、赛事表、报名表、赛程表、成绩表、公告表。建表时优先考虑以下边界项目只涉及一个学校或一个单位内的比赛所以“代表队”可以做成用户表里的一个字段而不单独建 team 表如果一定要强调团体总分再单独抽出 team 表但那样就要加第三范式上的冗余设计反而不适合毕设体量。下面直接给出核心表的 MySQL 建表语句选用 MySQL 8 语法。注意字段注释必须写清楚方便答辩时对着表结构讲。CREATE DATABASE sports_contest DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; USE sports_contest; CREATE TABLE t_user ( id INT PRIMARY KEY AUTO_INCREMENT, username VARCHAR(30) NOT NULL UNIQUE COMMENT 登录名建议用学号或工号, password VARCHAR(64) NOT NULL COMMENT MD5或BCrypt后的密文不要存明文, real_name VARCHAR(30) NOT NULL COMMENT 姓名, role_id INT NOT NULL DEFAULT 2 COMMENT 1管理员2运动员, team_name VARCHAR(50) DEFAULT NULL COMMENT 代表队/班级, phone VARCHAR(20) DEFAULT NULL, create_time DATETIME DEFAULT CURRENT_TIMESTAMP, INDEX idx_role (role_id) ) ENGINEInnoDB COMMENT 用户表; CREATE TABLE t_event ( id INT PRIMARY KEY AUTO_INCREMENT, event_name VARCHAR(50) NOT NULL COMMENT 赛事名称男子100米预赛, event_type TINYINT NOT NULL COMMENT 1单人项目2团体项目, category VARCHAR(20) NOT NULL DEFAULT 田径 COMMENT 项目分类, start_time DATETIME DEFAULT NULL COMMENT 计划开始时间, place VARCHAR(100) DEFAULT NULL COMMENT 比赛地点, max_players INT NOT NULL DEFAULT 8 COMMENT 每组人数或项目人数上限, status TINYINT NOT NULL DEFAULT 0 COMMENT 0报名中1已截止2进行中3已结束 ) ENGINEInnoDB COMMENT 赛事表; CREATE TABLE t_signup ( id INT PRIMARY KEY AUTO_INCREMENT, event_id INT NOT NULL COMMENT 赛事ID, user_id INT NOT NULL COMMENT 运动员ID, group_no INT DEFAULT NULL COMMENT 预赛分组号编排后写入, signup_time DATETIME DEFAULT CURRENT_TIMESTAMP, status TINYINT NOT NULL DEFAULT 0 COMMENT 0待审核1通过2拒绝, UNIQUE KEY uk_event_user (event_id, user_id) ) ENGINEInnoDB COMMENT 报名表; CREATE TABLE t_schedule ( id INT PRIMARY KEY AUTO_INCREMENT, event_id INT NOT NULL, group_no INT NOT NULL COMMENT 第几组/第几轮, lane_no INT DEFAULT NULL COMMENT 跑道号或出场顺序, user_id INT NOT NULL COMMENT 参赛人ID, round_no INT NOT NULL DEFAULT 1 COMMENT 第几轮1预赛2决赛, UNIQUE KEY uk_event_group_lane (event_id, group_no, lane_no) ) ENGINEInnoDB COMMENT 赛程表; CREATE TABLE t_score ( id INT PRIMARY KEY AUTO_INCREMENT, schedule_id INT NOT NULL COMMENT 关联赛程表的具体参赛记录, event_id INT NOT NULL, user_id INT NOT NULL, score DECIMAL(6,2) DEFAULT NULL COMMENT 成绩如12.58秒, rank_no INT DEFAULT NULL COMMENT 本组名次, is_qualified TINYINT DEFAULT 0 COMMENT 是否晋级, remark VARCHAR(200) ) ENGINEInnoDB COMMENT 成绩表;建表时有几个细节值得单讲。一是时间字段全部用 DATETIME不用 TIMESTAMP因为 TIMESTAMP 在 MySQL 8 里有时区转换问题毕设项目部署在不同电脑上容易出现“少 8 小时”的鬼现象。二是成绩字段用 DECIMAL(6,2)因为体育成绩要精确到百分之一秒而秒数最大也就是两位数加一个小数点6 位总长度足够用。三是报名表上加了联合唯一键uk_event_user这样同一赛事同一人不可能重复报名省去在 Service 层做重复判断。3.2 赛程编排算法怎么用一次分组生成不冲突的赛程表赛程编排是本项目里最值得拿出来讲讲的“业务算法”比单纯的增删改查要有内容得多。常见做法是首先把报名审核通过的人放到一个 List 里然后按每组上限人数去分组分组之后把每个运动员写进 t_schedule 表再给 t_signup 表回填 group_no。这里最大的坑是“随机分组的可复现性”。很多同学会直接用SELECT * FROM t_signup ORDER BY RAND()然后循环分到各组。这在数据量小的时候没问题但答辩老师常会问一句“你这个随机数是完全随机的吗如果我想指定种子做实验怎么办”。所以我建议在 Service 层做一个简单的“轮转分组”工具不依赖数据库随机public MapInteger, ListSignup assignGroups(ListSignup signups, int groupSize) { // 按报名时间排序保证稳定顺序 signups.sort(Comparator.comparing(Signup::getSignupTime)); MapInteger, ListSignup groups new LinkedHashMap(); int groupNo 1; for (int i 0; i signups.size(); i) { if (i % groupSize 0 i 0) { groupNo; } groups.computeIfAbsent(groupNo, k - new ArrayList()).add(signups.get(i)); } return groups; }逻辑说明先用signupTime排序这是报名顺序不是数据表里的自增 ID。然后按groupSize切分第 1 到 8 个人进第 1 组第 9 到 16 个人进第 2 组。这样产生的结果在相同输入下是固定的不会出现跑一次一个样的问题。需要调整时只要在排序前加一个“种子参数”比如按学号最后一位、抽签顺序号来预排序就能手动控制编组结果。参数说明groupSize不要硬编码读取 t_event 表的max_players字段如果项目是团体赛则按团队整体作为分组单位字段含义变成“每队人数”。生成 t_schedule 写入时要注意lane_no单人项目要交错分配跑道避免同组同一单位运动员连续挨着这个小细节在答辩时提出来会加分。4. 在 IDEA 里跑通项目的完整过程从 JDK 到 Tomcat 的一次成型4.1 JDK、Tomcat、Maven、Spring 版本的一组兼容清单热搜里“idea运行javaweb项目配置”是点击量很高的词原因很简单很多项目不是写不出来是配环境配到怀疑人生。如果电脑里已经装了不同版本的 JDKIDEA 会弹出“Project SDK 不匹配”的提示这时候不要无脑选最新版。SSM 这套东西依赖的是 Java 8 的一些旧特性比如javax.servlet包名升到 JDK 17 后 JSP 和 Tomcat 9 都会出现兼容问题。所以先统一版本再写代码不然代码写完了也启动不了。通用兼容原则可以按下面这张表对齐项目版本备注Project SDK1.8IDEA 里设置为 18 或 1.8Java Compiler8在 Settings → Build → Compiler 里对应切换Maven3.6.3避免 Maven 3.9 在解析旧依赖时行为变化Tomcat9.0.x支持 Servlet 4.0配 IDEA 时选择 Tomcat ServerSpring5.3.xspring-webmvc、spring-jdbc、spring-txMyBatis3.5.16mapper 注解和 XML 都支持这里有个容易忽略的点IDEA 里“Tomcat Server”配置中的 JRE 默认使用的是Default如果你机器上同时有 JDK 8 和 JDK 17一定要手动选择 JDK 8否则 Tomcat 虽然启动了报错信息却指向 JSP 编译器版本问题非常难定位。4.2 web.xml 与 spring-mybatis.xml最容易被忽略的三处配置DD 文件web.xml是 JavaWeb 项目的“门面”很多毕设项目里 web.xml 版本号是 2.3这会直接导致 EL 表达式不生效、JSP 里${}全部原样输出。我建议 web.xml 直接用 Servlet 3.1 版本声明同时把 DispatcherServlet 和编码过滤器写好web-app xmlnshttp://xmlns.jcp.org/xml/ns/javaee xmlns:xsihttp://www.w3.org/2001/XMLSchema-instance xsi:schemaLocationhttp://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd version3.1 filter filter-nameencodingFilter/filter-name filter-classorg.springframework.web.filter.CharacterEncodingFilter/filter-class init-param param-nameencoding/param-name param-valueUTF-8/param-value /init-param init-param param-nameforceEncoding/param-name param-valuetrue/param-value /init-param /filter filter-mapping filter-nameencodingFilter/filter-name url-pattern/*/url-pattern /filter-mapping servlet servlet-namespringmvc/servlet-name servlet-classorg.springframework.web.servlet.DispatcherServlet/servlet-class init-param param-namecontextConfigLocation/param-name param-valueclasspath:spring-mvc.xml/param-value /init-param load-on-startup1/load-on-startup /servlet servlet-mapping servlet-namespringmvc/servlet-name url-pattern//url-pattern /servlet-mapping /web-app逻辑说明CharacterEncodingFilter必须放在所有过滤器的最前面放在后面会导致 request 参数在进入 Controller 前已经按 ISO-8859-1 解析了一次后面再编码也没用这是 JSP 中文乱码最常见的根因。load-on-startup设为 1 表示 Tomcat 启动时立刻初始化 Spring 容器而不是等第一个请求进来才初始化这样启动阶段就能看到 Spring 配置错误而不是等在线用户触发。连接数据库的配置放在 spring-mybatis.xml 里这文件也是 404、500 错误的集中营bean iddataSource classcom.zaxxer.hikari.HikariDataSource constructor-arg bean classcom.zaxxer.hikari.HikariConfig property namejdbcUrl valuejdbc:mysql://localhost:3306/sports_contest?useUnicodetrueamp;characterEncodingutf8mb4amp;useSSLfalseamp;serverTimezoneAsia/Shanghaiamp;allowPublicKeyRetrievaltrue/ property namedriverClassName valuecom.mysql.cj.jdbc.Driver/ property nameusername valueroot/ property namepassword value你的密码/ /bean /constructor-arg /bean注意 jdbcUrl 有两个反直觉的点一是useSSLfalse一定要显式写否则 MySQL 8 默认趋向 SSL 安全连接本地环境经常会握手失败二是allowPublicKeyRetrievaltrue这是 MySQL 8 新增的参数不写就会报Public Key Retrieval is not allowed。把driverClassName写成com.mysql.cj.jdbc.Driver注意“cj”两个字不能省写旧驱动类名com.mysql.jdbc.Driver在 MySQL 8 下也会提示找不到类。4.3 在 IDEA 里配置 Tomcat 运行的完整动作项目准备好后很多人卡在 IDEA 不知道怎么把它跑起来。这里按步骤给出我一般会走的路按顺序操作基本不会翻车第一步File → Project Structure → Artifacts确认 Web Application 的 Exploded 包存在并确认其 Output Layout 里有依赖包如果没有右键 Add Copy of Configuration Files 把 WEB-INF/classes 加进去。这一步不做启动后控制台会报一大堆 ClassNotFoundException。第二步Run → Edit Configurations点左上角加号选 Tomcat Server → Local。再切到 Deployment 页签点加号选择 Artifact关键是 Application Context 这一栏。我一般统一填/sports这样项目访问路径是http://localhost:8080/sports不会出现“项目根路径后面还带个随机后缀”的可访问性问题。第三步切到 Server 页签把 On Update Action 设置为 Redeploy这样修改代码后 IDEA 会重新部署而不是 accumulate 旧 class。Open Browser 可以取消勾选避免每次弹新页面。第四步启动。如果能在控制台看到以下输出说明 JavaWeb 项目骨架已经通了Using CATALINA_BASE: ...\apache-tomcat-9.0.65 Starting ProtocolHandler [http-nio-8080] Deploying web application archive ... Context path: /sports到这里访问http://localhost:8080/sports/login.jsp能打开登录页就说明从 IDEA 到 Tomcat 再到 SpringMVC 的最小链路已经跑通。5. 避坑排查JavaWeb 体育竞赛系统的五个必踩之坑与对症解决5.1 MySQL 8 连接时报 Public Key Retrieval is not allowed现象Tomcat 启动不报错但一查数据库页面就抛异常控制台出现Public Key Retrieval is not allowed。原因MySQL 8 默认使用 caching_sha2_password 加密方式客户端第一次连接需要向服务器请求公钥做 RSA 加密但 JDBC 驱动默认不允许自动获取公钥。解决在 jdbcUrl 中追加allowPublicKeyRetrievaltrueuseSSLfalse。同时确认 MySQL 用户是rootlocalhost不要用root%。5.2 启动时 ClassNotFoundException: com.mysql.cj.jdbc.Driver现象IDEA 控制台直接抛java.lang.ClassNotFoundException: com.mysql.cj.jdbc.Driver。原因pom.xml 里没有引 mysql-connector-java或者引了旧版本 5.1.x。旧驱动类名是com.mysql.jdbc.Driver新版是com.mysql.cj.jdbc.Driver两个类名看着像但是两个不同的类。解决pom.xml 使用 8.0.33 版本依赖并确认依赖是compile而非provided如果是provided作用域Tomcat 运行时也拿不到。5.3 JSP 页面中文全部变成问号或乱码现象页面标题、查询结果里的中文都显示为???或者打开页面是乱码但正常启动。原因分三层断开。第一Tomcat 的 server.xml 里 Connector 没有配置URIEncodingUTF-8第二web.xml 里的 CharacterEncodingFilter 没有生效第三数据库连接串里没有指定characterEncodingutf8mb4。三层里任何一层断掉都会出现。解决三个地方一起改。server.xml 的 8080 Connector 加URIEncodingUTF-8web.xml 里按 4.2 节配置过滤器jdbcUrl 里显式写characterEncodingutf8mb4。改完重启 Tomcat刷新浏览器。这个坑我每年都能遇到属于玄学式乱码但对症下药就是这三处。5.4 Invalid bound statement (not found): com.sports.contest.mapper.UserMapper.findByName现象Controller 能正常进入但调用 Mapper 方法时抛org.apache.ibatis.binding.BindingException: Invalid bound statement (not found)。原因MyBatis 的 Mapper 接口找到了但 Mapper XML 文件没被识别。一般是两个原因mapper XML 放在了src/main/java目录Maven 默认只打包 resources 下的 XML或者 spring-mybatis.xml 里mapper-locations指定了classpath:mapper/*.xml但 XML 文件没在根路径。解决把 XML 文件移到src/main/resources/mapper/下pom.xml 的buildresources里补充包含src/main/java下的 xml 文件也可以但最省事的做法是统一放 resources。确认 spring-mybatis.xml 里设置了basePackagecom.sports.contest.mapper和mapperLocationsclasspath:mapper/*.xml。5.5 每次修改 JSP 都要重启 Tomcat启动还报内存溢出现象改动一个 JSP 页面后刷新浏览器不生效必须手动 Redeploy频繁操作后 IDEA 弹OutOfMemoryError: PermGen space或Metaspace。原因Tomcat 默认部署模式没开热部署JSP 改动没有触发编译IDEA 分配给 Tomcat 的 JVM 内存太小反复 restart 累积了旧 class。解决在 Run Configurations 的 Server 页签设置 On Update Action 为 Redeploy并在 VM options 里加一段-Xms256m -Xmx512m -XX:MetaspaceSize128m -XX:MaxMetaspaceSize256m。如果是 Tomcat 9只要改 JSP 文件本身IDEA 会自动重新编译 JSP 而不用重启整个服务这是 JSP 比 Servlet 在开发期的最大优势别把热部署功能浪费了。6. 上策在这赛程编排和权限拦截器让“展示型毕设”变成“可运行系统”6.1 用拦截器做粗粒度权限不引入 Shiro 也够答辩用权限这块很多毕设会选择集成 Spring Security 或 Shiro但我觉得在体育竞赛管理系统里是杀鸡用牛刀。直接用 SpringMVC 的 HandlerInterceptor 做两个拦截就够登录拦截和角色拦截。做法是写一个LoginInterceptor实现HandlerInterceptor接口的preHandle方法检查 session 里是否存在登录用户如果是去 admin 开头的路径再检查用户的 role_id 是否为 1。在 spring-mvc.xml 里配置mvc:interceptors interceptor mvc:mapping path/**/ mvc:exclude-mapping path/login.jsp/ mvc:exclude-mapping path/user/login/ mvc:exclude-mapping path/css/**/ mvc:exclude-mapping path/js/**/ /interceptor /mvc:interceptors逻辑说明/**表示拦截全部请求但要把登录页、登录接口和静态资源排除掉否则用户还没登录就被重定向到登录页形成死循环。这个配置在答辩时可以直接答出来为什么不抽权限表因为角色只有管理员和运动员两种用拦截器做粗细粒度控制在设计上更简单也符合最小实现原则。6.2 验证业务代码的两种实用手段事务回滚和成绩排序系统跑通后一定要做一次全链路自测。我通常用两个手段验证。第一事务回滚测试在报名 Service 方法里同时执行插入报名表和更新报名人数两个操作故意让第二个操作失败观察第一个操作是否回滚如果回滚了说明Transactional配置生效。第二成绩排名验证录入一组故意相同的小数成绩确认ORDER BY score ASC, signup_time ASC能稳定给出名次。最后收个尾。做毕设时我的一个习惯是每完成一个功能点就把浏览器地址栏里对应的 URL 和关键报错贴进一个本地 README 里这样答辩演示时不用临时回忆功能入口而且出了问题能快速定位是哪个 Controller。这个题目本身不难但把赛程编排、报名去重、权限拦截和事务管理这四处做好就已经比大多数“仓库里只有增删改查”的 JavaWeb 项目完整案例更像一个真正能运转的管理系统。希望帮到你。本文还有配套的精品资源点击获取
返回列表