Java毕设宠物社交小程序:从萌宠档案到服务闭环的架构实践
这个项目标题里其实藏了三个产品名萌崽、爪友、毛孩子。很多同学看到这种名字第一反应是直接开一个 SpringBoot 工程把增删改查糊上去最后论文里写一句“本系统实现了宠物社交功能”。如果只是应付交差这样确实能混过去但这个 Java 毕设程序真正的价值就在这三个名字的关系里。拆不明白后面所有表结构、接口、页面全是散的拆明白了一个小程序项目也能做到像真实创业项目一样逻辑闭环。先说结论萌崽是“内容入口”解决用户为什么来的问题爪友是“服务闭环”解决用户来了之后能干什么的问题毛孩子是“社区心智”解决用户为什么留下的问题。三个名字对应三种功能层正好嵌套成一套宠物社交加服务平台加内容社区的完整方案。下面我按这个思路把从需求、技术架构、数据库设计、核心功能实现到部署调试的完整经验过一遍做毕设或者自己做项目练手都可以直接照着搭。1. 项目定位与需求拆解三个名字背后的产品逻辑1.1 “萌崽”宠物社交小程序的切入点宠物社交最怕的一件事是用户来了之后没东西可看、没东西可发。萌崽这个模块解决的就是“内容从哪来”。很多毕设上来就做“用户主页、发动态、评论、点赞”做完却发现整个应用像一个空壳子根本不像宠物社区。原因很简单用户没有绑定宠物发什么内容都缺灵魂。我建议把“宠物档案”作为整个小程序的第一优先级功能。用户在注册之后第一步不是完善个人资料而是给宠物建档案宠物昵称、品种、生日、性别、是否绝育、疫苗情况、头像、个性签名。听起来很常规但这一步是整个社交链路的起点。宠物有了档案动态才能挂靠到宠物名下用户才能通过“附近宠友”“同品种圈子”找到同类内容才有聚合维度。说白了萌崽解决的是“我为什么发内容”因为我要晒我的猫、记录它的成长。有了这个出发点之后做关注、点赞、评论、转发才有意义。所以第一阶段的功能清单可以很聚焦宠物档案管理、动态发布、动态信息流、评论点赞关注、宠友搜索。这些做完一个“宠物朋友圈”的骨架就起来了。1.2 “爪友”宠物互动与服务平台的服务闭环光有内容没有服务用户看完就走这是纯内容产品的通病。爪友这个名字放在中间就是要把“线上互动”升级成“线下服务”让用户在这个小程序里真的能约到一次遛狗、一次寄养、一次上门洗护、甚至一次宠物医疗陪诊。我见过不少毕设把“服务预约”做成了简单的“发个表单提交一下”这其实是不够的。服务闭环至少要有四块服务项目展示、时间选择与预约、订单状态流转、评价反馈。服务方可以是普通用户比如隔壁养狗的朋友帮你遛狗也可以是线下宠物店入驻。考虑到毕设复杂度我不建议做商家后台审核那一套完整流程只需要一个角色字段普通用户、服务者。服务者可以发布服务项目普通用户可以在服务大厅看到附近的遛狗、寄养、洗护等服务并预约。这里要特别考虑一个问题线下服务是有地域属性的。用户不能预约一个一千公里外的遛狗服务所以爪友模块必须绑定 LBS按距离展示服务。这正好也呼应了“宠物互动”里的“附近宠友”“同城约伴”功能。线上看动态、线下约服务两条线通过地理位置串起来整个项目的产品逻辑立刻通顺了。1.3 “毛孩子”内容社区的运营心智第三个名字“毛孩子”很容易被忽略不少同学把它当成一个普通话题标签随便加个“热门话题”页面就完事。实际上毛孩子才是让用户沉淀下来的社区层强调的不只是“晒宠物”而是“爱宠生活分享”。也就是说内容不能只有萌图还要有养宠经验、品种科普、寻宠求助、宠物好物种草、同城宠物活动召集。这一层做起来并不复杂因为不需要再发明新功能而是把已有内容按“话题”和“社区频道”重新组织。比如动态发布时可以选择话题标签#猫咪日常、#养宠求助、#宠物好物、#寻宠启事。然后在社区首页按话题聚合让用户能刷到一个“求助区”、一个“种草区”。就是这一点“标签化”的动作就能把零零散散的宠物动态变成有社区结构的内容池。三个名字连起来就是一篇很好的毕设开题叙事以宠物档案和动态内容吸引用户留住用户萌崽以位置服务和预约能力完成商业闭环爪友以话题聚合和社区运营提升粘性毛孩子。答辩的时候把这个逻辑讲清楚比堆功能清单有用得多。2. 技术选型与架构设计Java 后端为什么要这样搭2.1 后端技术栈与选型理由后端我推荐 Spring Boot 2.7 MyBatis-Plus MySQL 8.0 Redis WebSocket这套组合是当前 Java 毕设里最稳的方案。SSH、SSM 那套不是不能写但 Spring Boot 的自动配置和生态明显更适合短周期开发答辩时也更好解释Spring Boot 解决了传统 SSM 配置繁琐的问题让开发者把精力放在业务实现上。MyBatis-Plus 最大的价值不是帮你少写几行 XML而是它自带的 LambdaQueryWrapper 和分页插件能省掉大量重复的 CRUD 代码。你在做宠物动态列表、服务预约查询这种多条件筛选场景时用 QueryWrapper 直接链式拼条件写起来比手写 SQL 快得多也不容易出字符串拼接的坑。Redis 在这个项目里不是摆设至少有三个真实用途存放登录 token 并控制过期时间、缓存点赞计数和动态热度、实现服务预约的分布式锁防止并发重复预约。只要用到了其中两个答辩的时候被问到缓存一致性、缓存穿透之类的问题你就有的聊了。这里也提一句架构层面的事小程序前端只通过 HTTP/HTTPS 调用后端接口后端不直接暴露数据库。前端发请求到后端后端校验 token、处理业务、查 MySQL、读写 Redis图片文件另外走阿里云 OSS 或腾讯云 COS。整个链路很清晰画成部署图也容易讲。2.2 小程序前端与 Java 后端的接口设计小程序端有两种选择微信原生开发和 uni-app。如果你只打算发布到微信小程序那就用原生开发工具链最稳定调试也方便如果想着以后可能是 H5、支付宝小程序都要再考虑 uni-app。毕设层面原生开发已经够用而且中文资料最多遇到问题搜起来不费劲。前后端接口要提前定一套统一规范。我习惯定义一个统一的响应体 Result结构为 code、message、data 三个字段code 为 0 表示成功其他值表示业务异常。小程序端封装一个 request 方法所有请求都走它自动处理 token 注入、401 跳登录、错误提示。这个统一响应体看起来简单但项目功能一多你就知道它有多香——不需要每个接口各写各的返回格式前端也不需要在每个页面单独处理错误。token 怎么传建议放在请求头里名字可以叫 Authorization。小程序端在本地缓存 wx.setStorageSync(token, token)每次请求前 getStorageSync 取出来放到 header 里。后端用拦截器统一校验发现 token 过期就返回 401前端收到 401 后清缓存并跳转到登录页。这一套逻辑做好大部分接口的会话问题就都能兜住。2.3 开发环境与服务器部署开发阶段最省事的方法是在微信开发者工具里勾选“不校验合法域名”这样本地局域网访问 Java 后端时不会被拦。但要演示给别人看或者你自己用手机真机预览就必须把后端部署到云服务器上并在小程序后台配置合法域名HTTPS证书要有效否则真机一测全是请求失败。Java 后端部署我建议用最简单的方式服务器装 JDK 17 和 MySQL、Redis、Nginx后端打成 jar 包用 nohup 启动Nginx 做反向代理把域名 80/443 流量转到 jar 的端口。不需要搞 Docker Compose 编排那是加分项不是必选项。小程序开发者工具上传代码之后体验版二维码一发别人就能直接看效果这是演示环节最顺畅的一条路。我踩过一个很典型的坑本地使用微信开发者工具一切正常换到真机就白屏报错。一查是小程序后台没有配置 request 合法域名。所以别嫌麻烦提前把服务器域名搞定、证书配好真机调试这关必须过。3. 数据库设计把核心表结构一次想清楚3.1 用户与宠物平台的“双主体”建模宠物社交平台和普通社区最大的区别在于它的数据模型是双主体的用户一套宠物一套用户和宠物之间是一对多关系。很多同学做宠物社区时只建了用户表宠物信息直接塞在用户表里几个字段这个设计到后面做“宠物动态时间线”“按品种搜索”“同一只宠物的成长记录”时会把自己给限制死。宠物档案表可以这样设计CREATE TABLE pet_profile ( id BIGINT AUTO_INCREMENT PRIMARY KEY, user_id BIGINT NOT NULL COMMENT 所属用户ID, pet_name VARCHAR(32) NOT NULL COMMENT 宠物昵称, breed VARCHAR(64) COMMENT 品种, category TINYINT COMMENT 1猫 2狗 3其他, birthday DATE COMMENT 出生日期, gender TINYINT COMMENT 1公 2母 0未知, avatar_url VARCHAR(255) COMMENT 宠物头像, sterilized TINYINT DEFAULT 0 COMMENT 是否绝育, vaccine_status TINYINT DEFAULT 0 COMMENT 疫苗状态, signature VARCHAR(200) COMMENT 个性签名, create_time DATETIME DEFAULT CURRENT_TIMESTAMP, update_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP );注意几点user_id 建普通索引因为你几乎所有宠物维度查询都要先根据用户找到宠物品种 breed 建议存标准品种名而不是存 id这样搜索和展示都直观绝育和疫苗状态用 TINYINT 而不是 VARCHAR既省空间又方便做筛选条件。这套表写出来答辩时讲“一个用户可以养多只宠物每只宠物独立建档”就是现成的亮点。3.2 动态社区与互动关系关注、点赞、评论别乱建表动态表是整个信息流的基石。最简单的模型是CREATE TABLE pet_post ( id BIGINT AUTO_INCREMENT PRIMARY KEY, user_id BIGINT NOT NULL, pet_id BIGINT NULL COMMENT 关联宠物, content TEXT, images TEXT COMMENT 图片URL多个用逗号分隔, topic_id BIGINT NULL COMMENT 话题ID, location VARCHAR(100) COMMENT 发布位置, longitude DECIMAL(10,6), latitude DECIMAL(10,6), like_count INT DEFAULT 0, comment_count INT DEFAULT 0, create_time DATETIME DEFAULT CURRENT_TIMESTAMP );这里 images 我用 TEXT 存逗号分隔的 URL而不是单独建一张图片表。为什么因为宠物动态的图片数量和动态数量都不算大拆表反而让查询变复杂除非图片特别多再考虑分表。评论表和点赞表要单独建。评论区就是 post_id、user_id、content、reply_user_id一个标准的一对多。点赞表要注意不能重复点赞最好加唯一索引CREATE TABLE post_like ( id BIGINT AUTO_INCREMENT PRIMARY KEY, post_id BIGINT NOT NULL, user_id BIGINT NOT NULL, create_time DATETIME DEFAULT CURRENT_TIMESTAMP, UNIQUE KEY uk_post_user (post_id, user_id) );有了这个唯一索引重复点赞、取消点赞再点赞都不会产生脏数据前端也不用担心用户手滑点了两下。关注关系表和点赞表结构类似也是 follow_user_id followed_user_id 加唯一索引但查询时注意方向别把“我关注了谁”和“谁关注了我”搞反这个低级错误在答辩演示时出过不少次。3.3 服务预约、订单与消息通知预约服务这块我建议把“服务项目”和“预约订单”分成两张表。服务项目表保存服务者发布的遛狗、寄养、洗护等服务的名称、价格、服务时间、服务范围、封面图、描述预约订单表保存用户下的每一单核心字段是 service_id、user_id、provider_id、service_date、service_time_slot、status、remark、create_time。订单状态可以考虑 status 用 TINYINT0 待支付、1 待接单、2 已接单、3 服务中、4 已完成、5 已取消。这个状态机不需要做复杂工作流引擎只用 switch 判断当前状态允许哪些迁移就行。比如“已取消”的订单不能再改成“已完成”后端接口里做一层校验就够。消息通知表也很容易被忽略。用户预约成功、服务者接单、用户评价后服务者收到提醒这些都需要有一个通知中心。最简单的设计是 notice 表receiver_id、type、content、related_id、is_read、create_time。动态点赞评论可以写入通知服务状态变更也可以写入通知一个通用表搞定所有场景前端小程序做一个小红点就可以了。4. 核心功能模块实现从登录到内容闭环4.1 微信登录与用户体系接入微信小程序登录的流程有固定套路前端 wx.login 拿 code后端拿 code 调微信接口换取 openid 和 session_key然后以 openid 判断用户是否存在存在则刷新登录态不存在则创建用户并返回 token。核心代码大概长这样PostMapping(/login) public ResultLoginVO login(RequestBody LoginDTO dto) { // 1. code 换 openid String url https://api.weixin.qq.com/sns/jscode2session?appid appid secret secret js_code dto.getCode() grant_typeauthorization_code; String result restTemplate.getForObject(url, String.class); JSONObject json JSONObject.parseObject(result); String openid json.getString(openid); // 2. 查询或创建用户 User user userMapper.selectOne(new LambdaQueryWrapperUser() .eq(User::getOpenid, openid)); if (user null) { user new User(); user.setOpenid(openid); user.setNickname(萌宠用户 RandomUtil.randomNumbers(6)); user.setAvatar(default.png); userMapper.insert(user); } // 3. 生成 token 存入 Redis有效期 7 天 String token UUID.randomUUID().toString().replace(-, ); redisTemplate.opsForValue().set(login:token: token, String.valueOf(user.getId()), 7, TimeUnit.DAYS); return Result.success(new LoginVO(token, user)); }注意几个容易踩的坑。第一code 只能使用一次连续点登录按钮可能造成第二次调用失败前端要加防重复提交。第二openid 是用户唯一标识绝对不能作为 token 直接用token 和 openid 要分离否则泄露一个接口参数就能冒充任意用户。第三真实项目里获取用户手机号要用微信的按钮授权组件不能自己写 input 让用户填个人小程序是不开放这个接口的。4.2 动态发布、图片上传与信息流图片上传的常规做法是后端生成一个 OSS 临时上传凭证小程序端直接直传到阿里云 OSS再回传一个图片 URL 给后端存起来。为什么不能让小程序把图片传给后端、后端再转发到 OSS因为图片体积通常几百 KB 到几 MB走你服务器转发会白白占带宽、增加接口耗时直传又快又省。后端只需要提供一个接口返回 OSS 的临时凭证和上传路径。动态发布之后进入信息流。信息流最常见的方案有三种拉模式、推模式和混合模式。毕设场景下拉模式完全够用不要碰推模式。拉模式实现思路很简单信息流接口根据当前登录用户查它关注列表然后按时间倒序拉这些人的动态再辅以分页。如果用户关注的人太少就补充一些全站热门动态兜底避免首页空荡荡。分页推荐用 cursor游标方式也就是把当前列表最后一条动态的创建时间或 ID 传回来查询条件变成 create_time lastCreateTime而不是用 offset 翻页。这有个实打实的好处新增的动态不会导致下一页里的数据重复或漏掉用户体验比 offset 好得多。用 MyBatis-Plus 的 Page 也支持但注意 order by create_time desc。4.3 同城宠物互动定位、距离计算与附近推荐同城功能是小程序里的一个亮点但也是一个容易翻车的地方。小程序端通过 wx.getLocation 获取经纬度需要在小程序后台声明位置接口用途用户也要授权。拿到经纬度之后可以在前端把定位回传也可以让后端每次请求都带经纬度参数。附近宠物列表的实现毕设阶段不搞 GeoHash 那一套用 MySQL 加 Haversine 公式直接算就行。SQL 可以这么写SELECT id, pet_name, breed, avatar_url, (6371 * acos(cos(radians(#{lat})) * cos(radians(latitude)) * cos(radians(longitude) - radians(#{lng})) sin(radians(#{lat})) * sin(radians(latitude)))) AS distance FROM pet_profile WHERE latitude IS NOT NULL HAVING distance #{radius} ORDER BY distance LIMIT 20这个 SQL 里 6371 是地球半径单位是公里。只要给 latitude 和 longitude 建复合索引在几千条数据量下性能完全没问题没必要为了这个单独引入 Elasticsearch 或者 MongoDB。如果用户拒绝授权定位就返回一个默认坐标比如选取一个城市中心然后提示用户开启定位可以获得更准的同城推荐别让整个页面直接挂掉。4.4 预约服务与订单闭环预约服务模块最容易发生的并发问题是两个人同时选中了同一个服务者的同一个时间段结果都显示预约成功。毕设阶段解决这个问题有两种手段按优先级排列一是数据库唯一索引约束比如在预约订单表加一条唯一索引 (service_id, service_date, time_slot)谁先插入谁成功后插入的人会报 DuplicateKeyException后端捕获这个异常后提示“该时间段已被预约”二是 Redis 分布式锁预约前先尝试获取锁获取失败直接返回冲突提示。我建议把唯一索引作为第一道防线因为这不需要额外依赖MySQL 本身就保证。Redis 分布式锁可以作为一个加分点自己加上并准备一段答辩话术“在外卖、家政这类场景中同一个服务者同一时间段只能服务一个订单所以用唯一索引防重复插入同时用 Redis 锁前置拦截减少无意义的数据库写冲突。”这句话一出来技术深度立刻不一样了。预约完成之后还要做一个收尾动作订单完成后用户可以评价评价内容写入评价表服务者的评分从评价表里聚合出来展示在服务列表里。评分这个细节虽然只是一个小功能但它让你的服务闭环显得完整而不是预约完就断了。4.5 私信与 WebSocket 即时通信宠物社交里“宠友互发私信”几乎是标配功能。实现方案无外乎两种接入第三方即时通讯 SDK或者自研一个简易 WebSocket 消息系统。对毕设来说第三方 SDK 虽然稳但对方 SDK 的文档、依赖、控制台配置会占用大量时间而且答辩时大多只能讲“我调了别人的接口”很难讲出深度。自研一个简易 WebSocket 一对一聊天反而是更好的选择因为逻辑足够、场景可控、能讲的东西多得多。自研方案的要点有几块WebSocket 握手时通过 token 识别用户身份服务端把 session 维护在 ConcurrentHashMap 里key 是用户 IDvalue 是 WebSocketSession。A 给 B 发消息时后端先入库message 表保存 from_user_id、to_user_id、content、is_read、create_time再检查 B 是否在线在线则直接推送不在线则等他下次上线拉取离线消息。心跳机制可以用前端定时发送 ping 消息后端响应 pong超过一定时间没收到心跳就关闭连接。自研到这一步已经能覆盖真实聊天中 80% 的基础能力。5. 第三方服务与合规细节这些坑早踩早好5.1 OSS 存储与图片处理图片存储我推荐直接用云厂商的对象存储不要自己写文件写到服务器本地。本地存储看着简单但后面会遇到几个现实问题服务器磁盘满了怎么办、图片备份怎么做、小程序访问本地图片路径不稳定。OSS/COS 本身带有 CDN 加速能力而且可以配置图片处理缩略图、水印、裁剪。接入对象存储时要考虑防盗链如果不设置别人拿到你的图片链接可以直接盗用浪费你的流量费用。可以在对象存储控制台设置 Referer 白名单只允许你的小程序域名和服务器域名访问。同时图片上传前要在小程序端做压缩微信的 wx.compressImage 可以直接用不然用户手机相册里一张 10MB 的照片传上来既慢又费流量加载列表时还会卡。5.2 内容审核社区类小程序上线逃不掉只要你的项目里有用户发布动态、评论、私信就必须考虑内容安全问题。这并不是上纲上线而是社区类小程序在上线审核时绕不过去的实际要求。最稳的做法是接入云厂商的图片/文本内容安全检测服务发布动态时先调接口检测图片里有没有违规内容、文本有没有辱骂和违法违规信息检测通过才允许入库。同时本地要做一层简单的敏感词过滤后端拿到 content 后先跑一遍词库匹配命中就拦截并把请求标记为异常。还有一个更实用的功能是举报机制动态和评论都支持用户举报举报后写入举报表管理员端哪怕只是简单的后台页面可以查看并处理比如禁言或删除动态。你不用把管理后台做得多复杂但“审核、举报、处理”这条链路得有答辩时安全性和合规性也是加分项。5.3 支付与隐私安全提醒真实接入微信支付需要企业主体、商户号、类目资质个人开发者基本走不通。毕设项目不要硬接真实支付建议做“模拟支付”用户下单后点支付弹窗显示“演示环境模拟支付成功”然后订单状态流转到待接单。在论文里解释清楚“真实环境需要接入微信支付统一下单接口本项目采用模拟支付便于演示”这个处理既真实又不会卡在资质上。隐私方面必须注意两个点。第一用户的手机号属于敏感信息存储时建议脱敏比如只存 138****1234 这种格式不要明文整串存。第二需要在小程序里配置隐私保护指引弹窗告知用户收集了位置信息、头像昵称、手机号等数据。这些不是可以跳过的流程审核时都会看。数据安全的口径在答辩时也经常被追问提前想好怎么答别只说“我数据库里有手机号字段”。6. 调试实录与经验清单交项目前最值得检查的五件事6.1 高频问题速查表问题现象常见原因解决办法登录一直失败code2Session 返回错误码appid 和 secret 不是同一套用了别人的小程序秘钥检查小程序后台的 appid/secret确认不是测试号真机预览请求全部失败小程序后台没配置 request 合法域名或 HTTPS 证书无效配置合法域名确认 Nginx 证书完整、443 端口开放图片上传到 OSS 失败临时密钥过期或者客户端时间与服务器时间不同步检查系统时间临时密钥有效期设长一点前端做重试定位一直转圈拿不到经纬度用户拒绝了授权或开发工具模拟定位没开做授权失败兜底提示手动选择城市WebSocket 连不上服务器安全组没放行对应端口或使用了 ws:// 而小程序要求 wss://上线必须用 wssNginx 配置 WebSocket 升级服务端 jar 一启动就崩没启动 Redis 或 MySQL没改数据库账号密码启动前检查依赖服务看日志里的 Caused by这里要单独提醒一下心跳包。WebSocket 长时间空闲会被服务器断开前端不处理的话用户聊着聊着就发现消息发不出去了。我在项目里做了每 30 秒前端发送一次 ping、后端立即响应 pong 的心跳机制断线之后会自动重连并重新拉取离线消息。这个细节虽然小但演示私信功能时特别重要不然现场突然断连会非常尴尬。6.2 部署演示常见翻车点毕设演示翻车率最高的一幕不是功能没写完而是“本地一切正常换一台电脑就废了”。数据库连接、Redis 地址、OSS 配置如果写死在代码里并且指向 localhost部署到服务器就必然报错。我建议所有外部配置都放进 application.yml 里部署时通过修改配置文件或环境变量切换。开发环境用本机生产环境用服务器 IP 或域名不要图省事写死。另一个高频翻车点是服务器安全组。很多同学买了云服务器只放行了 22 端口结果网页和接口全访问不了。Java 后端一般监听 8080Nginx 监听 80 和 443这些端口都要在安全组里放行。如果用了 MySQL 远程连接3306 也要放行但更安全的方式是本地连服务器 ssh 隧道别把数据库端口裸奔到公网。演示数据一定要提前准备。一个没有任何数据的社区类小程序打开首页空荡荡评委的观感会大打折扣。至少准备 3 到 5 只宠物档案、10 条以上动态、3 条附近服务、2 个不同状态的订单并且提前用演示账号把所有页面跑一遍。这套“演示数据工程”花不了太久但对答辩效果的提升是肉眼可见的。6.3 答辩时怎么讲这个 Java 毕设才不心虚评委看毕设最常问的五句话我提前整理出来为什么做这个选题答宠物经济规模增长养宠人群有社交和服务需求但市面上缺少一个把内容、互动、预约服务整合到一起的平台。系统包含哪些角色答普通用户、服务者、管理员三层角色不同角色看到的功能入口不同。核心表有哪些你们字段怎么设计的答讲用户、宠物、动态、关注、点赞、订单、通知这几张核心表再举宠物档案表为例说明一对多关系。遇到过哪些技术难点怎么解决的答同城距离计算的方案选型、并发预约防冲突、WebSocket 在线推送与离线消息这三个话题任一展开都很加分。项目有哪些不足后续怎么优化答不要只说“没有不足”而是说“当前采用 MySQL 范围计算距离数据量增大后可引入 GeoHash 或 Elasticsearch消息推送是单机 WebSocket后续可引入 MQ 和分布式长连接网关”。最后一句话我想特别强调答辩的时候千万不要背代码没人关心你写了多少行。评委更想听到的是你的“决策过程”——为什么选这个数据库、为什么用 Redis、为什么分页用游标、并发问题怎么保证。把每个技术选型背后的为什么讲明白你的 Java 毕设自然就到了优秀档。这个项目做完之后我最大的体会是收获不是学会了多少个框架而是把一条业务链路从产品定位、表结构、后端接口到小程序部署完整走了一遍。如果让我重做一遍我会把更多时间花在“先画业务流程再写代码”上需求一旦通了后端写起来几乎是流水线。另外提醒一句代码一定要自己敲哪怕参考开源项目也要把每个模块吃透不然答辩现场一追问就露馅。一个能流畅跑通完整链路的小程序永远比十个只写了一半的零散功能更有说服力这也是这个项目真正沉淀下来的最重要经验。