☰
基于JavaWeb的体育赛事管理系统毕设全攻略
2026/10/20 5:14:05 网站建设 项目流程

每年到了毕业设计选题的时候,“体育赛事管理系统”都是Java类题目里的热门选手。原因是这个题目看起来不复杂,业务场景又很具体,从赛事发布、在线报名、赛程编排到成绩统计,每一步都有明确的需求,不像很多管理系统那样只是单纯的增删改查,也不至于难到一个人做不完。但真正动手之后会发现,题目虽常见,坑也不少:时间冲突怎么判断、名次怎么算、权限怎么拦、部署时为什么总是连不上数据库,这些问题如果不提早想清楚,后面会反复返工。

这篇内容我打算按一个完整的JavaWeb毕设流程来梳理,围绕基于JavaWeb的体育赛事管理系统,从选题思路、需求设计、数据库建表、核心代码实现,一直讲到部署报错和文档、演示视频的整理。无论你是刚拿到题目还没开工,还是已经写了一半卡在某段逻辑上,这篇整理应该都能帮你少走几段弯路。

1. 选题分析:体育赛事管理系统的真实业务场景

1.1 这个系统到底在管什么

体育赛事管理系统不是一个竞技直播平台,它的核心工作是把一场线下赛事从“官方发布”到“最终颁奖”的全流程搬到线上。最常见的落地场景是校运动会、院级球赛、单位内部联赛,一般流程是:

  • 主办方创建一场赛事,设置比赛项目,比如男子100米、立定跳远、篮球团体赛;
  • 参赛者或者领队在线报名,填写个人信息、选择项目;
  • 赛事工作人员根据报名人数编排赛程,分配场地和时间;
  • 现场裁判在赛后录入比赛成绩;
  • 参赛者和观众可以随时查看赛程和成绩排名。

这条链路看起来简单,但每一步都有业务细节。比如一场赛事有多个项目,一个运动员可以报多个项目;报名要在截止时间之前;赛程编排时同一个场地不能被两场比赛占住;成绩单位可能是秒、也可能是米,排名规则不一样;成绩还要考虑并列名次。这些设计点如果拆开看,每个都是一个小业务模块,一个做JavaWeb的应届生能不能把逻辑理清,正适合通过这种题目来检验。

1.2 为什么“基于JavaWeb”的完整方案适合做成毕设

很多学校在JavaWeb课程里教的就是JSP、Servlet、JDBC、MySQL、Tomcat这一套,所以毕设题目里出现“基于JavaWeb”是基于教学体系的自然延续。对做毕设的人来说,这套技术栈有几个明显的优势。

第一,代码可控。传统Servlet/JSP写成什么样,请求怎么进、数据怎么取、页面怎么渲染,每一步都在自己手里。答辩时被问到“系统从登录到显示数据中间经历了什么”,你可以很自然地回答:浏览器发起请求,Servlet接收,调用Service,再通过DAO访问数据库,最后转发到JSP渲染。这套回答本身就是JavaWeb的考点。

第二,过程可见。容器启动、Servlet实例化、数据库连接、JSP翻译成Servlet类,每个环节都有明确报错和日志可查。对很多同学来说,这种“哪儿错了一眼能看到”的体验,比用一个自动帮你把所有事情做掉的框架更容易积累经验。

第三,工作量适中。完整做一套体育赛事管理系统,核心代码量通常在几千行量级,一个人花三四个月完全能做完,不会失控。

当然,学校如果允许用Spring Boot,也可以用框架来做,业务逻辑是一样的。但我的建议是,无论用什么技术,都一定要保留MVC分层的骨架:实体类、DAO、Service、控制器、页面各司其职。这样即使题目里写的是JavaWeb,答辩时老师说“你这个和Spring MVC有啥区别”,你也能把对照关系讲清楚。

2. 需求与设计:从需求分析到数据库落地

2.1 角色划分与权限体系

系统上线之前,先把角色想清楚,后面所有功能设计都会围绕角色展开。这个系统我建议按四类角色划分:

角色核心操作
管理员创建赛事、设置项目、发布公告、管理用户、结束赛事
裁判/工作人员查看赛程、录入成绩、审核成绩、维护场次状态
运动员/领队注册登录、浏览赛事、在线报名、查看个人成绩
游客/普通用户查看公开赛事信息、赛程和已公布成绩

权限控制建议分两层。页面层面用一个过滤器拦截需要登录或需要特定角色的目录,比如管理员的路径都放在/admin/下,裁判的路径放在/referee/下;方法层面再在Servlet里获取当前用户角色做二次校验。这样可以防止用户直接改URL绕过页面入口。

实际开发中,很多同学容易把角色写死在前端菜单上,觉得“我看不到就不存在了”。这不是权限控制,真正的判断必须放在后端。比如删除赛事、修改成绩这类操作,前端隐藏按钮只能算体验优化,后端不校验的话,接口被直接调用就出大事了。

2.2 核心功能模块拆解

赛事管理模块是整个系统的主线。管理员创建赛事时,至少需要填写赛事名称、赛事类型、开始时间、结束时间、举办地点、赛事说明、状态。状态字段是关键,建议设计成:0未发布、1报名中、2进行中、3已结束。很多业务规则都要依赖这个状态,比如只有状态为“报名中”的赛事才允许新增报名,状态为“进行中”才能录入成绩。

报名管理模块要处理的是报名资格、重复报名和截止时间。个人项目按人校验,团体项目按队伍校验。为了防止同一个人对同一个项目反复提交,数据库层面一定要给报名表加唯一约束,光靠代码判断是可能出漏洞的。

赛程编排模块是系统里的硬骨头。一个最简单的编排逻辑是:选择项目,选择场地,确定开始时间和结束时间,然后检查该时间段内场地是否已被占用。复杂一点可以支持批量生成,根据报名人数自动拆成预赛、决赛场次,但这个工作量较大,建议作为扩展点而不是核心目标。

成绩管理模块设计要区分“录入”和“公布”两个状态。裁判录入的成绩先进入待审核状态,裁判长或管理员审核通过后再对外展示。这样即使录错了也能撤回修改,不至于在页面上闹笑话。

公告模块属于锦上添花,用来发布报名通知、赛程变更信息,实现上就是简单的发布、编辑、置顶,难度不高,但能让系统看起来更完整。

2.3 数据库设计的关键表

数据库是整个系统的地基,表结构设计得不好,后面每个模块都会别扭。我建议至少包含以下核心表。

用户表t_user:

CREATE TABLE `t_user` ( `id` int(11) NOT NULL AUTO_INCREMENT, `username` varchar(50) NOT NULL, `password` varchar(128) NOT NULL, `real_name` varchar(50) DEFAULT NULL, `role` varchar(20) NOT NULL DEFAULT 'athlete', `phone` varchar(20) DEFAULT NULL, `create_time` datetime DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`), UNIQUE KEY `uk_username` (`username`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

赛事表t_event:

CREATE TABLE `t_event` ( `id` int(11) NOT NULL AUTO_INCREMENT, `event_name` varchar(100) NOT NULL, `event_type` varchar(50) DEFAULT NULL, `start_date` date DEFAULT NULL, `end_date` date DEFAULT NULL, `location` varchar(150) DEFAULT NULL, `status` tinyint(4) DEFAULT '0', `description` text, `create_time` datetime DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

比赛项目表t_project,重点要设计一个unit字段,因为排名规则取决于计量单位:

CREATE TABLE `t_project` ( `id` int(11) NOT NULL AUTO_INCREMENT, `event_id` int(11) NOT NULL, `project_name` varchar(100) NOT NULL, `project_type` varchar(20) DEFAULT 'personal', `unit` varchar(20) DEFAULT 'time', `max_applicants` int(11) DEFAULT '100', `apply_deadline` datetime DEFAULT NULL, PRIMARY KEY (`id`), KEY `idx_event_id` (`event_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

报名表t_enrollment要加联合唯一索引,这是防止重复报名最关键的一层保护:

CREATE TABLE `t_enrollment` ( `id` int(11) NOT NULL AUTO_INCREMENT, `project_id` int(11) NOT NULL, `user_id` int(11) NOT NULL, `status` tinyint(4) DEFAULT '0', `create_time` datetime DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`), UNIQUE KEY `uk_project_user` (`project_id`, `user_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

赛程表t_schedule和成绩表t_score是联动的,赛程表里的场地、开始时间、结束时间字段就是为了做冲突检测服务。成绩表里建议增加rank_no和status字段,一个用来展示名次,一个用来控制成绩是否对外公开。

表与表之间的关系也要提前画清楚:一份赛事里多个项目,一个项目对应多份报名,多个报名可能被编排成多个场次,一场比赛对应一条或多条成绩。ER图在毕设文档里是必画的,表结构理不顺,那张图也画不清楚。

2.4 页面与交互的细节设计

页面数量不要求多,但核心链路要完整。前端页面规划如下:

  • 首页:赛事列表、公告栏、当前热门报名项目;
  • 赛事详情页:赛事信息、项目列表、报名入口、赛程入口;
  • 报名页:选择项目、填写必要信息、提交报名、查看自己的报名记录;
  • 赛程页:按赛事查看场地排期、按项目筛选赛程;
  • 成绩页:按项目展示最终排名;
  • 后台页面:赛事管理、项目设置、报名审核、赛程编排、成绩录入、用户管理。

交互上有几个细节会影响体验。表单提交前要做必填项校验,提交后要给明确反馈;删除赛事或项目这种不可逆操作,要有二次确认;分页组件要保证页码正确,不会出现点击下一页后数据位置错乱的情况。这些细节在文档里也可以写进“系统测试”部分,作为用例来体现思考的完整性。

3. 核心代码实现与踩坑记录

3.1 包结构设计与分层思想

一个容易阅读、也容易答辩的项目,包结构必须清晰。我习惯这样组织:

  • entity/:与数据库表对应的实体类;
  • dao/:操作数据库的DAO层,只负责SQL和结果映射;
  • service/:业务逻辑层,处理报名校验、成绩计算等规则;
  • servlet/:控制器层,负责接收请求、调用Service、决定跳转;
  • filter/:登录校验、编码设置等过滤器;
  • util/:工具类,比如MD5加密、分页封装、日期处理。

分层的好处是,答辩被问“为什么把业务逻辑写在Service层而不是Servlet里”时,你可以回答:Servlet的责任是HTTP处理,业务规则应该集中管理,这样切换前端页面或者接口形式时,业务代码不用改。这个回答是有分量的。

3.2 JDBC连接工具类与DAO模板

传统JDBC最容易出的问题是资源没有关闭。数据库连接、PreparedStatement、ResultSet都是资源,用完都要释放。我建议先写一个工具类来统一管理连接和关闭操作:

public class DBUtil { private static final String URL = "jdbc:mysql://localhost:3306/sports_db" + "?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai"; private static final String USERNAME = "root"; private static final String PASSWORD = "123456"; static { try { Class.forName("com.mysql.cj.jdbc.Driver"); } catch (ClassNotFoundException e) { e.printStackTrace(); } } public static Connection getConnection() throws SQLException { return DriverManager.getConnection(URL, USERNAME, PASSWORD); } public static void close(AutoCloseable... resources) { for (AutoCloseable res : resources) { if (res != null) { try { res.close(); } catch (Exception e) { e.printStackTrace(); } } } } }

如果你用的是MySQL 5.x,驱动类要写成com.mysql.jdbc.Driver;换成MySQL 8.x之后要写成com.mysql.cj.jdbc.Driver。这个区别经常让第一次做项目的人卡很久。

DAO层的写法也值得注意,查询操作用PreparedStatement而不是Statement。这既是防止SQL注入的基础要求,也是答辩时一个非常标准的加分点。如果有人问你“系统安全方面做了什么”,答“SQL全部使用预编译,用户输入不直接拼接SQL”比空谈安全理念扎实得多。

3.3 登录与权限过滤的实现

登录模块不要只做“删掉一端不校验”,密码必须加密存储。以前很多课程设计是明文存密码,毕设阶段完全可以做得规范一点,用MD5或者加盐哈希。虽然MD5本身不是最强的方案,但作为教学项目足够,并且你可以回答出“为什么不能存明文:数据库一旦泄露,所有账号密码直接暴露”。

登录完成后把用户对象放进Session:

User user = userService.login(username, md5Password); if (user != null) { request.getSession().setAttribute("loginUser", user); response.sendRedirect(request.getContextPath() + "/event/list"); } else { request.setAttribute("errorMsg", "用户名或密码错误"); request.getRequestDispatcher("/login.jsp").forward(request, response); }

权限拦截用Filter来做:

public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException { HttpServletRequest request = (HttpServletRequest) req; HttpServletResponse response = (HttpServletResponse) resp; HttpSession session = request.getSession(false); User user = session == null ? null : (User) session.getAttribute("loginUser"); String path = request.getServletPath(); if (user == null) { response.sendRedirect(request.getContextPath() + "/login.jsp"); return; } if (path.startsWith("/admin/") && !"admin".equals(user.getRole())) { response.sendError(403, "无权访问"); return; } chain.doFilter(req, resp); }

这里面要注意一个细节:如果当前请求是登录请求本身,过滤器不能拦截,否则就循环跳转了。一般通过path判断排除登录接口来避免。

3.4 赛程冲突检测的核心逻辑

赛程编排是整个项目里最有技术含量的点。同一场地、同一时间段只能有一场比赛,判断逻辑其实是一个区间重叠问题。已知一场新赛程的计划开始时间是newStart、结束时间是newEnd,只要数据库里已经存在这样一条赛程:它的开始时间早于新赛程的结束时间,并且它的结束时间晚于新赛程的开始时间,那就说明存在重叠。

对应的SQL可以写成:

String sql = "SELECT COUNT(*) FROM t_schedule " + "WHERE venue_id = ? AND status != -1 " + "AND start_time < ? AND end_time > ?";

参数分别是场地ID、新赛程结束时间、新赛程开始时间。这个逻辑的关键是“开始时间小于别人结束时间”和“结束时间大于别人开始时间”两个条件同时成立,只要有一方被包含在另一方的时间段内,都会触发冲突。

这里容易踩的坑是:直接用between判断会漏掉“跨区间”的情况。比如已有赛程是9点到11点,新赛程是10点到12点,用“新开始时间在已有区间内”能检测出来,但反过来已有赛程9点到10点,新赛程8点半到9点半,用“已有开始时间在新赛程区间内”才能检测到。所以最稳妥的还是区间重叠公式,而不是简单比较某一个端点。

3.5 成绩录入与排名计算

成绩排名不能简单地在SQL里写ORDER BY score_value LIMIT 1就结束。因为同一个项目有多条成绩,并且不同项目的计量单位排序规则不同。田径类项目时间越短成绩越好,跳远、铅球类项目数值越大成绩越好。

我会在Service层处理排名逻辑:

  1. 根据项目ID查出所有成绩记录;
  2. 根据项目的unit字段决定排序方向,time升序,distance和count降序;
  3. 遍历排序后的列表,给每条记录赋名次;
  4. 如果前后两条成绩相同,名次保持一致,数据库里记录同一个rank_no。

代码大概长这样:

List<Score> scoreList = scoreDao.findByProjectId(projectId); scoreList.sort(Comparator.comparing(Score::getScoreValue) .reversed()); // 如果用time单位则按升序,下面是通用处理 if ("time".equals(project.getUnit())) { Collections.reverse(scoreList); } int rank = 0; BigDecimal lastScore = null; for (int i = 0; i < scoreList.size(); i++) { Score s = scoreList.get(i); if (lastScore == null || s.getScoreValue().compareTo(lastScore) != 0) { rank = i + 1; lastScore = s.getScoreValue(); } s.setRankNo(rank); scoreDao.updateRank(s); }

这个逻辑用到了事务,因为多条更新要么都成功、要么都失败。建议在Service层统一开启事务,任何一条更新出错就回滚,避免出现排名字段一半新一半旧的情况。

3.6 分页与搜索的落地细节

后台列表页通常要支持分页。最简单也最可控的方案是手动计算:每页条数固定为10,查询当前页数据时用LIMIT offset, pageSize,同时查一个总数用来计算总页数。

int pageNo = request.getParameter("pageNo") == null ? 1 : Integer.parseInt(request.getParameter("pageNo")); int pageSize = 10; int offset = (pageNo - 1) * pageSize; List<Event> list = eventDao.findPage(offset, pageSize, keyword); int total = eventDao.count(keyword); int totalPage = (int) Math.ceil(total * 1.0 / pageSize);

搜索功能建议和分页一起做,关键词通过LIKE模糊匹配赛事名称和地点。搜索条件要带进翻页链接里,否则点击第二页时搜索条件就丢了,这是很多初学者容易忽略的点。

4. 本地部署与上线:环境配置和报错排查

4.1 开发环境的版本搭配

开发环境的版本搭配是第一步,也是很多人耗费时间最久的一步。下面这套组合最常见,问题也最少。

  • JDK:1.8,稳定且兼容绝大多数老项目;
  • Tomcat:8.5或9.0;
  • MySQL:5.7或8.0;
  • IDE:IDEA或Eclipse,IDEA对Maven和Tomcat配置更友好;
  • 数据库驱动:如果你用MySQL 8.0,选mysql-connector-java 8.0.x。

版本不是越新越好。在毕设场景里,JDK 8 + Tomcat 8.5 + MySQL 5.7是经过大量验证的组合。如果你一开始就上JDK 17、Tomcat 10,遇到很多兼容性问题反而会消耗宝贵时间。

4.2 从源码到可运行的War包

演示和最终交付时,推荐打成War包放到Tomcat里跑。步骤不复杂,但每步都要看清楚。

  1. 在IDEA中确定项目依赖都已配置好,数据库驱动Jar包要放进WEB-INF/lib目录,而不是仅仅在编译时引入。
  2. 点击Project Structure,找到Artifacts,选择Web Application: Archive,Name建议和项目名一致。
  3. Build Artifacts,生成War包。
  4. 把War包复制到Tomcat的webapps目录下。
  5. 启动Tomcat,访问http://localhost:8080/项目名/。

如果是把项目拿给别人演示,这个流程能保证对方只要装好JDK和Tomcat就能跑,不需要在IDE里重新配置一遍。

4.3 高频报错排查清单

我把自己实际踩过、也看到别人反复踩的坑整理成一张表:

错误现象常见原因处理方法
ClassNotFoundException: com.mysql.jdbc.Driver驱动包没放进WEB-INF/lib,或驱动路径写错引入mysql-connector-java并放到lib目录;MySQL 8用com.mysql.cj.jdbc.Driver
Access denied for user 'root'@'localhost'数据库用户名、密码配置错检查DBUtil里的连接配置
Communications link failureMySQL服务没启动,或端口不对启动MySQL服务,确认端口3306
页面中文全部变成问号编码不一致JSP设置UTF-8,数据库连接URL加characterEncoding=utf-8
The server time zone value '???ú???'MySQL 8时区问题URL加serverTimezone=Asia/Shanghai
启动后访问404部署名称或访问路径不对确认War包名和访问URL路径一致
8080端口被占用本机已有进程占用端口改Tomcat的server.xml端口,或用命令查出占用进程

这张表可以直接拿去配合文档里的“系统部署说明”写,也可以作为答辩前自查的清单。

4.4 部署到云服务器上的注意事项

如果需要把系统部署到云服务器,流程和本机基本一致,但有几个额外的坑。云服务器默认安全组可能不放行8080端口,记得登录控制台放行;MySQL如果装在服务器本机,连接地址写localhost,不要写内网IP;如果服务器上的MySQL版本和本地不一致,优先看驱动版本是否匹配。

另外,演示环境的数据要提前录制好,不能用空的数据库去演示。服务器时间也要校准成北京时间,否则赛程展示的日期看起来会差好几个小时。

5. 毕设配套:文档、演示视频和答辩准备

5.1 设计文档的章节怎么组织

毕业设计除了能跑的代码,还要交一份设计文档,也就是常说的LW。文档写得好的核心原则是:先有系统,再写文档。很多同学习惯先编框架,结果截图是P的、流程是抄的,一答辩就被问穿。正确路径是系统做完后,按实际页面和逻辑组织文档。

章节框架建议如下:

  1. 绪论:研究背景和意义、国内外现状、主要工作;
  2. 相关技术介绍:Java、JavaWeb、JSP、Servlet、MySQL、Tomcat;
  3. 需求分析:可行性分析、功能需求分析、非功能需求分析、用例图;
  4. 系统设计:系统架构设计、功能模块设计、数据库设计、ER图和表结构;
  5. 系统实现:每个核心模块的页面截图、关键代码段、逻辑说明;
  6. 系统测试:测试环境、测试用例、测试结果、兼容性说明;
  7. 总结与展望:项目总结,以及可以改进的方向。

文档里的每个图都不是白放的。用例图对应需求分析,ER图对应数据库设计,时序图对应核心业务流程。如果时间不够,最少要保证:用例图、ER图、系统架构图、核心模块流程图这四类图不缺。

5.2 演示视频录制的实操要点

演示视频不是录屏,而是一场有脚本的讲解。很多人录出来的视频是鼠标乱点,五分钟看完不知道在演示什么,这个问题完全可以通过脚本解决。

演示脚本要按业务流程来走,千万别按后台菜单一个个点。推荐顺序是:管理员登录 → 创建赛事 → 设置比赛项目 → 开始报名 → 用运动员账号登录报名 → 裁判账号录入成绩 → 成绩公布并查看排名。每演示一个功能,口播一句“这个操作的目的是什么”,比单纯说“我点了这个按钮”有价值得多。

录制之前先在测试库里准备好两组账号:一个管理员账号,一个运动员账号,再准备少量真实感强的测试数据,比如“男子100米”“女子400米”“篮球团体赛”。录屏时分辨率建议1280x720以上,时间控制在8到15分钟,太长反而暴露问题。

5.3 答辩时最容易被追问的问题

答辩环节老师很少让你逐行念代码,更多的是围绕设计决策和部署细节来提问。下面这几个问题几乎是必问的,建议提前准备好答案:

  • “为什么用JavaWeb而不是Spring Boot?”回答方向是课程要求与题目限制,同时强调自己理解了MVC分层。
  • “数据库为什么这么设计?外键为什么有些地方不用?”答:主外键关系保证数据完整性,但某些高表采用外键使用逻辑关联,是为了分页查询性能,这个思路既诚实又能体现设计感。
  • “赛程冲突怎么判断?”把区间重叠逻辑口述清楚。
  • “成绩并列名次怎么处理?”说明相同成绩返回相同名次的跳号规则。
  • “Session和Cookie区别是什么?”标准面试题,答清楚作用域、存放位置、状态保持机制即可。
  • “怎么防止SQL注入?”说明所有SQL都用了PreparedStatement,而不考虑用字符串拼接。

把这些问题提前写成模拟问答,在答辩前一天过一遍,效果比多背一遍代码要好得多。

6. 扩展方向与个人实操体会

6.1 低成本的高分加分项

做完基础功能之后,有余力的话可以加几个低成本但效果好的亮点。

  • 导出Excel:把报名名单或成绩排名导出成Excel,在后台加一个按钮,用Apache POI实现,代码量不大,但视觉冲击力很强。
  • 验证码登录:用Kaptcha生成图片验证码,不仅安全,还能在文档里专门写一节“登录安全设计”。
  • 简单图表统计:在赛事管理后台放一个柱状图展示各项目报名人数,用ECharts纯前端渲染即可。
  • 密码加盐:普通MD5换加盐哈希,并解释为什么更安全。
  • 实时刷新成绩页:每隔几秒用Ajax拉取一次最新成绩,不用WebSocket也能达到准实时体验。

这些亮点不需要全部做,挑一个做到完整、稳定、能演示,就比堆砌十个没做完的功能强。

6.2 做这个题目时的几点实在话

我把这个项目完整走完一遍之后,最大的体会是:做毕设最有价值的事情不是代码本身,而是把“需求到实现再到交付”的闭环走通。你定义的任何一个模块、设计的任何一张表、写下的任何一段注释,都是将来面试时可以拿出来谈的真实素材。

如果你还没开工,我建议先把最小闭环跑通:登录、建赛事、报名、录成绩、看排名。不要一开始就想着把所有功能全做完,先让链路通起来,再逐步加固。每开发一个功能,顺手把遇到的问题和解决方式记到文档里,这些问题在写设计文档和答辩时都是最真实的内容。最后再补一句:代码一定要手动敲,文档一定要根据自己系统截图,Git记得频繁提交。项目做扎实了,答辩时底气是完全不同的。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询