每年的毕业设计季总能看到一批同学被“选题”折磨得焦头烂额。游戏分享网站这种项目听起来难度适中、事务清晰特别适合拿来当计算机专业的毕设项目但实际动起手来从技术栈选型到功能模块拆解再到部署演示每一环都有讲究。我自己从带项目到实际调试跟着一个基于Spring Boot MyBatis Plus的完整游戏分享网站项目走完了全流程今天把整套设计和实现过程中的关键点、踩坑经验和部署细节全部摊开来讲希望能让正在做类似项目的同学省下几个通宵。先说清楚这个项目能干什么用户注册登录之后可以浏览游戏、按分类筛选、搜索游戏、查看游戏详情、下载游戏或跳转到游戏主页同时还能对游戏进行评论和点赞登录用户自己也可以发布游戏分享上传封面图和游戏文件管理自己发布的游戏内容后台管理端则负责用户管理、游戏审核/下架、分类管理这些维护性操作。简单说它就是一个小型的游戏内容分享社区前端页面用Bootstrap Thymeleaf做服务端渲染后端用Spring Boot提供完整API数据层使用MyBatis Plus完成增删改查和分页查询。这套技术方案对于毕设而言既不至于太简单让人觉得没工作量也不会难到让一个人写不完。1. 项目整体设计思路与功能拆解1.1 面向的用户角色和核心功能游戏分享网站这类项目最大的好处是“需求一看就懂”但要注意的是需求简单不等于可以随便做。真正决定毕设质量的是功能模块的完整度和细节设计。我把整个系统的用户分成三类对应三种使用权用户角色核心操作权限典型页面游客浏览游戏、查看分类、阅读评论首页、游戏列表、游戏详情注册用户游客全部权限 上传游戏、评论、点赞、个人中心管理个人主页、游戏发布页、评论编辑管理员用户全部权限 后台管理入口后台管理面板、审核列表、统计页功能拆解时最简单的做法是“沿一条数据流走一遍”。用户进入网站看到首页的游戏推荐列表点进某个游戏详情页看到封面、简介、下载信息如果感兴趣就点赞、评论如果自己有好东西想分享那就走发布游戏的流程填写信息、上传封面、提交管理员在后台看到新提交的游戏审核通过后前台可见。这一条链路走通整个项目的核心逻辑就全部闭环了。1.2 技术栈选型背后的真实理由Spring Boot这个框架在毕业设计里的出现频率有多高不需要我多说。但真正要回答的问题是为什么这个项目适合用Spring Boot而不是其他方案第一是快速集成。Spring Boot内置了Tomcat容器不需要单独部署一个外置Tomcat本地开发时直接跑main方法就能启动这对毕设答辩时现场演示尤其重要——队友不会配置环境的意外太常见了少一个环节就少一个變數。第二是生态适配。这个项目需要做服务端渲染、需要连MySQL、需要做文件上传、需要做接口校验这些在Spring Boot生态下都有非常成熟的起步依赖Starter引入即用不用像传统的SSH架构那样写一堆XML配置。第三是MyBatis Plus带来的效率提升。如果用手写MyBatis XML增删改查至少80%的代码是重复的而MyBatis Plus可以直接通过BaseMapper接口继承获得通用的单表CRUD方法配合它内置的分页插件列表页的分页查询几行代码就能搞定。这不是偷懒而是把力气花在真正需要业务逻辑的地方。另外前端我倾向于用Thymeleaf做服务端渲染而不是前后端分离。原因很实际毕设项目的重点在后端业务逻辑如果选择前后端分离方案还要额外搭一套Vue或React工程涉及跨域、token鉴权、接口联调工作量直接翻倍对于一个人完成的毕设来说风险太大。服务端渲染的方式后端返回一个完整的HTML页面理解起来直观答辩时讲起来也顺畅逻辑链路是连贯的。1.3 项目目录结构与模块规划项目包的划分建议直接按业务模块走不要为了炫技引入复杂的DDD分层。我常用的结构是这样的src/main/java/com/gameshare ├── controller // 接收请求返回页面或JSON ├── service // 业务逻辑接口实现类 ├── mapper // MyBatis Plus的Mapper层 ├── entity // 数据库实体类 ├── dto // 前端交互的DTO对象 ├── vo // 视图对象组合多个表的数据 ├── config // 配置类拦截器、资源映射、分页插件 ├── common // 通用返回结果、异常处理、常量 └── GameshareApplication.java代码里有一个细节值得注意实体类尽量只对应数据库字段接口返回给页面的数据如果需要多个表拼合就单独建VO类。很多新手图省事在实体类里塞一堆数据库里不存在的字段结果MyBatis Plus在自动生成SQL时出现“字段找不到”的报错。分开命名的好处是出了问题一眼能看出是哪一层的事。2. 数据库建模与MyBatis Plus落地实践2.1 表结构设计五张核心表就够了数据库是这类项目的基石表设计不好后面写代码全是泪。我的建议是不要一开始就设计出十几张表从核心需求反推先保证几张主表合理再逐渐扩展。这个项目最核心的表是用户表、游戏表、分类表、评论表、点赞记录表。下面是我实际用过的建表语句字段和注释都写清楚了-- 用户表 CREATE TABLE t_user ( id bigint(20) NOT NULL AUTO_INCREMENT, username varchar(50) NOT NULL COMMENT 登录名, password varchar(100) NOT NULL COMMENT 加密后的密码, nickname varchar(50) DEFAULT NULL COMMENT 昵称, avatar varchar(255) DEFAULT NULL COMMENT 头像地址, email varchar(100) DEFAULT NULL COMMENT 邮箱, role tinyint(1) DEFAULT 0 COMMENT 0普通用户 1管理员, status tinyint(1) DEFAULT 1 COMMENT 1正常 0禁用, create_time datetime DEFAULT NULL, PRIMARY KEY (id), UNIQUE KEY uk_username (username) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4; -- 游戏分类表 CREATE TABLE t_category ( id bigint(20) NOT NULL AUTO_INCREMENT, name varchar(50) NOT NULL COMMENT 分类名称, sort int(4) DEFAULT 0 COMMENT 排序权重, PRIMARY KEY (id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;游戏表是核心中的核心字段关系到后续列表展示和详情页的效果CREATE TABLE t_game ( id bigint(20) NOT NULL AUTO_INCREMENT, user_id bigint(20) NOT NULL COMMENT 发布者ID, category_id bigint(20) NOT NULL COMMENT 所属分类, game_name varchar(100) NOT NULL COMMENT 游戏名称, cover_image varchar(255) DEFAULT NULL COMMENT 封面图地址, game_file varchar(255) DEFAULT NULL COMMENT 游戏文件地址, intro text COMMENT 简介, download_count int(10) DEFAULT 0 COMMENT 下载次数, like_count int(10) DEFAULT 0 COMMENT 点赞总数, status tinyint(1) DEFAULT 0 COMMENT 0待审核 1已发布 2已下架, create_time datetime DEFAULT NULL, update_time datetime DEFAULT NULL, PRIMARY KEY (id), KEY idx_category (category_id), KEY idx_user (user_id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;设计表的时候有一个坑要提醒千万不要用text类型存大段base64图片。有些同学为了省去上传图片的步骤把封面图片直接转成base64塞进数据库最后的结果是页面查询加载极慢数据库文件体积暴涨答辩演示时直接卡死。正确做法是图片上传到本地磁盘指定目录数据库里只存一个相对路径。评论表和点赞记录表相对简单但注意点赞表需要加唯一约束防止同一个用户对同一个游戏重复点赞CREATE TABLE t_comment ( id bigint(20) NOT NULL AUTO_INCREMENT, game_id bigint(20) NOT NULL, user_id bigint(20) NOT NULL, content varchar(500) NOT NULL, create_time datetime DEFAULT NULL, PRIMARY KEY (id), KEY idx_game (game_id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4; CREATE TABLE t_like_record ( id bigint(20) NOT NULL AUTO_INCREMENT, game_id bigint(20) NOT NULL, user_id bigint(20) NOT NULL, create_time datetime DEFAULT NULL, PRIMARY KEY (id), UNIQUE KEY uk_game_user (game_id, user_id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;2.2 从实体类到建表SQL的落地思路这次项目里遇到一个有趣的问题搜索热度很高“MyBatis Plus根据Java实体类生成创建表的SQL语句”。先说结论MyBatis Plus本身不负责建表它的核心是ORM但确实有办法基于实体类自动生成建表SQL前提是实体类上的注解足够规范。我们的实体类一般这样写Data TableName(t_game) public class Game { TableId(type IdType.AUTO) private Long id; TableField(user_id) private Long userId; TableField(category_id) private Long categoryId; TableField(game_name) private String gameName; TableField(cover_image) private String coverImage; TableField(game_file) private String gameFile; private String intro; TableField(download_count) private Integer downloadCount; TableField(like_count) private Integer likeCount; private Integer status; TableField(create_time) private LocalDateTime createTime; TableField(update_time) private LocalDateTime updateTime; }注意TableName、TableId、TableField这几个注解它们是连接实体类和数据库表的桥梁。如果想用工具按照实体类生成SQL可以使用IDEA的数据库插件配合MyBatisX插件检查实体类字段与数据库字段的对应关系并自动生成缺失表的建表语句如果是自己写SQL也可以把这些注解当作文档手工维护一个schema.sql文件。毕业设计最稳妥的做法是建表SQL单独维护成文件实体类注解与表字段保持一字不差。别盲目相信自动生成万一字段类型对应不上后面查问题的时候非常痛苦。2.3 多表关联查询的几种实现方式列表页需要展示游戏名、分类名、发布者昵称这就涉及三张表的关联。MyBatis Plus的BaseMapper只支持单表便利操作多表关联一般有几种处理方式方式一编写自定义SQL配合Select注解写在Mapper接口上Select(SELECT g.*, c.name AS category_name, u.nickname AS publisher_name FROM t_game g LEFT JOIN t_category c ON g.category_id c.id LEFT JOIN t_user u ON g.user_id u.id WHERE g.status 1 ORDER BY g.create_time DESC) ListGameVO selectPublishedGames(PageGameVO page);方式二在Service层先查游戏主表再根据categoryIds批量查分类表然后在内存中组装VO。这种方式避免了复杂的SQL适合数据量小的场景代码写起来比较清晰。方式三使用MyBatis Plus提供的自定义XML目录在resources/mapper目录下写XML文件。这种最传统适合需要动态SQL的复杂场景。我实际项目里用的是方式一结合Page对象的分页参数MyBatis Plus的分页插件会自动处理limit语句。这里强烈建议条件允许的情况下用Page作为方法的入参返回IPage这样分页查询的total、pages这些参数不用自己手动数直接就能渲染到页面的分页组件里。public IPageGameVO getPublishedGames(long page, long size) { PageGameVO pageParam new Page(page, size); return gameMapper.selectPublishedGames(pageParam); }3. 核心功能模块的实现与实用细节3.1 登录注册与权限控制的落地方式登录鉴权我记得当年做毕设的时候最容易被卡住的环节。我现在做这个项目用的是Session方案配合Spring MVC的拦截器实现未登录跳转Component public class LoginInterceptor implements HandlerInterceptor { Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { // 放行登录页、注册页和静态资源 if (request.getRequestURI().contains(/login) || request.getRequestURI().contains(/register) || request.getRequestURI().contains(/css) || request.getRequestURI().contains(/js) || request.getRequestURI().contains(/images)) { return true; } // 判断Session中是否有登录用户 HttpSession session request.getSession(); User user (User) session.getAttribute(loginUser); if (user null) { response.sendRedirect(/login); return false; } return true; } }密码加密这块强烈建议使用BCryptPasswordEncoder而不是MD5。MD5虽然流行但彩虹表攻击太容易破解了毕设答辩老师一眼就能看出来这是“低水平实现”。BCrypt的用法也很简单public String encodePassword(String rawPassword) { return new BCryptPasswordEncoder().encode(rawPassword); } public boolean matchPassword(String rawPassword, String encodedPassword) { return new BCryptPasswordEncoder().matches(rawPassword, encodedPassword); }3.2 游戏分享发布与文件上传处理方案发布游戏是整个项目最“重”的操作涉及到两个类型的上传封面图片和游戏文件。这里真的不要一上来就买OSS服务把本地文件存储方案跑通就够了。在application.yml里配置上传路径file: upload-dir: D:/gameshare-uploads/创建一个配置类把上传目录映射成可访问的URL路径Configuration public class ResourceConfig implements WebMvcConfigurer { Value(${file.upload-dir}) private String uploadDir; Override public void addResourceHandlers(ResourceHandlerRegistry registry) { // 上传文件映射 registry.addResourceHandler(/upload/**) .addResourceLocations(file: uploadDir); } }这样上传的图片路径存“/upload/xxx.jpg”页面直接用同样的路径就能访问到。上传文件的后端代码要注意的是Spring Boot默认上传单个文件大小限制为1MB实际游戏文件动不动就几十上百MB必须修改配置spring: servlet: multipart: max-file-size: 200MB max-request-size: 200MB同时接收MultipartFile时需要做类型校验防止用户上传可执行脚本或危险文件。检查文件名后缀只允许zip、rar、7z、jpg、png、jpeg、gif这些常见格式。3.3 评论与点赞模块的设计细节点赞模块是很多同学容易做得“不优雅”的地方。最简单的方案是每次点赞都update t_game表的like_count字段加1但这样会出现“点赞后点掉按钮状态不同步”的问题。正确的做法是先维护点赞记录表再同步更新游戏主表的like_count字段。后端投票的逻辑是判断点赞记录是否存在如果不存在就插入记录并且游戏表的like_count加1如果存在就删除记录并且like_count减1。这两个操作务必加上事务否则极端场景下会出现记录和计数对不上的问题。Transactional public boolean toggleLike(Long gameId, Long userId) { LambdaQueryWrapperLikeRecord wrapper new LambdaQueryWrapper(); wrapper.eq(LikeRecord::getGameId, gameId) .eq(LikeRecord::getUserId, userId); LikeRecord record likeRecordMapper.selectOne(wrapper); if (record null) { LikeRecord newRecord new LikeRecord(); newRecord.setGameId(gameId); newRecord.setUserId(userId); likeRecordMapper.insert(newRecord); // 加计数 gameMapper.increaseLikeCount(gameId); return true; } else { likeRecordMapper.delete(wrapper); gameMapper.decreaseLikeCount(gameId); return false; } }评论模块相对简单用MyBatis Plus做分页查询按时间倒序即可。注意评论内容的展示要做一下HTML转义防止XSS直接用Thymeleaf的th:text默认就是转义的别用th:utext。3.4 Thymeleaf页面渲染与后端数据交互的实战这个项目的前端页面不需要写得多高级但一定要“能看”。Bootstrap在这方面的优势是开箱即用栅格系统一搭卡片列表就出来了。首页的代码逻辑大致是控制器返回一个ModelAndView携带IPage对象和分类列表GetMapping(/) public String index(RequestParam(defaultValue 1) long page, RequestParam(defaultValue 9) long size, Model model) { IPageGameVO gamePage gameService.getPublishedGames(page, size); model.addAttribute(gamePage, gamePage); model.addAttribute(categories, categoryService.listAll()); return index; }页面中遍历游戏列表并渲染卡片用Thymeleaf标签即可。分页组件用Thymeleaf拼接页码链接注意保持当前查询条件不然翻页之后筛选条件丢失这也是一个容易忽视的细节。nav ul classpagination li th:if${gamePage.current 1} a th:href{/?page ${gamePage.current - 1}}上一页/a /li li th:eachi : ${#numbers.sequence(1, gamePage.pages)} th:class${i gamePage.current} ? active a th:href{/?page ${i}} th:text${i}/a /li li th:if${gamePage.current gamePage.pages} a th:href{/?page ${gamePage.current 1}}下一页/a /li /ul /nav这里有一个关于图集或列表展示的细节如果游戏封面图比较多务必要确保图片加载不会拖垮页面。最简单的方式是在上传时压缩一下封面图或者在HTML上给img标签指定宽高避免页面布局跳动。4. 环境配置、版本选择与部署演示指南4.1 版本匹配一个被折磨半年的话题打开招聘网站Spring Boot的职位要求基本都写着3.x但这不意味着做毕设也一定要用最新版。“springboot版本太高”这个词条的搜索量不低说明很多同学都掉进过这个坑。我的实际建议是做毕设用Spring Boot 2.7.x搭配Java 8而不是用Spring Boot 3.x搭配Java 17。原因很现实Spring Boot 3.x底层是基于Jakarta EE的包名从javax改成了jakarta很多网上流传的老代码和教程直接抄过来无法运行再加上JDK版本的差异如果你本地不是JDK 17又是各种报错。而Spring Boot 2.7.x是2.x的最后一个版本也是最稳定的一代直接使用javax命名空间网上的资源数量最多出问题搜得到答案。Maven项目里的关键依赖配置如下parent groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-parent/artifactId version2.7.18/version relativePath/ /parent dependencies dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-web/artifactId /dependency dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-thymeleaf/artifactId /dependency dependency groupIdmysql/groupId artifactIdmysql-connector-java/artifactId version8.0.33/version scoperuntime/scope /dependency dependency groupIdcom.baomidou/groupId artifactIdmybatis-plus-boot-starter/artifactId version3.5.3.1/version /dependency dependency groupIdorg.projectlombok/groupId artifactIdlombok/artifactId optionaltrue/optional /dependency /dependenciesMyBatis Plus在3.5.3.1这个版本下和Spring Boot 2.7.x的兼容性已经被大量项目验证过可以放心用。补充说明一下数据源配置同时包含Druid连接池的具体设置spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/game_share?useUnicodetruecharacterEncodingutf8mb4serverTimezoneAsia/ShanghaiuseSSLfalse username: root password: yourpassword druid: initial-size: 5 min-idle: 5 max-active: 20注意这里用MySQL 8.x时数据库驱动类名必须是com.mysql.cj.jdbc.Driver并且url里要加serverTimezone参数否则连接会报时区相关的错误。4.2 项目打包的完整操作流程开发阶段跑main方法没问题但毕设演示最好是打成jar包运行这样更能体现“可部署性”。打包步骤其实非常简单但我见过不少同学卡在“怎么把项目变成可交付的文件”这一步。打开项目根目录的终端执行Maven打包命令mvn clean package -DskipTests如果命令执行成功target目录下会生成一个gameshare-0.0.1-SNAPSHOT.jar文件。这个jar包就是整个后端应用的成品内置了Tomcat直接运行java -jar gameshare-0.0.1-SNAPSHOT.jar运行过程中要保证MySQL服务是启动的并且application.yml里配置的数据库名、用户名、密码与实际一致。这里我再强调一次绝对不要把数据库密码写死在代码里后打进jar再发给别人至少要留一个外部配置的方式演示的时候也方便改成本地的密码。如果发现打包出来的jar包resource文件缺少比如templates下的页面没带全那要注意pom.xml的resource配置是否正常。大多数时候默认配置就够了但如果自己改过build节点务必要把src/main/resources加回去。4.3 演示环境跑通的注意事项答辩演示是最容易翻车的环节。我总结了一套“演示前检查清单”照着做能避免90%的现场问题首先浏览器和数据库要提前打开并且数据库预热一遍主要页面查询别到答辩时上来第一件事是等待页面加载其次本地的端口要固定好8080端口如果被占用了提前改掉不然Windows下经常出现端口冲突最后录一段功能演示视频作为后备方案。如果现场的电脑突然蓝屏、数据库连不上一份提前录好的视频能救急。本地文件上传的路径也要提前创建好目录Windows和Linux的路径写法有差异如果之前代码里写的是“D:\upload”到学校实验室电脑上跑不起来演示时出现了“上传后图片不显示”的尴尬场面那真的就是前功尽弃。5. 部署过程中遇到的坑与排查技巧5.1 启动阶段常见的三类报错先说说启动时的报错排查。这是我带这个项目过程中最常见的三个问题端口被占用的报错信息是一大串“Port 8080 was already in use”解决办法要么换端口要么先查是谁占用了8080。Windows下用netstat -ano | findstr 8080查出PID再在任务管理器结束对应进程。数据库连接失败往往在启动后访问页面时才暴露特征是页面白屏加500错误日志里有“Communications link failure”字样。这基本都是MySQL服务没启动或者url里的host端口写错了。包冲突问题表现为奇怪的NoSuchMethodError异常这类问题大多出在依赖版本上。比如lombok和某个插件版本不匹配用了过高的spring-boot-maven-plugin版本等。排查方式是执行mvn dependency:tree分析依赖树找到冲突的jar包。5.2 数据访问层的高频问题数据访问层的问题具有一个共同点所有报错都能在MyBatis Plus的日志和SQL执行日志里找到线索。建议在application.yml里把mapper的日志级别打开logging: level: com.gameshare.mapper: debug控制台就会输出每个Mapper方法实际执行的SQL语句哪个字段拼错了哪个参数没传进去一目了然。特别提醒一个分页的坑MyBatis Plus的分页插件必须在config里面显式注册否则分页方法执行后返回的数据是全量而不是当前页。很多新手忘了加这个配置Configuration public class MybatisPlusConfig { Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor new MybatisPlusInterceptor(); PaginationInnerInterceptor paginationInnerInterceptor new PaginationInnerInterceptor(DbType.MYSQL); paginationInnerInterceptor.setMaxLimit(100L); interceptor.addInnerInterceptor(paginationInnerInterceptor); return interceptor; } }5.3 部署上线运行阶段的高频坑把jar包部署到云服务器时如果按默认配置直接启动大概率会遇到两类问题一是上传目录不存在导致上传失败二是防火墙没开端口导致浏览器访问不了。Linux服务器上先创建目录并给权限mkdir -p /data/gameshare/uploads chmod -R 755 /data/gameshare/uploads然后确认端口放行。云服务器有两层防火墙云厂商控制台的安全组规则和服务器内部防火墙。很多人配了云厂商安全组却忘了服务器内部的firewalld结果端口依然不通。服务器上使用nohup后台运行应用nohup java -jar gameshare-0.0.1-SNAPSHOT.jar --spring.datasource.password实际密码 app.log 21 这里用命令行参数方式覆盖数据库密码避免在jar包里留下敏感信息。查看运行日志使用cat app.log或者tail -f app.log排查启动问题全靠它。5.4 常见问题速查表最后把整个过程中频繁遇到的问题整理成一张表方便按图索骥表现可能原因解决办法启动时端口占用本地其他程序占用8080换端口或结束占用进程访问页面报Whitelabel Error控制器返回视图名与页面文件不匹配检查templates目录下页面文件名连接数据库超时MySQL未启动或账号密码错误启动MySQL服务核对配置中文乱码数据库字符集不统一统一utf8mb4url加characterEncoding上传图片后页面无法访问静态资源映射未配置确保ResourceConfig生效连续点赞计数不准未加唯一约束或未用事务补唯一索引方法加Transactional分页返回全部数据分页插件未注入注册MybatisPlusInterceptor页面样式丢失静态资源被拦截或路径错误检查拦截器放行/css /js路径6. 项目扩展与进一步完善的几个方向如果你的时间有富余想让项目在评阅时有更多加分项我建议从以下几个方向做扩展每个方向对代码的侵入都不大但体现在答辩PPT和论文里会显得你确实做了深度思考。第一是搜索功能的强化。目前只有普通的模糊查询基于游戏名做like查询。可以进一步支持分类筛选组合条件搜索甚至引入全文索引。但这个功能不要写得太复杂满足“能搜、搜得快、结果准”就行了。第二是数据统计模块。在后台加一个简单的统计面板用ECharts展示每日新增用户、每日发表游戏数等指标需要额外维护一张操作日志表或者用定时任务统计。第三是用户积分或等级体系。用户发布游戏获得积分评论获得积分积分达到一定值升级。这个功能可以充分展示你对业务规则的分析能力也是论文里比较好写的一章。第四是部署方式的升级。如果项目文件不大可以考虑用Docker Compose做一键部署把MySQL和应用容器化。但注意Docker方案要提前在答辩机器上验证否则临时装Docker容易翻车。我不推荐你为了追求“功能多”而把项目做成四不像每个功能都要考虑“好不好演示”和“能不能讲清楚”。毕设的核心评价标准是完整性和逻辑自洽而不是堆砌的技术名词。我个人在实际开发中的体会是这个游戏分享网站的难度分布是“易学难精”起步阶段的技术选型和页面搭建都很顺手真正需要花时间的是业务模块之间的数据关联、权限控制的边界处理、以及部署演示环境的一致性问题。把这些环节全部跑通之后你对Spring Boot的理解会是质变级别的。最后再分享一个小技巧——在你的论文和项目里把所有核心流程串成一条“从注册登录到发布内容再到后台审核”的完整故事答辩讲解的时候按这条主线讲比零散介绍每个模块的效果好得多。