
简介基于 Java、SSMSpring/SpringMVC/MyBatis框架和微信小程序开发的宠物寄养平台是一套可直接运行的高分毕业设计项目适合计算机相关专业学生用于毕业设计、课程设计或期末大作业。系统包含宠物主人、寄养者、管理员三类角色覆盖发布寄养、浏览宠物、预约寄养、消息通知、后台管理等完整业务链路前后端代码齐全并配套论文文档解决了从零搭建项目与撰写文档的两大难题。资源包整体大小为 47.16MB共 1206 个文件主要包含 Vue/JavaScript 前端代码、Java 后台逻辑、JSON/WXML/WXSS 小程序页面、PNG/SVG 界面素材、SQL 数据库脚本以及 doc/docx 论文和部署脚本等目录结构清晰便于按模块检索学习。目前已有 49 人学习浏览项目经过严格调试功能完善、界面美观、操作简洁既可直接作为毕业设计作品也可作为学习 SSM 框架、小程序开发与前后端分离实践的优质参考。1. 宠物寄养平台不是玩具项目它为什么适合做 Java 毕设看到这份「基于 javassmmysql微信小程序的宠物寄养平台」源码包你的第一反应可能是一个普通的预约下单项目。我反而觉得它是少数能讲清楚完整业务闭环的毕设选题线下宠物店寄养靠 Excel 登记主人不知道宠物每天什么状态小程序端预约、后台管订单正好戳中真实痛点。技术栈也稳SSM 分层清晰、MySQL 容易部署、微信小程序自带登录和消息能力答辩时每一层都能展开讲。适合正在选毕设题目的在校生也适合想补 Java 项目经验的转行者。下面按部署顺序拆开讲哪里会翻车我也会标记出来。2. 拆解平台的技术选型SSM 为什么还不过时MySQL 和微信小程序各承担什么2.1 SSM 三个框架在项目里各自管什么SSM 是 Spring、SpringMVC、MyBatis 三个框架的合称。Spring 负责对象创建、依赖注入和事务管理SpringMVC 负责接收 HTTP 请求把 URL 映射到 ControllerMyBatis 负责把 Java 方法和 SQL 语句对应起来完成数据库读写。放到宠物寄养平台里就是三层小程序请求先到 ControllerController 把参数交给 ServiceService 里写“下单前检查宠物档案是否完整”这类业务规则最后通过 Mapper 访问 MySQL。为什么毕设选 SSM 而不是 Spring Boot不是因为 SSM 更好而是因为它更“透明”。Spring Boot 的自动配置省事但答辩时老师问你“请求是怎么进到 Controller 的”你不容易说清楚。SSM 的 web.xml、spring-mvc.xml、mybatis-config.xml 都是显式配置每一行都能讲出作用。还有一个实际理由java 面试八股文里 SSM 仍然是高频考点做完这个项目Spring 容器、事务传播、MyBatis 映射这些问题都能顺手复习到。如果你已经熟练 Spring Boot当然可以换但很多源码包就是 SSM换框架要动配置和依赖临毕业没必要冒这个险。看一个最核心的 Controller 写法RestController RequestMapping(/api/order) public class OrderController { Autowired private OrderService orderService; PostMapping(/create) public Result create(RequestBody OrderCreateRequest req) { // 小程序端提交预约信息这里只做参数接收和结果返回 int orderId orderService.createOrder(req); return Result.ok(orderId); } }这段代码的逻辑很简单RestController让 SpringMVC 把这个类的返回值直接写成 JSON小程序端收到的就是{code:200,data:1024}这样的结构。RequestBody把前端 POST 过来的 JSON 反序列化成OrderCreateRequest对象前端传的字段名必须和实体字段一致比如petId、serviceId、startDate。真正重要的是orderService.createOrder(req)里面的逻辑插入订单、更新宠物状态、扣减寄养位数量要放在同一个事务里任何一个步骤失败都要回滚这就是 java 里保证数据一致性的标准做法。常见误用是有人把 SQL 直接写在 Service 里Controller 里塞一堆业务判断MyBatis 只做一个空壳。论文里的“分层设计”章节就很好写但如果你不分层答辩时老师翻开代码会直接问“你的事务控制在哪里”。所以拿到源码以后先看 Controller 和 Service 是不是分开的再看 Service 方法上有没有Transactional这两点决定了这个项目值不值得改成你自己的。2.2 MySQL 表设计宠物寄养最核心的 5 张表宠物寄养平台的实体关系不复杂用户拥有宠物宠物发起寄养订单订单选择服务用户对完成的寄养做评价。围绕这个闭环核心表可以控制在 5 张。表名作用关键字段user小程序用户id, openid, phonepet宠物档案id, user_id, name, type, breedservice寄养服务id, name, price, unitorder寄养订单id, order_no, user_id, pet_id, service_id, status, start_date, end_date, amountreview评价id, order_id, user_id, content, score先看用户表。openid 是微信小程序用户的唯一标识要建唯一索引同一个微信号只能对应一条记录。CREATE TABLE user ( id int NOT NULL AUTO_INCREMENT, nickname varchar(32) NOT NULL DEFAULT , phone varchar(20) DEFAULT , openid varchar(64) NOT NULL, create_time datetime NOT NULL, PRIMARY KEY (id), UNIQUE KEY uk_openid (openid) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;字段说明openid用 varchar(64)微信返回的 openid 长度一般在 28 到 36 位之间留够余量phone允许为空因为用户可能拒绝授权手机号create_time用 datetime不要用 timestamp不然 2038 年之后都是坑。字符集统一用 utf8mb4因为用户昵称里可能出现 emojiutf8 存不下。订单表是另一个容易写错的表因为order是 MySQL 关键字建表时必须加反引号。CREATE TABLE order ( id int NOT NULL AUTO_INCREMENT, order_no varchar(32) NOT NULL, user_id int NOT NULL, pet_id int NOT NULL, service_id int NOT NULL, status tinyint NOT NULL DEFAULT 0, start_date date NOT NULL, end_date date NOT NULL, amount decimal(10,2) NOT NULL, create_time datetime NOT NULL, PRIMARY KEY (id), KEY idx_user_id (user_id), KEY idx_status (status) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;这里的status用 tinyint 表示订单状态0 待支付、1 已支付、2 寄养中、3 已完成。用数字不用字符串是为了查询快、存储省也方便在代码里做状态机。DEFAULT 0正好是 mysql 设置默认值为 0 的常见姿势。金额字段用decimal(10,2)绝对不要用 float不然算寄养费会产生 0.01 的误差。日期用 date含时间用 datetime分开存更清晰。一个建议物理外键能不加就不加。原因很简单初始化 SQL 脚本如果包含外键导入时必须先父表后子表一旦顺序不对脚本直接报错演示完想清空数据重新导入也麻烦。保留user_id、pet_id这些字段做逻辑关联在代码里去校验完全够用。2.3 微信小程序端为什么比纯 H5 更合适宠物寄养是低频但刚需的场景用户不会专门去记一个 H5 网址但会在微信里搜“宠物寄养”打开小程序。小程序的主要优势有三个微信登录免注册wx.login就能拿到身份标识订阅消息可以在寄养开始和结束时提醒用户入口在微信里用完不占手机内存。从开发角度看小程序端和后台是两套独立工程。小程序里常见的结构是 tabBar 四个页面首页展示服务和门店信息预约页填写寄养信息订单页查看状态我的页面管理宠物档案。每个页面由.wxml、.wxss、.js、.json四个文件组成原生语法在答辩时特别好讲直接指出“这是 WXML 模板逻辑在 JS 里跑”。有人会纠结要不要用 uniapp 做多端我的建议是毕设别折腾。题目明确写了微信小程序就用原生语法。uniapp 多一层编译有时在 Android 和鸿蒙的 WebView 上表现不一样调试报错会多一个“编译后代码”的黑匣子答辩现场没必要给自己加戏。等参加工作以后对多端有需求再用 uniapp 完全不迟。3. 把项目跑起来的完整步骤从 MySQL 初始化到微信开发者工具加载3.1 环境清单JDK、Tomcat、MySQL、微信开发者工具的版本搭配拿到源码包以后第一件事不是打开 IDEA 直接运行而是先确认本机环境。相当一部分毕设项目跑不起来问题都不在代码而是版本搭错了。组件推荐版本说明JDK1.8SSM 老项目在 JDK 11 以上容易遇到反射和 cglib 问题MySQL5.7 或 8.08.0 要切换驱动类并配置时区Tomcat8.5 或 9.0与 JDK 1.8 搭配最稳妥Maven3.6 以上依赖管理pom.xml 由 Maven 解析微信开发者工具最新稳定版只用来调试小程序前端这三件套的安装并不复杂。Windows 用 MySQL InstallerLinux 按发行版选安装方式Ubuntu 用apt install mysql-serverCentOS 用yum install mysql-community-server装完以后执行mysql_secure_installation设置 root 密码。真正花时间的是把字符集调成 utf8mb4否则导入 SQL 后中文变成乱码。IDEA 导入 SSM 项目有一个细节解压后目录里如果已经有.idea文件夹直接 Open 可能会沿用别人的配置建议删掉.idea再打开。如果 pom.xml 没有被识别右键选 “Add as Maven Project”等依赖下载完。接下来配置 TomcatRun → Edit Configurations → Tomcat Server → Local选择 Tomcat 安装目录在 Deployment 里添加 war explodedApplication context 写/这样小程序端请求http://localhost:8080/api/...才不会多一层路径。3.2 初始化数据库执行 SQL 脚本的前后检查源码包里一般带一个.sql文件也可能叫init.sql或者pet_boarding.sql。导入之前先用文本编辑器打开看前 30 行确认有没有CREATE DATABASE和USE语句。如果带了直接在命令行导入。mysql -uroot -p --default-character-setutf8mb4 /path/to/pet_boarding.sql mysql -uroot -p -e USE pet_boarding; SHOW TABLES;第一条命令把表结构和初始化数据导入 MySQL--default-character-setutf8mb4是为了让中文字符串不被转成乱码。第二条命令验证导入结果进入pet_boarding库并列出所有表。正常情况下会看到上面说的 5 张核心表外加管理员表、参数配置表等扩展表。如果表数量不对大概率是脚本里有外键依赖导入顺序出问题需要在脚本开头加上SET FOREIGN_KEY_CHECKS0;。图形化用户一般用 Navicat for MySQL 导入先创建好数据库再右键数据库选择“运行 SQL 文件”。注意 SQL 文件里如果有USE pet_boarding而你没有先创建这个库导入会直接报错。图形化导入还有一个好处是导入完成后立刻能看到表结构和行数方便核对。数据库就绪之后修改后端项目的数据库连接配置。SSM 里一般是一个jdbc.properties文件jdbc.drivercom.mysql.cj.jdbc.Driver jdbc.urljdbc:mysql://localhost:3306/pet_boarding?useUnicodetruecharacterEncodingutf8useSSLfalseserverTimezoneAsia/Shanghai jdbc.usernameroot jdbc.password123456driver 写成com.mysql.cj.jdbc.Driver对应 MySQL 8.0。url 里有几个参数很关键useUnicodetrue和characterEncodingutf8保证中文入库不乱码useSSLfalse是为了避开 MySQL 8.0 启动时常见的 SSL 连接告警serverTimezoneAsia/Shanghai防止日期差 8 小时。如果连的是远程数据库把 localhost 换成目标 IP并且确认防火墙放行 3306 端口。3.3 后台接口联调用 Postman 验证登录和下单两个核心接口Tomcat 启动看到Server startup in [xxx] ms之后先别急着打开微信开发者工具。用 Postman 把后端接口跑通能把前后端问题一分为二。很多人直接打开小程序看到 request fail 以为是前端问题结果后端服务根本没起来。登录接口取决于源码包设计常见的是管理员登录接口用于后台管理端curl -X POST http://localhost:8080/api/admin/login \ -H Content-Type: application/json \ -d {username:admin,password:123456}返回{code:200,data:{token:xxx}}说明接口正常。如果返回 500看 Tomcat 控制台日志用户名密码错了一般是 SQL 查不到记录不会报 500。接着测创建订单接口curl -X POST http://localhost:8080/api/order/create \ -H Content-Type: application/json \ -H Authorization: Bearer xxx \ -d {user_id:1,pet_id:1,service_id:2,start_date:2025-06-01,end_date:2025-06-03}user_id、pet_id、service_id要和数据库里已经存在的记录对应否则外键约束不会有但业务校验会提示“宠物不存在”。这一步最容易踩的坑是参数名不匹配后端实体用userId前端传user_idMyBatis 映射不上接口报 500。解决办法是统一下划线风格或者在代码里用JsonProperty做映射。接口验证通过后再打开微信开发者工具导入小程序端源码目录。AppID 可以先用测试号开发阶段在“详情 → 本地设置”里勾选“不校验合法域名”。到这里后台和小程序端的通路就打通了。4. 微信小程序端的对接登录态、订单列表和消息提醒的实现细节4.1 小程序登录wx.login 换 code后端怎么换 openid小程序登录是整个前端对接的第一步流程是wx.login拿到临时 code把 code 发给后端后端用 code、appid、secret 换 openid后端查 user 表没有就自动创建用户然后返回一个自定义 token。wx.login({ success(res) { if (res.code) { wx.request({ url: http://localhost:8080/api/user/login, method: POST, data: { code: res.code }, success(r) { if (r.data.code 200) { wx.setStorageSync(token, r.data.data.token); } else { wx.showToast({ title: r.data.message, icon: none }); } } }); } } });前端这里不要做任何业务判断只需要把 code 交给后端。code 是一次性的有效期 5 分钟同一个 code 用第二次微信会直接拒绝。后端拿到 code 以后需要向微信接口发请求String url https://api.weixin.qq.com/sns/jscode2session?appid appid secret secret js_code code grant_typeauthorization_code; // 用 HttpClient 发起 GET 请求解析返回的 openid // appid 和 secret 只能放在服务端不能写在小程序源码里解析到 openid 之后查user表。如果查不到就插入一个新用户这里nickname可以先给默认值等用户主动授权再更新。最后生成一个 UUID 作为 token 返回给前端。毕设阶段可以把 token 放在内存 Map 里服务重启 token 失效用户需要重新登录。这个“重启即掉线”的代价可以接受答辩时如果老师问就说生产环境会换成 Redis逻辑是一样的。注意一个安全细节session_key不要返回给前端也不能写进日志。前端只认自己的 token后端所有需要登录的接口都检查这个 token 是否存在。4.2 订单列表的下拉刷新与缓存时间设置订单列表是高频页面每次进入都请求接口会拖慢页面还会让后端无谓地多处理请求。常见做法是加一个短时缓存配合下拉刷新强制更新。Page({ data: { orders: [], loading: false }, onShow() { this.loadOrders(); }, onPullDownRefresh() { this.loadOrders(true); wx.stopPullDownRefresh(); }, loadOrders(force) { const cache wx.getStorageSync(orderListCache); if (!force cache Date.now() - cache.t 3 * 60 * 1000) { this.setData({ orders: cache.list }); return; } wx.request({ url: http://localhost:8080/api/order/list, header: { token: wx.getStorageSync(token) }, success: (res) { if (res.data.code 200) { const list res.data.data; wx.setStorageSync(orderListCache, { list, t: Date.now() }); this.setData({ orders: list }); } } }); } });缓存时间设置在这里就是3 * 60 * 1000意思是 3 分钟内不重新请求。force参数给下拉刷新用传 true 时强制走接口保证用户主动刷新能看到最新状态。缓存 key 建议拼上用户 ID比如orderListCache_${userId}否则切换账号后可能看到上一个用户的订单。还有一个很常被忽略的细节是自定义导航栏高度。页面用自定义导航栏时内容会被顶到状态栏下面需要用代码避让const { statusBarHeight } wx.getWindowInfo(); this.setData({ statusBarHeight });状态栏高度加上导航栏本身的高度一般是statusBarHeight 44。不同手机这个值不完全一样但 44px 是微信官方设计稿里比较稳妥的经验值。很多毕设页面在这块翻车表现为文字和左上角胶囊按钮重叠答辩照片都拍不好看。4.3 预约寄养时用单选框选择服务类型预约寄养的页面里服务类型要用单选因为一次寄养只能选一种服务比如普通寄养、VIP 寄养、带遛狗服务。WXML 代码如下radio-group bindchangeonServiceChange label wx:for{{services}} wx:keyid styledisplay:block; padding:12rpx 0; radio value{{item.id}} checked{{item.id selectedServiceId}} color#07c160 / text{{item.name}}{{item.price}}元/天/text /label /radio-group对应的 JS 处理函数onServiceChange(e) { this.setData({ selectedServiceId: Number(e.detail.value) }); }这里有三个容易踩的坑。第一radio-group的bindchange返回的 value 是字符串而后端serviceId是 int提交前必须用Number()转换否则条件item.id selectedServiceId全都不成立。第二checked要写在radio上写在label上不会生效。第三wx:key用 id不要用索引否则列表顺序变化时选中状态会错位。选中服务类型之后提交按钮还要做一次完整校验selectedServiceId是否为 0、startDate是否早于endDate。这些校验前端做一遍后端 Service 层也要做一遍双保险。另外提一句微信小程序年审如果以后想把项目真正上线真实微信登录和订阅消息要求小程序已经注册并完成年审个人主体可用的类目有限。但毕设演示用测试号或体验版就行不用走年审流程。5. 避坑与排查宠物寄养平台最常见的 5 个翻车点5.1 服务启动阶段的三类问题这一节是血泪经验比较集中的地方。项目跑不起来多数问题集中在启动阶段。现象 1Tomcat 启动失败提示端口被占用。原因之前启动的服务没有完全关掉或者本机其他程序占用了 8080。解决Windows 执行netstat -ano | findstr 8080Linux 或 Mac 执行lsof -i:8080找到占用端口的 PID 后结束进程。也可以直接在 IDEA 里把 Tomcat 端口改成 8081但小程序端所有请求地址要跟着改。现象 2后端日志报Cannot create PoolableConnectionFactory程序启动失败。原因数据库连接池创建失败本质是 MySQL 没启动、密码不对或者连接串配置有问题。解决先手动执行mysql -uroot -p确认能登录再用 Navicat for MySQL 按jdbc.properties里的 URL 试连一次。这里要检查的地方是数据库连接池参数尤其是 MySQL 8.0 的驱动类是否写成了com.mysql.jdbc.Driver这个老驱动在 8.0 下会直接报错必须换成com.mysql.cj.jdbc.Driver。现象 3Linux 下连接 MySQL 报ERROR 2002 (HY000): Cant connect to local MySQL server through socket /tmp/mysql.sock。原因MySQL 服务没有启动或者 socket 文件路径不对。解决执行systemctl status mysqld看服务状态如果没启动就执行systemctl start mysqld。用源码方式安装的 MySQLsocket 文件可能被配置在其他目录直接用mysql -h127.0.0.1 -P3306 -uroot -p绕过 socket 连接能连上就行。这三条放在一起是因为它们有个共同点报错信息指向的问题往往不是真正的问题。端口占用是明面上的但为什么占用才是关键连接池失败是结果密码对不对才是关键。5.2 业务代码和数据层面的两类问题现象 4订单已经支付但订单状态还是 0待支付。原因支付回调里更新订单状态和查询订单不在同一个事务或者异常被 try-catch 吞掉了。解决把状态更新方法放到 Service 层加上Transactional这样更新失败整个事务回滚不会出现钱扣了但订单没变化的情况。另外不要在 catch 里只 log 不处理那会把事务标记成可提交等于白写事务。数据一致性在 SSM 里最可靠的保证就是事务。现象 5小程序请求后端接口报request:fail url not in domain list。原因微信开发者工具默认校验 request 合法域名本地调试用的是 IP 不是 HTTPS不满足要求。解决开发阶段在“详情 → 本地设置”勾选“不校验合法域名”上线后必须在小程序管理后台配置 request 合法域名并且这个域名必须是 HTTPS。很多人卡在这里其实是把开发环境和生产环境的要求搞混了。如果后端本机部署小程序模拟器可以访问http://localhost:8080真机预览就不行真机只能访问局域网 IP 或已备案的 HTTPS 域名这个问题在现场演示时尤其容易突发。6. 把毕设包装成能演示的项目三个收尾技巧项目能跑和能演示是两回事。我自己做答辩项目时会额外花一个晚上做三件事效果非常明显。第一件事准备一份演示数据。在pet_boarding.sql之外再写一个demo_data.sql包含 2 个用户、3 只宠物、4 条订单订单状态覆盖“待支付 → 已支付 → 寄养中 → 已完成”的完整链路。演示时按状态筛选老师能看到每个阶段的界面而不是对着空列表讲功能。第二件事写一份 README。把环境版本、导入步骤、默认管理员账号、小程序 AppID 怎么配置写清楚。老师问“项目怎么跑”你照着 README 念一遍既不会遗漏步骤也显得专业。第三件事用 Postman Runner 做一次接口验证。打开 Postman 的 Runner把创建订单接口循环跑 20 次观察后端日志有没有异常。这能提前暴露并发插入订单时可能出现的重复号问题也能在答辩时直接展示“接口经过重复调用测试”。演示顺序我习惯固定为启动 MySQL → 启动 Tomcat → 打开微信开发者工具 → 登录 → 创建寄养订单 → 切到后台管理端看到新订单。整个流程控制在 3 分钟内不临时去翻代码。每次答辩前我会把电脑重新走一遍这个流程这是我自己用过最有效的后悔药。希望帮到你。本文还有配套的精品资源点击获取