ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

SpringBoot+微信小程序旅游攻略系统毕业设计全解析

2026/9/7 21:13:01 拓冰建站 浏览量
SpringBoot+微信小程序旅游攻略系统毕业设计全解析 开场白先说点实在的。每年到这个节点总有学弟学妹私信我问毕设到底做什么选题Java 方向是不是太卷了小程序和 Web 管理系统到底选哪个我的建议一直很明确——如果你所在学校对毕设的技术要求是“能跑、能演示、能讲清楚、有一定工作量”那 SpringBoot 微信小程序这套组合就是性价比极高的稳妥方案。这次要拆解的项目是“基于 SpringBoot 的旅游攻略系统小程序”。它不是一个花架子而是把后端接口、小程序端展示、管理后台、数据大屏四个环节串起来的完整闭环。简单说用户在小程序里浏览景点和攻略、收藏点赞、发布自己的游记管理员在后台维护景点内容、审核攻略、管理用户最后通过大屏把访问量、热门景点、活跃用户这些数据可视化展示出来。整个项目做完功能量充足、技术栈主流、演示效果也亮眼用来当毕设或者作为求职项目写进简历都站得住脚。这篇帖子我就把整个项目从选题思路、技术选型、数据库设计、核心接口实现到常见坑位和答辩亮点完整拆给你看。内容偏长但都是干货建议先收藏再慢慢啃。1. 项目整体设计与思路拆解1.1 为什么选 SpringBoot 小程序这套组合很多人觉得 SpringBoot 太“烂大街”毕设十个人里八个都是 SSM 或者 SpringBoot 管理系统。但你得换个角度想这个问题毕设的本质是什么是让你在有限时间内完成一个逻辑完整、可演示、可解释的系统并且向评委证明你掌握了相关技术。这是“确定性优先”的场景不是“前沿探索”的场景。SpringBoot 的优势在于生态极其成熟。你想要用户登录有现成的拦截器和 JWT 方案你要操作数据库有 MyBatis-Plus 这种几乎不用写 SQL 的 ORM你想做文件上传SpringBoot 对本地存储和云存储都支持得很好。网上资料多到什么程度呢哪怕你凌晨三点卡在某个报错上搜一下基本都能找到解决方案。这一点对毕设来说太重要了——你不会有太多时间耗在环境问题和冷门 Bug 上。小程序端的选择同样有讲究。微信小程序本身就有天然的分发优势评委老师每个人的微信里都能直接打开体验不需要安装 App演示成本极低。相比做一个纯 Web 系统小程序的前端界面更容易做出“移动端产品”的感觉视觉上更贴近真实商业项目。而且小程序开发工具自带模拟器和调试器调试体验比浏览器里调响应式页面要直观得多。一句话总结我的选型逻辑后端求稳前端求新中间用 API 衔接整个链路用大屏做视觉收尾。这套组合既不会让你在技术上翻车又有足够的展示亮点。1.2 功能模块的规划逻辑我见过不少学弟做毕设上来就闷头写代码结果写到中期发现功能散成一盘沙有的模块没意义有的模块又缺关键环节。做系统设计第一步永远是“画圈”——明确这个系统要解决什么问题哪些功能是核心闭环哪些是加分项。旅游攻略系统的核心闭环就三条线用户线微信登录 - 浏览景点/攻略 - 收藏/点赞 - 发布个人攻略。这条线覆盖了一个典型 C 端用户的完整行为路径。内容线管理员维护景点信息 - 用户围绕景点产出攻略内容 - 管理员审核和精选优质内容。这条线让系统有持续的内容供给和质量管理机制。数据线用户行为产生日志和数据 - 后端定时聚合统计数据 - 大屏可视化展示。这条线让“数据”成为项目的一个独立卖点。围绕这三条线具体功能可以拆成下面几块用户模块微信授权登录、个人资料管理、我的收藏、我的攻略列表。景点模块景点列表、景点详情、按地区/分类筛选、关键词搜索。攻略模块攻略列表、攻略详情、发布攻略支持图文混排、点赞和评论。管理后台景点管理、攻略审核、用户管理、数据统计概览。大屏展示实时访问趋势、热门景点 Top10、用户增长趋势、攻略发布量统计。做规划时我给自己的要求是每个模块都必须回答“为什么存在”这个问题。比如“点赞”功能它表面上是一个互动功能实际上是大屏统计“热门攻略”的核心数据来源。这样一来功能之间就有了逻辑勾连答辩的时候你也能讲出一套完整的业务故事。1.3 系统架构的整体设计这个项目的架构并不复杂但每一层都要职责清晰。我采用的是最经典的前后端分离结构小程序端负责页面展示和用户交互通过 HTTP 请求调用后端 RESTful API后端采用分层架构Controller - Service - Mapper通过 MyBatis-Plus 操作 MySQL 数据库Redis 负责缓存热门景点数据和 token 会话管理后台可以直接复用一套 Web 管理界面建议用 Vue 或者直接用 Thymeleaf 做一个简单的后台页面大屏前端通过 ECharts 从统计接口拉取数据渲染图表。这里有一个设计上的细节值得展开说。管理后台和大屏我建议分开做不要塞进同一个页面里。很多同学图省事把管理后台和大屏做成同一个路由下的两个 Tab结果到了演示的时候大屏页面加载了一堆管理表格的数据页面响应明显卡顿。分开之后管理后台面向管理员操作密集大屏面向访客和评委只读展示、刷新频率低两者互不干扰体验都更好。2. 技术栈选型深度解析2.1 SpringBoot 版本选择的血泪教训打开搜索引擎搜“SpringBoot 毕设”你会看到大量教程还在用 2.2.x、2.3.x 这种老版本。但很多同学在实际操作时直接去 start.spring.io 上生成最新版本结果就是 3.x。这里我强烈建议除非你非常清楚自己在做什么否则毕设项目请坚持用 SpringBoot 2.7.x。为什么SpringBoot 3.x 最核心的变化是强制要求 JDK 17并且底层从 javax.servlet 切换到了 jakarta.servlet。这意味着你在网上搜到的 90% 的 SSM 整合教程、拦截器示例、代码生成器配置都会因为包名不同而报错。你的精力应该花在业务实现上而不是折腾包名兼容。SpringBoot 2.7.x 配合 JDK 1.8是全网资料最丰富、踩坑成本最低的组合没有之一。具体版本我推荐这样搭配组件推荐版本说明JDK1.88u202稳定、生态兼容性最好SpringBoot2.7.182.x 最终版修复了大量已知问题MyBatis-Plus3.5.3.x代码生成、分页插件都很成熟MySQL5.7 或 8.0均可8.0 记得配驱动com.mysql.cj.jdbc.DriverRedis5.x / 6.x / 7.x单机版即可Maven3.6.3 或 3.8.x不要用最新版 4.x2.2 小程序端原生还是框架小程序端开发选型时你面前有两个主要选项微信原生小程序或者 uni-app 这类跨端框架。我的建议很直接做毕设用原生微信小程序就够了。uni-app 的优势是一套代码多端运行但这也意味着你要额外学习它的生命周期和语法规范。如果你只需要跑微信小程序一个端原生开发反而更直接——微信官方的文档和社区问答质量都很高大部分问题都能搜到。而且原生小程序的 WXML/WXSS 跟 HTML/CSS 有天然亲和力如果你学过前端基础上手成本很低。这个项目的页面结构我规划了这么几个。底部 TabBar 是四个主页面首页、景点、发现攻略广场、我的。首页放搜索框、轮播图、热门景点推荐景点页支持按地区和分类筛选发现页是攻略信息流我的页面展示用户头像、昵称以及我的收藏、我的发布记录。一个经验之谈页面不要贪多。我见过有人一口气设计十几个页面结果很多页面内容高度雷同反而让人觉得凑数。精做十个以内的核心页面每个页面的交互和视觉都打磨到位比堆二十个半成品页面更有说服力。2.3 大屏数据可视化的技术选择大屏可视化这个模块是很多人一听就头疼的部分——总觉得需要学很复杂的新技术。实际上如果你只是做毕业设计的大屏展示ECharts 就是最好的选择没有之一。ECharts 是百度开源的一套图表库后来捐给了 Apache 基金会。它对中文支持极好文档和示例都是中文的而且官方示例库Make A Pie里有大量可以直接套用的模板。你在上面找几个好看的图表改改数据接口就能用。更关键的是ECharts 基于 Canvas 渲染性能足够流畅图表类型覆盖了绝大部分可视化需求。大屏页面我建议做成一个独立的 HTML 页面通过iframe或者直接嵌入到后台项目中。布局上采用经典的栅格式面板布局顶部放标题和核心指标数字总访问量、用户数、攻略数中间主体区域放地图或者城市分布图和热门景点排行底部放趋势折线图和分类饼图。这个布局信息密度高又不杂乱是评委一眼就能看懂的经典大屏范式。3. 数据库设计与核心功能实现3.1 核心表结构设计原则数据库设计是毕设项目里最容易被低估的环节。很多人上来就建表建到一半发现字段不够用、关系理不清然后反复 alter table浪费时间不说代码里到处都是奇怪的兼容逻辑。我建议在设计表之前先回到业务逻辑把所有需要持久化存储的数据以最小粒度列出来再去做表设计。旅游攻略系统至少需要这几张核心表用户表useropenid微信唯一标识、nickname、avatar、gender、city、create_time、update_time。openid 是用户表里最重要的字段它就是你在微信生态里的用户身份证。注意同一个微信号在同一个小程序下的 openid 是唯一的不同小程序之间 openid 不同所以 openid 一定要建唯一索引。景点表scenic_spotname、cover_image、images多图可用 JSON 字符串或独立表、description、category、province、city、address、score、view_count、status。景点表是内容的基础攻略、收藏、大屏统计都会关联到它。攻略表strategyuser_id、scenic_spot_id、title、content富文本或 Markdown、cover_image、view_count、like_count、comment_count、status待审核/已发布/已驳回。这里注意一个细节像 like_count 这种统计字段我建议在攻略表里冗余存储一份计数。虽然严格的三范式要求把计数通过 count 查询动态算出但在真实项目里频繁的 count 查询在数据量上来之后会成为性能瓶颈。冗余一个字段配合点赞接口做原子更新性能更好代码也更简单。收藏表favoriteuser_id、scenic_spot_id、create_time。需要建联合唯一索引user_id, scenic_spot_id防止重复收藏。点赞表like_recorduser_id、strategy_id、create_time。同样建联合唯一索引并且给攻略表里的 like_count 做冗余更新。评论表commentuser_id、strategy_id、content、parent_id支持楼中楼、create_time。评论表做回复功能时用 parent_id 自关联是通用做法。管理员表adminusername、passwordBCrypt 加密存储、name、create_time。后台管理登录一定要用加密存储明文密码是答辩时会被追问的硬伤。3.2 微信登录的完整流程实现微信小程序登录是整个项目里最容易踩坑、也是面试官最喜欢问的一个环节。它的完整流程是小程序端调用wx.login()获取一个临时凭证 code把这个 code 通过后端接口传给自己的服务器后端拿到 code 后调用微信的code2Session接口换取 openid 和 session_key后端用 openid 去数据库查用户是否存在不存在就自动注册一个新用户登录成功后后端生成一个自定义 tokenJWT 或 UUID 均可返回给小程序小程序后续所有请求都带上这个 token 即可。后端核心代码大致长这样PostMapping(/login) public Result login(RequestBody LoginRequest request) { // 1. 用 code 换 openid String url https://api.weixin.qq.com/sns/jscode2session?appid appid secret secret js_code request.getCode() grant_typeauthorization_code; String result restTemplate.getForObject(url, String.class); JSONObject json JSONObject.parseObject(result); String openid json.getString(openid); // 2. 根据 openid 查用户不存在则注册 User user userMapper.selectOne( new LambdaQueryWrapperUser().eq(User::getOpenid, openid)); if (user null) { user new User(); user.setOpenid(openid); // 默认昵称、头像等 userMapper.insert(user); } // 3. 生成 token 并返回 String token JwtUtil.generateToken(user.getId()); return Result.success(token); }这里有一个非常关键的点新版微信2021 年后已经不推荐通过wx.getUserInfo直接获取用户的昵称头像了。现在的合规做法是在小程序端使用button组件的open-typechooseAvatar获取头像使用input组件的typenickname获取用户昵称用户主动填写后把头像昵称传到后端更新用户信息。这一步你要是用老代码审核小程序时会收到警告答辩时评委也可能追问。我在项目里采用的方案是登录时静默获取 openid生成 token 完成登录在“我的”页面提供编辑资料的入口让用户设置自己的头像和昵称。这样既保证首次登录流程足够顺畅又规避了平台合规风险。3.3 接口鉴权与拦截器设计小程序端的接口不是所有都公开的。景点列表和攻略列表这些浏览类接口游客也能看但发布攻略、点赞、收藏这些操作必须先确认用户身份。这里就要引入拦截器机制。我的实现思路是写一个AuthInterceptor继承 Spring 的HandlerInterceptor在preHandle方法里从请求头里取 token校验合法性并把用户信息放入ThreadLocal或请求属性中方便后续 Controller 使用。public class AuthInterceptor implements HandlerInterceptor { Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { // 放行预检请求 if (OPTIONS.equalsIgnoreCase(request.getMethod())) { return true; } String token request.getHeader(Authorization); if (StringUtils.hasText(token)) { try { Integer userId JwtUtil.parseToken(token); request.setAttribute(userId, userId); return true; } catch (Exception e) { // token 无效继续往下走由 Controller 层判断是否必须登录 } } request.setAttribute(userId, null); return true; } }注意我这里的设计是“拦截器不直接拒绝请求而是把 userId 塞进请求里”。原因很实际一个接口可能是半公开的比如攻略列表游客能看但看不到完整信息拦截器一刀切反而麻烦。Controller 层通过注解或手动判断来区分是否需要强制登录这样灵活度更高也更好扩展。实际开发中我会在需要登录的接口上加自定义注解RequireLogin然后用另一个拦截器去扫描这个注解做强制校验。这套逻辑你如果觉得复杂简化为拦截器对所有/api/user/**前缀的接口都强制校验其他接口放行也是完全可行的。3.4 攻略发布与图片上传攻略发布是用户侧最核心的一个功能。这里有两个技术点要注意富文本编辑和图片上传。小程序端的富文本编辑能力比较弱不像 Web 端可以用 wangEditor 这种现成库。我的做法是做了一个简化版的发布表单标题、封面图、正文文本 图片组合。用户从相册选图后先调用后端的/api/upload接口把图片传到服务器拿到 URL 后在正文里插入。这样实现起来思路清晰也避免了在小程序里嵌入复杂富文本编辑器带来的兼容性问题。后端文件上传接口用 SpringBoot 做非常方便PostMapping(/api/upload) public Result upload(RequestParam(file) MultipartFile file) { // 避免同名的处理 String originalFilename file.getOriginalFilename(); String ext originalFilename.substring(originalFilename.lastIndexOf(.)); String filename UUID.randomUUID().toString().replace(-, ) ext; // 存储路径按日期分目录 String datePath LocalDate.now().toString(); File dir new File(uploadDir / datePath); if (!dir.exists()) { dir.mkdirs(); } file.transferTo(new File(dir.getAbsolutePath() / filename)); // 返回访问 URL String url /upload/ datePath / filename; return Result.success(url); }上传后的文件路径我建议直接存相对路径然后通过一个 WebMvc 配置类做静态资源映射Override public void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler(/upload/**) .addResourceHandler(file: uploadDir /); }这样图片回显时直接用相对路径拼接即可部署到服务器后也不会有写死本地磁盘路径的尴尬。3.5 大屏数据统计接口的设计思路大屏要展示的数据最好不是实时去数据库里 count那样在大屏页面频繁刷新时会打爆数据库。我的方案是在 MySQL 里建一张统计汇总表用后端定时任务Spring 的 Scheduled每 10 分钟跑一次聚合统计把结果写入汇总表大屏接口只读汇总表。这张统计表可以包含这些维度日期、总访问量PV、总用户数、当日新增用户数、攻略总数、当日新增攻略数、地区分布JSON 字符串、热门景点排行JSON 字符串。定时任务的核心代码思路如下Scheduled(cron 0 */10 * * * *) public void aggregateData() { // 统计总用户数 Long userCount userMapper.selectCount(null); // 统计今日新增用户 LocalDate today LocalDate.now(); Long todayNewUser userMapper.selectCount( new LambdaQueryWrapperUser() .ge(User::getCreateTime, today.atStartOfDay())); // 统计热门景点 Top10 ListScenicSpot hotSpots scenicSpotMapper.selectList( new LambdaQueryWrapperScenicSpot() .orderByDesc(ScenicSpot::getViewCount) .last(limit 10)); // 组装并写入统计表 }这套方案的好处很直接大屏页面哪怕每 5 秒拉一次数据压力也只落在统计表上不会影响前端业务接口的响应性能。而且你答辩时可以理直气壮地说“我在设计时考虑了大数据量场景下的系统性能采用了预聚合策略。”这句话在评委那里是加分项。4. 管理后台与大屏可视化部分的落地4.1 管理后台功能拆解管理后台是体现“系统的完整性”的重要模块。很多同学只做用户端小程序管理后台就简单搞一个列表页面交差这其实是浪费了展示机会。管理后台做得好能向评委证明你具备完整的产品思维。后台我用的是 Vue Element UI或者更轻量的模板做前端页面通过接口与后端交互。最核心的功能模块如下景点管理新增、编辑、下架景点支持上传景点封面和详情多图支持按城市、分类筛选。攻略审核列出所有待审核的攻略管理员点开详情查看通过或驳回驳回时可以填写原因。审核操作要留痕也就是更新攻略表的status字段同时可往一张审核记录表里写一条数据。用户管理查看用户列表、用户详情包括该用户发布的攻略数、收藏数对恶意用户做禁用操作。禁用时在用户表里加一个status字段0 正常 1 禁用小程序端请求用户信息时检查 status被禁用用户无法登录。数据概览后台首页展示几个核心数字卡片用户数、景点数、攻略数、今日访问量配合一个小型图表展示近期趋势。这个页面相当于大屏的“简版”但信息更偏向运营管理视角。后台接口的权限控制很简单用一层管理员登录拦截器即可。管理员登录接口返回一个独立的 admin token后台所有请求头带上这个 token拦截器校验通过才能访问。注意管理员密码在前端传输时如果追求规范要做加密但毕设层面用 HTTPS BCrypt 存储已经足够这点可以在答辩时主动提出来作为你考虑过安全性的证明。4.2 大屏页面的数据联动大屏前端是一个独立的 HTML 页面我用的是 ECharts 5。布局如下顶部区域是标题和四个 KPI 数字累计用户数、累计访问量、攻略总数、景点总数。这些数字用data属性指向后端统计接口的对应字段。中间主体区域左侧放“热门景点 Top10”横向条形图。横向条形图适合展示排名性质的数据景点名称在左侧纵轴上访问量或浏览量在横轴上高低对比一目了然。右侧放“用户省份/城市分布”柱状图或地图数据来自用户表的city字段聚合统计。底部区域放两个趋势图左边是近 7 日新增用户折线图右边是近 7 日访问量趋势折线图。数据从统计汇总表里按日期查询。大屏页面的数据刷新我推荐用setInterval每 10 秒调用一次统计接口然后通过myChart.setOption()更新图表。这里有一个细节当数据量较大时不要每次都setOption整个配置项只更新series里的data字段即可这样图表的过渡动画会更流畅。如果你想让大屏更有“科技感”可以在 ECharts 的 option 里配置一些视觉小技巧背景色用深色渐变、坐标轴文字用浅色、加上辅助色的 hover 高亮、数据变化时用animationDurationUpdate控制过渡时长。这些细节不用做得太花哨适度就好但一定要保证图表的可读性。4.3 后端统计接口的缓存策略统计接口虽然读的是汇总表但如果大屏每 10 秒请求一次还是建议在接口层加一层缓存。最简单的实现是在统计接口上加 Redis 缓存。GetMapping(/api/statistics/overview) public Result getOverview() { String cacheKey statistics:overview; Object cacheData redisTemplate.opsForValue().get(cacheKey); if (cacheData ! null) { return Result.success(cacheData); } // 查询统计汇总表组装数据 StatisticsData data statisticsMapper.selectLatest(); redisTemplate.opsForValue().set(cacheKey, JSON.toJSONString(data), 30, TimeUnit.SECONDS); return Result.success(data); }这里缓存过期时间设 30 秒比大屏的刷新频率10 秒长但又不至于让数据长期不更新。合理的缓存策略能让整个系统在高频请求下保持稳定这也是你在答辩时可以重点讲的一个“系统设计亮点”。5. 常见问题排查与避坑指南实操篇这一部分我系统整理自己实际开发中遇到的典型问题也是热搜词里出现频率最高的几个坑每一条都是真金白银换来的经验。5.1 SpringBoot 版本太高导致的诡异问题你照着网上教程做教程用 2.x你本地新建项目却选了 3.x 版本结果引入 MyBatis-Plus 后报ClassNotFoundException: javax.servlet.Filter。这是因为 SpringBoot 3.x 把javax.*全换成了jakarta.*。网上绝大多数老教程、老代码片段都基于 javax你复制过来全是报错。排查思路很简单先确认你的 SpringBoot 版本。在 IDE 里看pom.xml的 parent 节点版本号如果以 3 开头赶紧换成 2.7.x。然后统一 JDK 版本SpringBoot 2.7 配 JDK 8 或 11 均可建议 JDK 8资源占用小兼容性最好。改完之后 Maven Clean Reimport一般能解决 80% 的诡异报错。提示如果你用 IDEA 的 Spring Initializr 创建项目默认勾选的 SpringBoot 版本是当前最新的稳定版。创建时手动把版本切换到 2.7.18一次到位少走弯路。5.2 小程序获取登录后的微信用户失败热搜词里有一条典型的报错小程序获取登录后的微信用户失败: wx1cb4398e1413dce7。这个报错的出现原因多数情况下是后端jscode2session接口返回了错误码或者 appid/secret 配置不对。还有一种情况是你在微信开发者工具里测试时用的不是自己的 appid而是测试号但后端配置的是一个正式 appid两边对不上code 自然换不到 openid。处理流程如下第一步查看后端日志。微信接口返回的错误信息里会有 errcode 和 errmsg比如40013表示 appid 无效40125表示 secret 无效40029表示 code 无效或过期。第二步检查小程序后台的 appid 是否和后端配置一致。第三步确认用户是否在微信开发者工具里选择了正确的测试账号并且“不校验合法域名”的开关是否打开开发阶段需要打开。如果是在手机上真机测试还要确认小程序后台的 request 合法域名里是否配置了后端接口的域名。没配的话小程序端请求会被拦截报url not in domain list。5.3 内存溢出java: OutOfMemoryError: Insufficient Memory这个报错在本地开发时一般不会无缘无故出现多发生在以下几种情况IDEA 启动配置里内存参数设得太小、Maven 编译时内存不足、上传图片时一次性加载了大文件到内存没有做处理、或者开启了循环递归查询导致栈溢出。排查步骤如果是 IDEA 编译报错在 Settings 里调大 Build Process Heap Size比如设为 700M 或更高。如果是项目运行报错在 VM options 里加-Xmx512m或-Xmx1g试试。如果是一次性加载列表数据导致的内存暴涨检查是否在代码里用list()把所有数据查出来了分页能解决大部分类似问题。如果是文件上传场景检查是否把MultipartFile直接转成了字节数组存内存改用文件流式写入可以大幅降低内存压力。5.4 小程序无法打开公众号文章需要配置什么这是一个常见的小程序 Web-view 组件问题。小程序里要打开公众号文章需要在微信公众平台的“开发设置 - 业务域名”中添加公众号文章的域名并且这个小程序必须是非个人主体——个人主体小程序不支持业务域名配置。业务域名配置要求 HTTPS且需下载校验文件放到该域名的根目录。如果你用的是第三方平台账号测试也做不了这个配置那只能把公众号文章内容抓取下来做成自己的详情页。5.5 数据库连接失败的常见原因MySQL 版本 8.0 的驱动类名是com.mysql.cj.jdbc.Driver5.x 是com.mysql.jdbc.Driver。如果你用的 MySQL 8.0但配置里写的 5.x 驱动启动时会报驱动类找不到。另一个常见问题是时区连接串里需要加serverTimezoneAsia/Shanghai否则可能会报The server time zone value ???ú±ê׼ʱ¼ä is unrecognized。推荐配置spring.datasource.urljdbc:mysql://localhost:3306/travel?useUnicodetruecharacterEncodingutf8useSSLfalseserverTimezoneAsia/Shanghai spring.datasource.usernameroot spring.datasource.password你的密码 spring.datasource.driver-class-namecom.mysql.cj.jdbc.Driver5.6 MyBatis-Plus 分页查询失效的坑MyBatis-Plus 的分页插件需要显式配置PaginationInnerInterceptor很多新手忘了这一步结果Page返回的数据里total是 0 或者查出来全表数据。正确配置如下Configuration public class MybatisPlusConfig { Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor new MybatisPlusInterceptor(); interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); return interceptor; } }顺便说一句如果用了分页插件后多表联查的自动分页在某些场景下不对建议在复杂 SQL 场景下手动写Page参数的 Mapper 方法不要过度依赖插件的自动分页。5.7 经典 Java 面试八股文与毕设项目的联动最后一条虽然严格说不是 Bug但热度极高——“java 面试八股文”年年都是热议话题。很多同学做完毕设去面试被问到底层细节时一问三不知。我这里给你一个建议清单这个项目做完之后以下知识点你必须能用自己的话说出来——SpringBoot 自动配置原理SpringBootApplication 复合注解、EnableAutoConfiguration 的加载机制。MyBatis-Plus 和 MyBatis 的区别分页插件实现原理。Spring AOP 在项目里用了哪里比如日志切面、事务管理。Redis 缓存更新策略Cache Aside Pattern 的优缺点。JWT 的结构Header.Payload.Signature和鉴权原理。小程序登录流程中 code2Session 的完整链路。ECharts 的渲染原理Canvas vs SVG为什么选 Canvas。MySQL 索引失效的常见场景你在项目里如何避免比如联合索引最左前缀原则、like 查询、函数包裹字段。把这些问题想明白项目做完了面试也顺手了。这条经验比我上面写的任何代码都值钱。6. 项目亮点挖掘与答辩加分项6.1 主动给项目“上价值”答辩时间通常只有 5~10 分钟你得在有限时间里把工作的亮点讲出来不能只罗列功能。建议按“业务闭环 技术亮点 优化思考”三段式来讲。业务闭环这个系统不是一个人人可用的简单展示站而是覆盖了内容生产、内容管理、内容消费、数据反馈的完整闭环。用户发布攻略管理员审核其他用户浏览互动数据汇总到大屏。每一环都有数据流转和状态变化。技术亮点要具体。比如你用了 Redis 缓存热点数据降低了数据库压力你设计了定时任务做数据预聚合避免了统计查询拖垮业务库你用了 JWT 做无状态鉴权支持横向扩展。每一个亮点都配上具体代码和性能数据说话。优化思考部分不用长篇大论但一定要展示你有“工程师思维”。比如现阶段图片存储用的是服务器本地磁盘如果数据量大了会考虑接入对象存储 OSS 并做 CDN 加速接口目前没有做限流后续会引入 Sentinel 防止刷量日志目前是本地文件后续可以接入 ELK 做统一日志管理。你不需要真的实现这些但说出来能证明你是真的思考过、调研过。6.2 演示环节的节奏控制演示是整个答辩的高潮部分我有几个经验分享给你。先演示小程序端时间控制在 3 分钟内打开首页展示轮播图、景点列表点进一个景点详情然后是攻略列表和攻略详情接着进行“登录——收藏——点赞——发布攻略”这条关键链路。发布攻略这个动作建议提前准备几张图片素材现场操作时节奏会流畅很多。再演示管理后台登录后台展示景点管理列表和新增/编辑操作最好是提前准备好数据现场直接编辑。然后进入攻略审核页面特意展示一条“待审核”状态的攻略执行“通过”操作一个小程序端如果停留在这个页面可以现场刷新看到状态变化——这一步的联动演示效果非常好强烈推荐。最后演示大屏切换到浏览器的大屏页面展示 KPI 数据、热门景点排行、趋势图。可以刷新页面制造一点“实时更新”的感官冲击。大屏的视觉冲击力和前两个模块形成鲜明对比是全场观感的高潮。注意整个过程要提前演练至少两遍注意网络环境。如果现场没有网络后端可以连本地数据库小程序则可以打开开发者工具的“不校验合法域名”选项保证接口能通。这一步极其关键别问我怎么知道的。6.3 一份合格的项目 README 怎么写最后送你一个实用建议项目完成后写一份高质量的 README 文档放在 GitHub 上。这不只是给评委看的也是给未来面试官看的。一个合格的 README 应包含项目简介、功能模块截图、技术栈清单、部署步骤、项目目录结构、未来优化方向。部署步骤要写得足够详细让完全不了解这个项目的人按步骤操作就能跑起来。你可以这样写本地安装 JDK 1.8、Maven、MySQL 5.7/8.0、Redis。创建数据库travel导入项目根目录下的sql/travel.sql脚本。修改application.yml中的数据库账号密码、Redis 地址。修改application.yml中的微信小程序 appid 和 secret测试环境可用测试号。Maven 打包mvn clean package -DskipTests。启动项目java -jar target/travel-server.jar。小程序端导入miniprogram目录在app.js里修改后端接口地址为http://localhost:8080开发者工具需打开不校验合法域名。管理后台导入admin-web目录执行npm install npm run dev。大屏页面直接访问http://localhost:8080/screen/index.html。写清楚部署文档的过程也是你重新梳理项目结构的过程很多之前没想明白的模块边界写着写着就会通。就算答辩不查这份文档对你自己也绝对有收获。说实话做毕设这件事选题选对了项目就成功了一半。SpringBoot 小程序 大屏可视化的组合技术上主流工作量饱满演示效果好对找工作也有实际价值。按照上面的思路一步步来你不仅能做出一份拿得出手的毕设还能在过程中把 Java 后端的核心链路真正吃透。遇到具体问题欢迎在评论区留言我看到了会尽量回复。祝顺利。