Spring Boot + 微信小程序校园应用毕设全攻略:从数据库到联调

发布时间:2026/9/19 1:30:14
Spring Boot + 微信小程序校园应用毕设全攻略:从数据库到联调
又是毕设选题的季节。每年这个时候总有一批同学在 Spring Boot 和微信小程序之间反复横跳纠结做什么题目才能既好过答辩、又能写进简历。如果你现在正卡在这个环节手上又恰好握着“springboot 校园场景应用小程序”这个题目那这篇文章就是写给你看的。先说这个题目的价值所在。校园场景应用小程序听起来是“小程序 Spring Boot”的组合但它的核心优势不只是技术栈好看而是业务场景足够贴近真实产品。校园里的失物招领、二手交易、活动报名、课程表查询、校园公告每一个功能点都是学生日常高频使用的场景需求清晰、演示效果直观还方便你编用户故事和测试用例。对于毕业设计来说这种“能演示、能解释、能扩展”的题目几乎是选型最优解。本文会从选题思路、数据库设计、后端搭建、小程序端联调一路讲到上线备案和常见报错排查内容偏实操适合准备动手写代码、又不想走弯路的人。1. 选题分析与整体设计思路1.1 为什么说这类选题是毕设的“安全牌”很多同学选题时有个误区喜欢追新一上来就想搞什么 AI 识别、分布式高并发。不能说这些方向不好但放在本科毕设的周期和答辩场景里风险其实挺大的。AI 模型训练不充分、高并发压测环境搭不起来、数据量根本支撑不了你的架构设计最后容易变成“演示五分钟被问两小时”。校园场景应用小程序恰好在难度和创新之间找到了平衡点。技术上覆盖了 Spring Boot 后端、小程序前端、数据库设计、接口联调、权限验证这些主流技能工作量和本科毕设要求匹配业务上又是你每天生活的场景功能怎么设计、需求怎么拆解你天然有体感不会出现“设想很好但做不出来”的问题。答辩的时候老师问“你这个失物招领的匹配逻辑是怎么想的”你能从用户角度讲清楚这种考场上的自信是实打实的。另外这个选题还有个隐形优势它天然是前后端分离结构这不只是在技术层面锻炼你也是直接瞄准了当前企业项目的主流开发模式。把这句话放在论文的“系统意义”章节里老师挑不出毛病。1.2 技术选型Spring Boot 和小程序为什么是黄金搭档后端我们选 Spring Boot前端选微信小程序这几乎是当下校园类项目最成熟的组合。展开聊聊各自的理由。Spring Boot 的优势不在“新”而在“稳”。它内嵌 Tomcat不用单独部署容器自动装配机制帮你省掉一大坨 XML 配置加上 Spring 生态里 MyBatis、Redis、文件上传这些常用组件都有成熟的集成方式。对毕设来说这意味着你可以把时间花在业务功能的实现上而不是配置环境。而且它占据了主流市场需求哪怕你以后想走 Java 开发方向这个项目的经历写在简历里也是加分的。微信小程序的上手逻辑和网页开发接近WXML 类似 HTMLWXSS 类似 CSSJS 逻辑层也用的是 JavaScript 语法前端基础薄一点也能很快跑起来。更重要的是小程序没有获客成本用户扫码即用天生适合校园这种线下熟人传播的圈子。对比一下原生安卓 App 的方案回头你还要面对安装包、版本兼容、各种手机厂商的权限问题每次演示还得掏出一台手机手动打开 App体验差太远了。所以我的建议很直接不要在这个组合上纠结它就是当前这类项目的最优解。你可以把精力省下来花在把功能性做得更完整、把细节打磨到位上。1.3 功能模块规划宁可少做也要做透这个题目最忌讳的就是功能清单拉得很长结果每个模块都是半成品。你想在校园场景里做公告、二手、失物招领、课表、活动、社团、跑腿……听起来很多但落到代码里每个都是一堆表、一堆接口、一堆页面最后论文写起来也是流水账。我当时做的时候选择把功能收敛到 5 个核心域做到每个都有独立的数据表和完整的操作链路。第一个是用户认证核心是微信登录通过wx.login拿到 code后端调用jscode2session换取 openid再生成自定义登录态 token 返回给前端。第二个是校园公告管理员发布、普通用户浏览支持阅读量统计和置顶操作。第三个是失物招领用户可以发布丢失或捡到物品的信息实现分类展示、按状态筛选、联系方式和取回确认流程。第四个是二手交易用户发布闲置商品支持图片上传、价格信息、留言咨询和下架操作毕业季的时候这个模块使用率直线上升。第五个是校园活动报名管理员创建活动设置报名截止时间用户可以查看活动列表、提交报名、后台取消报名。核心思路是做广度收敛、做深度延展。这五个模块支撑起了整个项目的主体结构答辩时你可以把每个模块的角色、流程、状态变化故事讲得很完整的而且每个模块都覆盖了增删改查、分页、图片处理、权限判断这些基础要求技术要点一个都不缺。2. 核心功能拆解与数据库设计2.1 用户角色和权限怎么设计校园应用和普通商业应用最大的不同在于用户角色相对固定。我的做法是设置三种角色普通用户、管理员、超级管理员。普通用户通过微信授权登录系统默认分配管理员可以管理公告、审核失物招领信息、创建活动超级管理员则拥有全部权限包括给用户分配管理员角色。权限控制不用搞得太复杂用拦截器加一个用户角色判断就可以了。项目里定义一个RequireRole注解加到对应 Controller 方法上通过拦截器统一校验当前登录用户的角色是否匹配。这样做的好处是代码侵入性小你只需要在需要管理权限的接口上标注一下就行。有些人会觉得 Spring Security 或者 Shiro 才显得专业但对于毕设项目重量级框架引入后可能带来额外的配置和学习成本反而分散了你的核心精力。在论文里你可以写“出于项目体量和开发效率考虑采用基于拦截器注解的轻量级权限控制方案”这句话既说明了设计思考也能体现你的工程判断力。2.2 核心表结构设计五张主要表一次看清数据库是整个项目的地基。表结构设计得好不好直接决定了你后面写代码时的心情。我把主要表拆为五张核心数据表外加一张用户表。用户表用来存储基本信息上面那五类功能的白名单都挂在它下面。为了让你少踩坑我直接整理出这些表的字段设计要点。用户表核心字段是openid、nickname、avatar、role外加create_time和update_time。openid是用户在微信生态里的唯一标识不作为主键主键用一个自增的id。角色字段用整数类型0 表示普通用户、1 表示管理员、2 表示超级管理员这样可以避免字符串比较带来的额外开销。公告表字段包括标题、正文内容、状态、是否置顶、阅读数、发布时间。一个容易忽略的点是发布人字段存储的是用户表的 id方便以后做“由谁发布”的关联查询。失物招领表这是业务状态最复杂的一张表。字段包括物品名称、物品描述长文本、图片 URL、拾取/丢失地点、联系人方式、物品类型0 丢失、1 拾到、状态0 待认领、1 已认领、2 已完成。这里有个关键点一定要加一个“发布人用户 id”并且要加“领取人用户 id”或“确认人用户 id”用来记录整个认领的闭环。状态流转可以用 0 到 1 再到 2这样小程序端按状态筛选数据时查询条件会非常干净。二手商品表字段包括标题、描述、价格用整数分为单位存储避免浮点数问题、图片 URL多个图的话用逗号分隔或者 JSON 数组、成色、联系人、所在校区、状态0 在售、1 已下架、2 已成交、发布人 id。对于“成色”这个字段我建议用数字字典0 全新、1 九成新、2 八成新这样前端渲染时映射成文字可扩展性和可维护性更强。活动表字段包括标题、内容、活动地点、开始时间、结束时间、报名截止时间、最大报名人数、当前报名人数、状态默认 0 未开始、1 进行中、2 已结束。状态建议不手工维护而是通过定时任务或者查询时动态计算。常见做法是写一个Scheduled定时任务每五分钟扫描一次自动更新活动状态字段这样表单上状态永远是准确的也方便活动列表的排序。活动报名表这是活动表的关联子表字段包括活动 id、用户 id、报名时间、是否取消软删除标记。加软删除是因为用户可能在活动前取消报名接着又能再次报名直接物理删除的话历史记录就找不回来了。用 0/1 标记既保留了数据又避免了唯一索引报错。这里要提醒一句数据库字段统一采用snake_case命名后端实体类用驼峰命名然后通过在配置里开启 MyBatis 的驼峰映射map-underscore-to-camel-case: true省去手写 ResultMap 映射的麻烦你一定不想在五张表的结果映射上浪费大把时间。同时create_time、update_time可以统一用数据库默认值填充减少代码里的赋值逻辑。2.3 为什么状态字段一定要加数字字典而不是直接写死字符串很多初次做项目的同学喜欢在数据库里直接存“待认领”“在售”这样文字状态表面看很直观实际上坑了不少人。文字状态的需求一多光是判断条件就能把你绕晕而且前端展示需要映射后端判断也需要映射本地存储的中文一旦有偏差整条链路的数据就乱了。所以我强烈建议状态字段统一使用整数类型用注释或单独的字典表说明含义。例如失物招领表的状态0 待认领、1 已认领、2 已完成。前端拿到数字后映射成对应的中文文案后端判断时也用数字。这样既节省存储空间又让查询语句可读性更强写 payload 时也更放心。提示在数据库设计说明里把每个状态位都写成枚举注释这样导师查看数据库时不用猜你自己过了三个月回来看也能秒懂。3. 实操过程从零搭建 Spring Boot 后端3.1 版本怎么选spring boot 版本太高怎么办这个坑我从身边同学那里听到过太多次了Spring Boot 最新版装上去依赖吭哧吭哧下载完毕然后启动直接报错一堆兼容性问题等着你去处理。网上搜出来的教程大多是旧版本的配置方式对不上新版本心态直接崩掉。我的建议是不要追求最新版本。Spring Boot 2.7.x 系列是我个人最推荐的毕设版本。它是 2.x 的最后一个维护版本稳定且社区资料丰富网上 90% 的教程、答疑都能直接用。同时它默认的配置方式对初学者更友好比如不强制要求使用 Spring Security 的 OAuth2 配置体系很多老教程在 Spring Boot 3.x 上就跑不通了。如果你已经装了太高版本可以在pom.xml里把版本号降下来然后重新导入依赖。改一行配置世界清静了。这里举个例子如果你的pom.xml里是parent groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-parent/artifactId version3.2.0/version relativePath/ /parent建议改成parent groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-parent/artifactId version2.7.18/version relativePath/ /parent改完之后右键 Maven 菜单重新加载项目。要是项目里引入了javax.*的包在 Spring Boot 3.x 中已经被替换成了jakarta.*这会导致代码大面积报错。换成 2.7.x 之后这个问题就不存在了因为 2.x 还是传统 JDK 8 加javax的分包方式兼容性最好。3.2 使用 IDEA 创建项目和初始化配置我用 IDEA 创建项目时选择 Spring Initializr 的方式SDK 选择 JDK 1.8 或 11。依赖方面引入下面的 starterdependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-web/artifactId /dependency dependency groupIdorg.mybatis.spring.boot/groupId artifactIdmybatis-spring-boot-starter/artifactId version2.3.1/version /dependency dependency groupIdmysql/groupId artifactIdmysql-connector-java/artifactId scoperuntime/scope /dependency dependency groupIdorg.projectlombok/groupId artifactIdlombok/artifactId optionaltrue/optional /dependency dependency groupIdcom.alibaba/groupId artifactIddruid-spring-boot-starter/artifactId version1.2.20/version /dependency文件上传用本地磁盘存储不引入 OSS一方面是为了省钱另一方面是自己维护文件路径也能更好地理解文件上传的流程。如果后面确实想扩展对象存储接口层封装得当的话替换需求也不大。核心配置文件application.yml长这样server: port: 8080 spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/campus_app?useUnicodetruecharacterEncodingutf-8serverTimezoneAsia/ShanghaiuseSSLfalse username: root password: 123456 type: com.alibaba.druid.pool.DruidDataSource servlet: multipart: max-file-size: 10MB max-request-size: 50MB mybatis: mapper-locations: classpath:mapper/*.xml configuration: map-underscore-to-camel-case: true file: upload-dir: /data/upload access-prefix: /files wx: appid: 你的小程序AppID secret: 你的小程序AppSecret有一点要提醒你serverTimezoneAsia/Shanghai一定要加。不加的话数据库连接在部分环境下会因为时区问题直接报错。多花一分钟避免半小时的排查时间。3.3 项目分包结构和统一返回格式一劳永逸的写法后端分包我见过很多种乱七八糟的写法有的把 Controller 和 Service 写在一个类里有的打了十几个包结果每层之间互相依赖。考虑到毕业设计后期要写论文我推荐清晰的标准四层分包。controller负责接收请求、参数校验、调用服务、返回结果。service业务逻辑层接口加实现类的方式方便写测试也方便扩展。mapper数据访问层注解式 SQL 或 XML 方式都可以。entity数据库表对应的实体类字段和表结构一一对应。common存放统一返回结果类、异常处理类、工具类、常量类。config配置类放拦截器、WebMvc 配置等。统一返回格式建议定义一个ResultT类内部包含code、message、data三个字段。成功的返回是Result.success(data)失败的返回是Result.error(msg)。再配一个全局异常处理器用RestControllerAdvice捕获业务异常前端就不用每次判断状态码了减轻接口联调压力。我在实际项目里是这么定义的Data public class ResultT { private Integer code; private String message; private T data; public static T ResultT success(T data) { ResultT result new Result(); result.setCode(200); result.setMessage(success); result.setData(data); return result; } public static T ResultT error(String message) { ResultT result new Result(); result.setCode(500); result.setMessage(message); return result; } }统一之后前端请求封装里只需要判断res.data.code是否等于 200不需要每写一个接口都重复一遍错误提示逻辑。3.4 微信登录和后端 token 验证链路校园类应用最重要的是识别用户是谁。微信小程序提供了wx.login接口会拿到一个临时凭证 code然后在后端使用这个 code 调用微信接口换取openid。我的实现逻辑大概是这样小程序端调用wx.login拿到 code。小程序端把 code 通过 POST 请求发送到后端的/api/user/login接口。后端使用HttpClient或OkHttp调用微信的jscode2session接口传入appid和secret换取openid和session_key。后端查数据库如果 openid 不存在则自动注册一个新用户存在则直接登录。后端生成一个 UUID 作为 token把 token 和用户信息绑定存到 Redis 或本地缓存里然后把 token 返回给小程序。这里有一个非常关键的工程细节所有人的登录凭证都必须走后端转发而不是在小程序端直接调用微信接口。因为小程序的appSecret一旦放在前端代码里被别人反编译获取就能冒充你的小程序调用所有接口。把凭证留在服务端是安全底线。缓存模块我用了 Redisspring-boot-starter-data-redis 简单配置存取 token 的代码如下Autowired private StringRedisTemplate redisTemplate; // 登录成功后 String token UUID.randomUUID().toString().replace(-, ); redisTemplate.opsForValue().set(token: token, openid, 7, TimeUnit.DAYS);后续请求中小程序端在请求头携带Authorization字段后端拦截器从 Redis 中取出 openid 放入ThreadLocal供 Controller 层直接获取当前用户信息。这种方案实现简单、逻辑清晰、性能也够用比传统的 session 更适合前后端分离场景。4. 小程序端开发要点与前后端联调4.1 页面结构和底部 TabBar 设计小程序端我采用原生开发没有引入 uni-app。原生小程序的学习成本更低调试也方便毕竟毕设答辩现场是拿微信开发者工具演示的不需要考虑跨端。整个项目结构大致分为 tabBar 页面和普通页面两种。tabBar 页面我选了首页、失物招领、二手集市、个人中心四个板块这四个是用户最常点的入口。每切换一个板块底部高亮图标和页面同步切换用户停留在功能入口的路径很短整体体验比较顺畅。个人中心页会展示用户的头像昵称、我的发布记录、我报名的活动、退出登录按钮。设置 tabBar 需要在app.json里配tabBar字段{ tabBar: { color: #999999, selectedColor: #1296db, list: [ { pagePath: pages/index/index, text: 首页 }, { pagePath: pages/lost/lost, text: 失物 }, { pagePath: pages/market/market, text: 二手 }, { pagePath: pages/mine/mine, text: 我的 } ] } }首页我用的是一个信息流布局把最新的公告、最新的失物招领、最新的二手商品聚合在这个页面上。最上方放一个轮播图组件下面的模块标题点击就能跳转到对应列表页。聚合页的好处是信息展示集中感官上数据量很大演示效果很好。4.2 请求封装把 wx.request 统一管理起来小程序端直接wx.request用起来很繁琐每写一个接口都要重复写 URL、header、success、fail代码很脏。我做了一层统一的request封装核心逻辑是自动拼接基础域名。自动从缓存中读取 token加到请求头里。统一处理 HTTP 网络错误和业务错误码。遇到 401 时自动跳转登录页重新登录。封装的代码大概是这样的const BASE_URL http://localhost:8080/api; function request(path, method GET, data {}) { return new Promise((resolve, reject) { wx.request({ url: BASE_URL path, method: method, data: data, header: { Content-Type: application/json, Authorization: wx.getStorageSync(token) || }, success(res) { if (res.data.code 200) { resolve(res.data.data); } else if (res.data.code 401) { wx.navigateTo({ url: /pages/login/login }); reject(res.data); } else { wx.showToast({ title: res.data.message, icon: none }); reject(res.data); } }, fail(err) { wx.showToast({ title: 网络异常, icon: none }); reject(err); } }); }); } module.exports { request };所有页面只需要import { request } from ../../utils/request然后调用request(/user/login, POST, { code })就能拿到数据。当后端返回数据或字段格式有问题时异常也会进到统一处理逻辑里比散落在每个页面里逐个调试强不少。4.3 动态设置小程序头部标题就是两行代码的事很多毕设项目一到“动态设置标题”就卡住其实微信官方早就做了支持。你可以在分享或者进入某个详情页时通过导航栏设置接口动态修改标题基本两行代码就能搞定wx.setNavigationBarTitle({ title: 失物招领 - 详情 });放在onLoad里调用。比如失物详情页根据 URL 上的 id 去请求后端拿到物品名称后把标题设置为“失物详情手机”用户可以直观看到当前页面在讲什么这个细节会让答辩老师觉得你考虑得很周全。4.4 本地开发联调三件套跨域、域名校验、局域网最常见的联调卡壳问题有三个我逐个拆开说说。第一个是跨域。Spring Boot 后端默认不允许跨域请求小程序不是浏览器其实不走常规的 CORS 同源策略但如果你用的是 web-view 内嵌页面就必须处理。我在后端写了一个全局的 CORS 配置类允许所有来源访问开发环境省心Configuration public class CorsConfig implements WebMvcConfigurer { Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping(/**) .allowedOriginPatterns(*) .allowedMethods(GET, POST, PUT, DELETE, OPTIONS) .allowedHeaders(*) .allowCredentials(true) .maxAge(3600); } }第二个是域名校验。用微信开发者工具本地调试时默认会在控制台报“域名不合法”。解决办法是在开发者工具右上角点击“详情”勾选“不校验合法域名、web-view业务域名、TLS 版本以及 HTTPS 证书”。这个选项勾上之后你就能在本地畅快地和 Spring Boot 联调了。第三个是局域网。你的电脑启动 Spring Boot 后小程序端如果填的是localhost那么手机真机预览时访问的是手机自己要改成你电脑的局域网 IP例如http://192.168.1.101:8080/api。而且手机和电脑要连接同一个 WiFi后端的server.address默认监听所有接口不用改。注意在真机预览时微信限制使用 HttpClient 访问 HTTP 明文请求目前只允许 HTTPS。所以如果你要真机演示本地开发阶段最好还是用开发者工具的模拟器调试等部署上线时再换成 HTTPS 的域名。4.5 文件上传功能的实现要点校园项目里图片上传的功能很常见。失物招领要传物品照片二手商品要传实物图活动详情也要配图。我这里的实现思路是后端写一个通用的/api/upload接口接收MultipartFile。存储到本地磁盘生成一个随机文件名防止重名覆盖。返回一个可访问的 URL 给前端。配置一个静态资源映射让上传的图片可以通过 HTTP 访问到。Spring Boot 里配置静态资源映射非常简单Configuration public class WebConfig implements WebMvcConfigurer { Value(${file.upload-dir}) private String uploadDir; Value(${file.access-prefix}) private String accessPrefix; Override public void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler(accessPrefix /**) .addResourceLocations(file: uploadDir /); } }上传接口的核心代码大致如下PostMapping(/api/upload) public ResultString upload(RequestParam(file) MultipartFile file) { if (file.isEmpty()) { return Result.error(文件不能为空); } String originalFilename file.getOriginalFilename(); String ext originalFilename.substring(originalFilename.lastIndexOf(.)); String fileName System.currentTimeMillis() - UUID.randomUUID().toString().substring(0, 8) ext; File dest new File(uploadDir, fileName); if (!dest.getParentFile().exists()) { dest.getParentFile().mkdirs(); } file.transferTo(dest); return Result.success(accessPrefix / fileName); }这样一个接口搞定所有模块的图片上传需求前端的wx.chooseMedia选图后用wx.uploadFile上传非常顺手。5. 常见问题与排查技巧实录5.1 登录用户不是该小程序的开发者这个报错在开发和体验阶段出现次数最多。很多人一看到这个提示就以为是后端代码有问题其实不是问题出在微信公众平台的成员管理里。你这个微信号没有被添加到小程序的“体验成员”或“开发者”列表里或者你登录的小程序 AppID 不对。解决办法去微信公众平台用管理员账号扫码登录在“成员管理”里把你自己的微信号添加到项目成员里角色设为“开发者”。添加完以后在微信开发者工具里重新登录不要只关掉报错弹窗就完事一定要退出当前账号重新登录一次。还有一个容易忽略的点如果你拿别人的 AppID 来开发那你必须是那个小程序的管理员或开发者才行。所以我建议毕设项目里直接申请一个自己的小程序账号个人主体就可以注册还没有费用等毕业了项目不维护了直接注销也不心疼。5.2 开发时域名不合法上线前必做的备案本地开发阶段可以勾选“不校验合法域名”但一旦到了真机预览或者上线发布阶段就必须把后端部署到一台有备案域名的服务器上而且域名协议必须是 HTTPS。这里的步骤并不多但耗时要留足。首先买一台云服务器装好 JDK 和 MySQL把 Spring Boot 项目打成 jar 包用nohup java -jar campus-app.jar 启动。接着买一个域名提交 ICP 备案。备案信息里有一个“备注”字段很多人不知道怎么填。初次备案的时候备注建议写“本网站/小程序用于校园场景应用的开发与测试主要提供校园公告、失物招领、二手交易等信息服务不涉及前置审批项目”简单明确一般都能顺利过审。备案通过之后如果你只是把小程序的 request 合法域名配成 HTTPS 域名还必须给域名配置 SSL 证书。证书在云平台申请免费的就行下载 Nginx 证书在 Nginx 里配置反向代理转发到后端的 8080 端口。前端小程序里请求的地址从http://localhost:8080/api改成https://你的域名/api然后在微信公众平台“开发管理 - 服务器域名”里把 request 合法域名、uploadFile 合法域名都配上。6. 数据库和接口联调时一些容易踩的深坑6.1 分页查询为什么越写越慢先检查你有没有用这种写法很多同学一开始写的分页逻辑是“查全表 内存截取”用户量一大就明显卡顿。正确做法是在 SQL 层就完成分页MyBatis 里可以用 PageHelper 插件它在底层拦截 SQL 自动拼接 LIMIT用起来非常省心。PageHelper.startPage(pageNum, pageSize); ListGoods goodsList goodsMapper.selectList(goodsQuery); PageInfoGoods pageInfo new PageInfo(goodsList);PageHelper 用的时候有一个坑startPage必须紧跟第一条查询语句如果中间有别的步骤或者第二次查询分页参数就会污染后续查询。注意不要在循环里调用startPage否则你永远只能拿到第一页的数据。6.2 前后端数据类型对不上JSON 解析报错怎么查联调阶段最常见的报错就是后端返回的日期格式比如2024-12-18T10:30:00和前端想展示的2024-12-18 10:30对不上。解决办法是在实体类的日期字段上加上JsonFormat注解JsonFormat(pattern yyyy-MM-dd HH:mm:ss, timezone GMT8) private LocalDateTime createTime;还有一个容易踩的坑是 Integer 和 Long 在前端 JS 中的精度问题。如果你的主键是雪花算法生成的 Long 类型到了 JS 里可能会因为超长整数而丢失精度最后所有 ID 都变成同一个。要么把主键类型改成字符串返回要么前端不要依赖主键做 id 判断这个问题在联调时很容易被忽略一旦遇到会很头疼。6.3 小程序端下拉刷新和上拉加载的配合列表页做到后面你得处理好触底加载更多和下拉刷新这两个交互。小程序原生的onPullDownRefresh和onReachBottom方法覆盖了这两个生命周期你只需要在app.json对应的页面配置里把enablePullDownRefresh: true打开即可。在实现加载更多的时候我通常用分页参数pageNum和pageSize每次触底把pageNum加一然后请求下一页数据追加到当前列表尾部。当下一次返回的数据长度小于pageSize时说明没有更多可加载了这时设置一个hasMore标记为 false不再触发请求。等下拉刷新时把pageNum重置为 1清空列表数据重新拉取。7. 一些真心话给正在做毕设的你这个项目做到最后它不只是一个“能跑的代码”项目从选题到数据库设计再到前后端联调完整地走完了一遍真实的业务开发流程。当你做完失物招领的认领闭环、二手商品的上下架、活动的报名退选你就会发现很多企业里所谓的“业务逻辑”其实就是这么一个个状态流转的小事。有一个小建议想特别提一下后期写论文的时候不要把代码粘贴一大堆重点写清楚你的设计思路和取舍原因。比如“为什么用 Redis 存 token”“为什么状态字段用数字”“为什么分页用 PageHelper”这些才是答辩老师真正感兴趣的点。如果你现在正在搭建这个项目按照上面的顺序一步步来先画数据库表再写后端接口然后接小程序页面。中间遇到报错不要慌几乎所有常见问题在上文的踩坑清单里都能找到答案。实在卡住了就重新检查三个东西依赖导没导对、配置路径对不对、参数名是否前后端一致。超过一半的所谓玄学报错最后都落在这三件事上。祝你的毕设顺利通过代码一跑就通答辩一讲就过。