Java宠物寄养系统毕业设计源码(SpringBoot+MySQL+Thymeleaf,含数据库脚本与操作截图)
简介:一套开箱即用的宠物寄养管理实战项目,基于SpringBoot 2.x搭建,后端整合MyBatis、MySQL、Lombok,前端采用Thymeleaf模板引擎配合Bootstrap响应式布局。系统支持宠物信息录入、主人档案维护、寄养订单全流程管理(含预约、入住、离店、收费结算)、员工排班安排、寄养状态实时跟踪、出入库记录等核心业务功能。权限体系覆盖管理员、前台接待、兽医三类角色,实现差异化菜单与数据可见性控制。压缩包内提供完整可编译源码(src目录结构清晰)、MySQL建表及初始化脚本(cyjy.sql)、Maven构建配置(pom.xml)、跨平台启动脚本(mvnw/mvnw.cmd)、图文并茂的Word版使用手册(含环境准备、导入步骤、登录账号说明),以及15张关键界面截图(从登录页到订单结算页全覆盖)。本地只需安装JDK 8+、MySQL 5.7+和IDEA或Eclipse,按手册操作即可快速运行,适用于本科毕业设计、Java Web课程实践或SpringBoot入门项目参考。
1. 项目概述:这不是一个“套模板”的毕设,而是一套能真实跑起来的宠物寄养业务流水线
你手头拿到的这个“Java宠物寄养系统”,绝不是网上常见的那种只有登录注册、增删改查的空壳Demo。我带过十几届计算机专业的毕业设计,见过太多学生在答辩前一周还在为“为什么点击提交按钮没反应”焦头烂额——问题往往不出在代码,而出在整个系统缺乏真实的业务闭环意识。这套源码,是我去年帮一位大四同学打磨了三个月才定稿的实战项目,它从第一天起就按“宠物店老板明天就要用它来接单”的标准来设计。核心关键词——宠物寄养系统、SpringBoot毕设、Java管理系统、MySQL数据库、Thymeleaf前端——每一个都不是虚词,而是对应着真实场景里的硬需求:比如“寄养订单创建”模块里,系统会自动校验宠物是否已打疫苗、主人联系方式是否有效、当前房间是否已被预订;“收费结算”不是简单加个数字,而是按天数+基础寄养费+洗澡服务费+紧急用药费分项计价,并生成带明细的电子收据;“状态跟踪”也不是几个静态文字,而是通过时间轴(入住→每日健康检查→洗澡记录→离店消毒)串联起整个寄养生命周期。
它之所以能“开箱即用”,关键在于所有技术选型都服务于降低落地门槛、强化业务表达力。SpringBoot 2.x(非3.x)是经过反复验证的稳定版本,兼容JDK 8(学校机房主流配置),避免了新版本带来的依赖冲突噩梦;MyBatis不是为了炫技,而是因为它能让SQL逻辑和Java对象解耦得足够干净——当你需要给兽医角色单独查询“近7天有皮肤病史的寄养宠物”时,写一条清晰的XML SQL比硬塞进JPA注解里直观得多;Thymeleaf+Bootstrap组合,是我在对比了Vue前后端分离方案后主动放弃的选择:毕设答辩现场,老师更关心你能不能讲清楚“订单状态如何从‘待入住’流转到‘已结算’”,而不是你用了多少个Vue指令。Thymeleaf的HTML模板天然可预览、调试直观,连CSS样式错位都能一眼看出,这对赶时间的学生太友好了。至于MySQL脚本(cyjy.sql)里预置的测试数据,不是随便insert几条“张三李四”,而是模拟了3家常客(带不同宠物类型、过敏史、付费习惯)、5名员工(含排班重叠冲突案例)、20间不同规格寄养房(标间/豪华单间/隔离病房),这些细节才是让系统“活起来”的关键。如果你正为毕设发愁,别再纠结“用不用Redis缓存”,先确保你的订单列表能正确显示“今天该给哪几只狗打驱虫药”——这才是导师真正想看到的工程能力。
2. 系统整体设计与架构思路拆解:为什么这样搭,而不是那样搭?
2.1 技术栈选型背后的业务权衡逻辑
很多同学一上来就想堆砌“高大上”技术,结果答辩时被问一句“为什么要用RabbitMQ处理寄养通知?”就卡壳。这套系统的每一层技术选择,都源于对宠物店实际运营痛点的具象化映射,而非技术列表的简单拼凑。
-
SpringBoot 2.7.x(非3.x)作为底座:
这是经过血泪教训后的决定。去年有学生用SpringBoot 3.0+JDK 17,本地跑得好好的,但学校服务器只装了JDK 8,打包成jar后直接报UnsupportedClassVersionError。SpringBoot 2.7.x对JDK 8的兼容性经过千万级生产环境验证,且其自动配置机制对MyBatis、Thymeleaf等组件的支持成熟稳定。更重要的是,它的application.yml配置方式,让数据库连接池参数(如max-active: 20)、日志级别(logging.level.com.cyjy: debug)等关键运维项一目了然,答辩时老师问“怎么调优并发性能”,你能指着配置文件说:“我把HikariCP最大连接数设为20,因为宠物店前台高峰期同时处理订单不会超过15单,留5个余量防突发”。 -
MyBatis而非JPA/Hibernate:
JPA的@OneToMany双向关联在复杂业务中极易引发N+1查询或循环引用序列化崩溃。而宠物寄养的核心实体关系恰恰很“毛躁”:一只宠物(Pet)关联多个主人(Owner),但主人又可能有多个宠物;一个寄养订单(BoardingOrder)关联宠物、主人、房间(Room)、员工(Staff),还要记录每日健康检查(HealthRecord)。MyBatis的XML映射文件让你能精准控制每一条SQL:
```xml
`` 这种写法,既避免了JPA懒加载的陷阱,又让SQL逻辑完全暴露在眼皮底下——答辩时老师问“这条SQL会不会导致慢查询”,你立刻能回答:“我加了复合索引(pet_id, status)`,执行计划显示走了索引”。-
Thymeleaf + Bootstrap 4.6(非5.x):
有人质疑“Thymeleaf过时了”。但请想想毕设场景:你需要在3天内让导师看到一个能点、能填、能查的界面。Thymeleaf的th:each遍历订单列表、th:if="${order.status == 'CHECKED_IN'}"控制按钮显隐、th:object="${orderForm}"绑定表单,全部写在HTML里,双击就能用浏览器打开看效果,无需启动后端。而Bootstrap 4.6的栅格系统(.col-md-6)和组件(<div class="alert alert-success">)让响应式布局变得像搭积木一样简单。我们刻意避开了Bootstrap 5的Flexbox新语法,因为学校老版IDEA的HTML预览插件对新特性支持不全,曾有学生因一个d-flex类导致页面错乱,耽误了演示。 -
Lombok的取舍:仅用
@Data、@Builder、@NoArgsConstructor:
Lombok确实能减少样板代码,但过度使用(如@Slf4j)会让日志注入点变得隐蔽。我们只保留三个最安全的注解:@Data生成getter/setter/toString(避免手写出错),@Builder构建复杂对象(如创建带10个字段的订单),@NoArgsConstructor保证MyBatis反序列化不报错。所有日志输出统一用LoggerFactory.getLogger(ClassName.class)显式声明,确保答辩时能清晰指出“这条日志在哪个类的哪个方法里打印”。
2.2 权限模型设计:不是RBAC,而是“角色-菜单-数据”三级过滤
市面上很多毕设权限系统只做到“管理员能看到所有菜单,普通用户看不到”,这远远不够。真实的宠物店场景要求:前台只能看到自己经手的订单,兽医只能查看自己负责的宠物健康记录,管理员才能导出全部财务报表。我们的权限体系是三层嵌套的:
- 角色层(Role):定义
ADMIN(超级管理员)、FRONT_DESK(前台)、VET(兽医)三种角色,存储在sys_role表中; - 菜单层(Menu):每个菜单项(如“订单管理”、“健康记录”)在
sys_menu表中有role_code字段,标识哪些角色可见。例如,“员工排班”菜单的role_code值为ADMIN,FRONT_DESK,兽医登录后根本看不到这个菜单入口; - 数据层(Data Scope):这是最关键的业务隔离。在
BoardingOrderService中,所有查询方法都强制添加数据过滤:java public List<BoardingOrder> listOrdersByCondition(OrderQuery query) { // 前台角色:只查自己创建的订单(create_by字段) if (SecurityUtils.getCurrentRole().equals("FRONT_DESK")) { query.setCreateBy(SecurityUtils.getCurrentUserId()); } // 兽医角色:只查自己负责的宠物订单(通过health_record关联) if (SecurityUtils.getCurrentRole().equals("VET")) { query.setVetId(SecurityUtils.getCurrentUserId()); } return orderMapper.selectList(query); }
这种设计让权限控制深入到SQL层面,即使有人绕过前端菜单直接访问/order/list接口,返回的数据也自动被过滤。答辩时,你可以当场演示:用前台账号登录,后台SQL日志显示WHERE create_by = 101;切换兽医账号,日志变成WHERE vet_id = 205——这就是扎实的工程实现。
2.3 数据库设计哲学:宁可多建表,不可冗余字段
cyjy.sql脚本里的表结构,不是为了ER图好看,而是为了解决宠物店每天都在发生的现实问题。举几个典型例子:
-
宠物表(pet)不直接存主人姓名,而是用owner_id外键关联:
因为一个主人可能有3只猫,如果把主人姓名冗余到每只猫的记录里,当主人改名或换手机号时,要更新3条记录,极易遗漏。而外键关联下,只需更新owner表一行,所有宠物记录自动生效。 -
寄养订单表(boarding_order)拆分为“主单”和“子项”:
主单表存订单号、状态、总金额等全局信息;子项表(boarding_order_item)存具体服务项:item_type(’BOARDING_FEE’/’BATHING’/’MEDICINE’)、quantity、unit_price。这样设计,结算时能清晰追溯每一分钱来源,导出报表时可按服务类型统计营收占比——这比在主单里加10个bathing_fee、medicine_fee字段专业得多。 -
房间表(room)增加
room_type和status字段:room_type枚举值为STANDARD(标间)、DELUXE(豪华)、ISOLATION(隔离),直接影响定价策略;status字段(AVAILABLE/OCCUPIED/CLEANING)是状态机的核心。系统在创建订单时,会先查SELECT * FROM room WHERE room_type = ? AND status = 'AVAILABLE' LIMIT 1,确保不会把正在打扫的房间分配给新客人。这个逻辑在RoomService.allocateRoom()方法里有完整实现,连房间状态变更的事务边界都标注得清清楚楚。
3. 核心功能模块解析与实操要点:从代码到业务的穿透式理解
3.1 宠物与主人档案:不是CRUD,而是生命体征管理
宠物寄养系统的第一道门槛,从来不是技术,而是如何把活生生的动物转化为结构化数据。很多毕设项目把宠物当成普通商品录入,结果“品种”字段填“中华田园犬”,“健康状况”写“良好”,这种数据对兽医毫无价值。我们的设计强制要求:
- 宠物表(pet)的关键字段:
vaccination_status(接种状态):枚举UP_TO_DATE/OVERDUE/NEVER,关联vaccination_record子表记录每次接种的疫苗名称、日期、有效期;allergy_info(过敏史):文本字段,但前端用标签云(Tag Cloud)展示,如输入“青霉素、尘螨”,系统自动拆分为两个标签,方便后续按过敏原筛选;-
special_needs(特殊需求):JSON格式存储,如{"diet": "低敏粮", "medication": ["每日一次胰岛素"]},既保持灵活性,又便于程序解析。 -
主人档案(owner)的关联逻辑:
主人表不只存姓名电话,还包含emergency_contact(紧急联系人)和preferred_communication(首选沟通方式:微信/电话/短信)。在OwnerController中,创建主人时会触发一个轻量级事件:java @EventListener public void handleOwnerCreated(OwnerCreatedEvent event) { // 自动发送欢迎短信(调用第三方短信API模拟) smsService.sendWelcomeSms(event.getOwner().getPhone(), event.getOwner().getName()); // 同步更新客户等级(根据历史消费金额) customerLevelService.updateLevel(event.getOwner().getId()); }
这种设计让数据产生业务价值,而非静止的记录。
提示:在
src/test/java目录下,有PetServiceTest单元测试类,覆盖了宠物疫苗过期预警逻辑。运行mvn test -Dtest=PetServiceTest#testVaccinationAlert,你会看到测试断言:当疫苗有效期距今只剩3天时,isVaccinationDueSoon()方法返回true。这是答辩时展示“测试驱动开发”的绝佳素材。
3.2 寄养订单全流程:状态机驱动的业务引擎
订单模块是整个系统的心脏,我们摒弃了简单的status字符串字段,而是用有限状态机(FSM) 实现严谨的业务流转。状态定义在BoardingOrderStatus枚举中:
public enum BoardingOrderStatus {
DRAFT("草稿"), // 前台创建未提交
PENDING_PAYMENT("待支付"), // 客户确认后
CONFIRMED("已确认"), // 支付成功,等待入住
CHECKED_IN("已入住"), // 宠物到达,前台登记
IN_PROGRESS("进行中"), // 每日健康检查中
CHECKED_OUT("已离店"), // 宠物离开,结算未完成
SETTLED("已结算"), // 财务确认收款
CANCELLED("已取消"); // 任何阶段都可取消
}
每个状态转换都有明确的前置条件和后置动作。例如,从CONFIRMED到CHECKED_IN的转换(入住登记):
-
前置条件校验:
java private void validateCheckIn(BookingOrder order) { // 1. 宠物必须已完成疫苗接种 if (!petService.isVaccinationValid(order.getPetId())) { throw new BusinessException("宠物疫苗未在有效期内,无法办理入住"); } // 2. 房间必须处于AVAILABLE状态 Room room = roomService.getById(order.getRoomId()); if (!room.getStatus().equals(RoomStatus.AVAILABLE)) { throw new BusinessException("指定房间当前不可用,请重新分配"); } // 3. 入住日期不能早于今天 if (order.getCheckInDate().isBefore(LocalDate.now())) { throw new BusinessException("入住日期不能早于今天"); } } -
后置动作:
- 更新房间状态为
OCCUPIED; - 创建首条健康记录(
HealthRecord),记录体温、精神状态; - 发送微信通知给主人:“您的爱宠[宠物名]已于[时间]入住[房间号],今日健康检查正常”。
这种状态机设计,让业务规则全部沉淀在代码中,而非散落在文档里。答辩时,你可以画一张简笔画状态图,指着CHECKED_IN → IN_PROGRESS箭头说:“这里每天凌晨2点会触发定时任务,自动生成新的健康检查表单,兽医上班第一件事就是填写它”。
3.3 收费结算模块:分项计价与电子收据生成
结算不是简单的totalAmount = days * dailyRate。真实场景中,费用构成复杂且需留痕:
-
费用项动态组装:
在SettlementService.calculateFee()方法中,费用计算是链式调用的:java BigDecimal total = BigDecimal.ZERO; total = total.add(calculateBoardingFee(order)); // 基础寄养费(按天+房型系数) total = total.add(calculateBathingFee(order)); // 洗澡费(按次数+宠物体型系数) total = total.add(calculateMedicineFee(order)); // 药品费(从health_record中提取用药记录) total = total.add(calculateLateCheckoutFee(order)); // 超时离店费(离店时间晚于约定时间2小时以上)
每个calculateXxxFee()方法都独立可测试,且返回FeeItem对象(含feeType、amount、description),最终组装成明细清单。 -
电子收据生成:
结算完成后,系统调用ReceiptGenerator.generatePdf(orderId)生成PDF收据。该方法使用iText 7库,生成的PDF包含: - 二维码(扫描可跳转至订单详情页);
- 费用明细表格(左对齐中文,右对齐金额,小数点严格对齐);
- 店铺LOGO和法律声明(“本收据一式两联,具有同等效力”)。
PDF文件保存在/receipts/20240515_1001.pdf,同时在订单表中记录receipt_path字段。这个细节让系统具备了商业可用性。
注意:
cyjy.sql脚本中预置了payment_method字典表,包含WECHAT_PAY、ALIPAY、CASH三种方式。在SettlementController中,选择微信支付会跳转至模拟支付页面(含假的支付成功回调),这是为答辩演示准备的——你不需要真的接入微信支付,但能展示完整的支付流程闭环。
3.4 员工排班与健康记录:让兽医工作有迹可循
排班不是简单的“张三周一至周五”,而是结合宠物健康需求的智能调度:
- 排班表(schedule)设计:
表结构包含staff_id、date、shift_type(MORNING/AFTERNOON/FULL_DAY)、duty_type(RECEPTION/VET_CHECK/CLEANING)。关键约束是: - 同一日期同一班次,
VET_CHECK岗位最多安排2名兽医(避免资源浪费); -
兽医连续值班不超过3天(符合劳动法规模拟)。
-
健康记录(health_record)的强关联:
每条记录必须关联: boarding_order_id(哪个订单下的检查);pet_id(哪只宠物);staff_id(哪位兽医操作);check_time(精确到分钟,用于判断是否按时);vital_signs(JSON存储体温、心率、呼吸频率)。
在HealthRecordController中,提交记录时会校验:java // 确保同一只宠物24小时内至少有一次检查 long recentCount = healthRecordService.countByPetAndTimeRange( record.getPetId(), LocalDateTime.now().minusDays(1) ); if (recentCount == 0) { throw new BusinessException("该宠物过去24小时无健康检查记录,请立即补录!"); }
这种设计让系统成为兽医工作的数字助手,而非负担。
4. 实操过程与核心环节实现:从零开始跑通项目的完整路径
4.1 环境准备与项目导入:避开90%新手的坑
本地运行前,请严格按以下顺序操作,跳过任何一步都可能导致启动失败:
-
安装JDK 8u202(推荐):
- 下载地址:Oracle官网历史版本(搜索“JDK 8u202”);
- 验证:java -version输出应为java version "1.8.0_202";注意:不要用OpenJDK 11+,SpringBoot 2.7.x对JDK 11的某些反射API有兼容性问题,曾导致
@ConfigurationProperties绑定失败。 -
安装MySQL 5.7.32(推荐):
- 下载MySQL Community Server 5.7.32;
- 初始化密码:安装向导中设置root密码为123456(与application.yml中配置一致);
- 创建数据库:CREATE DATABASE cyjy DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; -
导入数据库脚本:
- 打开MySQL命令行:mysql -u root -p,输入密码123456;
- 执行:USE cyjy; SOURCE /path/to/cyjy.sql;;关键检查:执行后运行
SELECT COUNT(*) FROM sys_user;,应返回3(管理员、前台、兽医各1个);运行SELECT * FROM room WHERE status = 'AVAILABLE';,应看到至少5间可用房间。 -
IDEA导入项目:
- 打开IDEA,选择File → Open → 选择项目根目录;
- 弹窗提示“Import project from external model”,选择Maven;
- 等待Maven自动下载依赖(约5分钟),重点观察pom.xml中spring-boot-starter-thymeleaf和mybatis-spring-boot-starter是否解析成功;常见错误:若出现
Cannot resolve symbol 'ThymeleafAutoConfiguration',说明Maven仓库未刷新,在IDEA右侧Maven面板点击Reload project图标。
4.2 启动与首次登录:验证核心流程
项目导入成功后,按以下步骤启动:
-
配置数据库连接:
- 打开src/main/resources/application.yml;
- 确认spring.datasource.url为jdbc:mysql://localhost:3306/cyjy?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai;
- 确认spring.datasource.username和password为root和123456。 -
启动应用:
- 在IDEA中找到CyjyApplication.java,右键Run 'CyjyApplication';
- 观察控制台日志:- 出现
Started CyjyApplication in X.XXX seconds表示启动成功; - 若出现
Failed to configure a DataSource,说明数据库连接失败,请检查MySQL是否运行、用户名密码是否正确; - 若出现
Field xxx in com.cyjy.service.impl.XxxServiceImpl required a bean of type 'xxx' that could not be found,说明MyBatis Mapper扫描路径错误,检查@MapperScan("com.cyjy.mapper")是否在启动类上。
- 出现
-
首次访问与登录:
- 浏览器打开http://localhost:8080;
- 使用预置账号登录:
| 角色 | 账号 | 密码 | 可见菜单 |
|—|—|—|—|
| 管理员 |admin|123456| 全部菜单 |
| 前台 |frontdesk|123456| 订单、宠物、主人、房间 |
| 兽医 |vet|123456| 健康记录、宠物、订单(只读) |实操心得:登录后,立即点击右上角“个人资料”→“修改密码”,将密码改为更安全的组合。这是答辩时体现安全意识的加分项。
4.3 核心业务演示:15分钟走通全流程
以“前台接待员”身份,用15分钟完成一次真实寄养服务演示:
-
录入新主人与宠物(3分钟):
- 点击【主人管理】→【新增主人】,填写姓名“王建国”、电话“13800138000”、紧急联系人“王小明(儿子)”;
- 点击【宠物管理】→【新增宠物】,选择主人“王建国”,填写名字“旺财”、品种“金毛”、生日“2022-03-15”、疫苗状态“已接种狂犬病疫苗(有效期至2025-03-15)”;注意:提交后,系统自动在
owner表插入一行,在pet表插入一行,并建立外键关联。 -
创建寄养订单(5分钟):
- 点击【订单管理】→【新增订单】;
- 选择宠物“旺财”,选择主人“王建国”,设置入住日期“2024-05-20”,离店日期“2024-05-25”(共5天);
- 系统自动分配房间(如“豪华单间001”),并显示预估费用“¥1250”(5天×¥200/天 + ¥250豪华房附加费);
- 点击【提交】,订单状态变为PENDING_PAYMENT;关键验证:打开MySQL命令行,执行
SELECT * FROM boarding_order WHERE pet_id = (SELECT id FROM pet WHERE name = '旺财');,确认订单已创建,status字段为PENDING_PAYMENT。 -
模拟支付与入住(4分钟):
- 在订单列表找到该订单,点击【支付】,选择“微信支付”,跳转至模拟支付页;
- 点击【支付成功】,订单状态变为CONFIRMED;
- 点击【办理入住】,选择入住时间“2024-05-20 09:30”,系统校验疫苗有效后,状态变为CHECKED_IN,并自动生成首条健康记录;此时,房间状态已更新为
OCCUPIED,可在【房间管理】中验证。 -
兽医日常检查(3分钟):
- 切换账号为vet/123456;
- 进入【健康记录】→【新增记录】,选择订单“BO20240520001”,填写体温“38.5℃”、精神状态“活泼”、饮食情况“正常”;
- 提交后,该记录出现在订单详情页的“健康记录”标签页中。
整个流程走通后,你已掌握了系统90%的核心能力。答辩时,这段演示就是你最硬核的成果展示。
5. 常见问题与排查技巧实录:那些文档里不会写的救命指南
5.1 启动失败类问题速查表
| 现象 | 可能原因 | 排查命令/操作 | 解决方案 |
|---|---|---|---|
控制台报java.lang.ClassNotFoundException: javax.servlet.Filter |
JDK版本过高(如JDK 11+) | java -version |
降级至JDK 8u202,或在pom.xml中添加<dependency><groupId>javax.servlet</groupId><artifactId>javax.servlet-api</artifactId><version>4.0.1</version><scope>provided</scope></dependency> |
启动时报Access denied for user 'root'@'localhost' |
MySQL密码错误或用户权限不足 | mysql -u root -p,输入密码测试 |
重置root密码:ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY '123456'; FLUSH PRIVILEGES; |
| 页面显示404,但控制台无报错 | Thymeleaf模板路径错误 | 检查src/main/resources/templates/下是否有index.html |
确保HTML文件放在templates目录下,且文件名与@Controller中return "index";的字符串完全一致(区分大小写) |
| 登录后菜单栏空白 | 权限数据未加载 | 查看控制台是否打印Loaded 3 roles and 12 menus |
执行cyjy.sql中的INSERT INTO sys_role_menu...语句,或重启应用(首次启动会自动初始化权限) |
5.2 业务逻辑类问题与独家避坑技巧
-
问题:订单状态无法从
CHECKED_IN变为IN_PROGRESS
原因:定时任务未启用。系统依赖@Scheduled(cron = "0 0 0 * * ?")每天凌晨执行健康检查提醒,但默认关闭。
解决:打开application.yml,将spring.task.scheduling.enabled: true取消注释;或在CyjyApplication类上添加@EnableScheduling注解。 -
问题:微信支付模拟页点击“支付成功”后,订单状态仍是
CONFIRMED
原因:支付回调URL未正确配置。模拟支付页提交的是POST /api/payment/callback,但控制器方法缺少@PostMapping。
解决:检查PaymentController.callback()方法,确保有@PostMapping("/callback")注解,且方法内调用orderService.confirmPayment(orderId)更新状态。 -
问题:导出PDF收据时中文乱码
原因:iText 7默认字体不支持中文。
解决:在ReceiptGenerator.java中,替换字体为思源黑体:java PdfFont font = PdfFontFactory.createFont("src/main/resources/fonts/NotoSansCJKsc-Regular.otf", PdfEncodings.IDENTITY_H); -
独家避坑技巧:答辩演示防翻车三板斧
1. 预演“断网”场景:提前拔掉网线,演示离线状态下查看历史订单、打印收据(所有数据已缓存至本地Session);
2. 准备“故障注入”话术:若演示中真遇到Bug,不要慌,笑着说:“这个异常恰好体现了我们系统的健壮性设计——您看,它没有崩溃,而是给出了清晰的业务提示‘宠物疫苗未在有效期内’,这正是我们强调的用户体验优先原则”;
3. 备份截图包:将1.png至15.png重命名为01_登录页.png至15_结算页.png,按序号放入PPT,答辩时可快速定位对应界面。
5.3 性能与扩展性优化建议(进阶参考)
虽然毕设不要求高并发,但若你想让项目脱颖而出,可补充以下轻量级优化:
-
数据库层面:为高频查询字段添加索引。例如,在
boarding_order表上执行:sql ALTER TABLE boarding_order ADD INDEX idx_pet_status (pet_id, status); ALTER TABLE health_record ADD INDEX idx_pet_date (pet_id, check_time);
这能让“查询某宠物所有健康记录”的SQL从全表扫描变为索引查找。 -
代码层面:对重复计算做缓存。例如,
PetService.getVaccinationStatus(petId)方法,可添加@Cacheable(value = "vaccinationStatus", key = "#petId")注解,避免每次健康检查都查一遍疫苗表。 -
前端层面:为长列表添加分页。当前
OrderController.list()方法已集成PageHelper,只需在Thymeleaf模板中添加分页导航:
```html- «
- »
```
这种优化不增加复杂度,却体现了工程素养。
6. 毕设答辩与课程设计应用指南:如何把代码转化为得分亮点
6.1 答辩PPT结构设计:用业务语言讲技术故事
别再用“第一章:绪论,第二章:需求分析…”这种教科书结构。我的建议是按宠物店一天的真实工作流组织PPT:
- 封面页:标题+你的名字+一句slogan,如“让每一只寄养的宠物,都被系统温柔以待”;
- 第1页:老板的痛点(不是技术需求):
“王老板的宠物店每天接到20+咨询电话,但30%的客户因‘不知道房间是否空闲’而流失;兽医手写健康记录,月底统计时发现3只猫的驱虫时间被漏记…”; - 第2页:我们的解决方案(对应系统截图):
左侧放10.png(房间状态看板),右侧放7.png(健康记录电子表单),标注“实时可视化的房间占用率”、“自动提醒驱虫周期”; - 第3页:技术如何支撑业务(核心代码片段):
展示RoomService.allocateRoom()方法,用红框标出SELECT ... WHERE status = 'AVAILABLE',旁边配文“用一行SQL,解决老板最头疼的‘房间空闲’问题”; - 第4页:我们做得不一样的地方(对比竞品):
制作对比表格,突出“状态机驱动订单流转”、“疫苗过期自动预警”、“电子收据带二维码”等独特点; - 封底页:致谢+一句真诚的话,如“感谢导师指导,也感谢王老板允许我们用他的店做原型验证”。
6.2 源码解读话术:把技术细节翻译成业务价值
答辩时,老师问“你用MyBatis的XML写SQL,和JPA比有什么好处?”,不要回答“因为JPA学习成本高”,而要说:
“老师,这个问题特别好。上周我去宠物店实地调研,发现兽医最常问的问题是‘近7天哪些狗有皮肤病史?’。用JPA写这个查询,要在实体类里加一堆
@OneToMany、@Where注解,一旦写错,运行时才报错。而MyBatis的XML里,我直接写:sql SELECT DISTINCT p.* FROM pet p JOIN health_record h ON p.id = h.pet_id WHERE h.symptom LIKE '%皮疹%' AND h.check_time >= DATE_SUB(NOW(), INTERVAL 7 DAY)
这条SQL,我能在MySQL命令行里直接测试,确保结果准确后再粘贴到XML里。对毕设来说,能快速验证、快速交付的方案,就是最好的方案。”
6.3 课程设计延伸方向:让项目持续生长
如果你用这个项目做课程设计,可以基于现有框架做增量开发,难度适中且价值明确:
- 增加微信小程序前端:用现有SpringBoot后端提供REST API(
/api/order/create,/api/pet/list),前端用uni-app开发,实现主人手机端预约、查看健康记录; - 集成短信通知:调用阿里云短信SDK,在订单状态变更时自动发送短信(如“您的爱宠旺财将于明日离店,请查收收据”);
- 添加数据看板:用ECharts在管理员首页绘制“月度营收趋势图”、“各房型入住率饼图”,SQL直接复用
cyjy.sql中的视图。
这些延伸不是为了炫技,而是让系统真正融入宠物店的数字化运营——这正是计算机专业学生该有的产品思维。
我个人在实际带毕设的过程中发现,最打动导师的,从来不是代码有多炫,而是你能否说清楚:这个功能,解决了谁的什么具体问题? 当你能指着cyjy.sql里的一条INSERT INTO room VALUES ('001', '豪华单间', 'DELUXE', 'AVAILABLE')说:“王老板告诉我,他最怕客人打电话问‘还有没有豪华单间’,所以我在房间表里加了room_type和status字段,让前台一键就能查到答案”,你就已经赢了。这套源码的价值,不在于它用了多少新技术,而在于它把宠物寄养这件小事,用程序员的方式,扎扎实实做对了。
简介:一套开箱即用的宠物寄养管理实战项目,基于SpringBoot 2.x搭建,后端整合MyBatis、MySQL、Lombok,前端采用Thymeleaf模板引擎配合Bootstrap响应式布局。系统支持宠物信息录入、主人档案维护、寄养订单全流程管理(含预约、入住、离店、收费结算)、员工排班安排、寄养状态实时跟踪、出入库记录等核心业务功能。权限体系覆盖管理员、前台接待、兽医三类角色,实现差异化菜单与数据可见性控制。压缩包内提供完整可编译源码(src目录结构清晰)、MySQL建表及初始化脚本(cyjy.sql)、Maven构建配置(pom.xml)、跨平台启动脚本(mvnw/mvnw.cmd)、图文并茂的Word版使用手册(含环境准备、导入步骤、登录账号说明),以及15张关键界面截图(从登录页到订单结算页全覆盖)。本地只需安装JDK 8+、MySQL 5.7+和IDEA或Eclipse,按手册操作即可快速运行,适用于本科毕业设计、Java Web课程实践或SpringBoot入门项目参考。
更多推荐


所有评论(0)