ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

基于Spring Boot的宠物咖啡馆平台:设计实现与毕设全攻略

基于Spring Boot的宠物咖啡馆平台:设计实现与毕设全攻略 直接开工。打开电脑对照着论文大纲和源码目录把“基于Spring Boot的宠物咖啡馆平台”这个毕设项目从头到尾捋了一遍。这个选题在近两年毕业设计里属于典型的“小而美”技术栈主流、业务场景清晰、功能边界合理不像电商系统那么卷又比简单的博客系统更有区分度。核心要解决的是这么一件事宠物咖啡馆的日常运营既包含普通咖啡馆的堂食点单、商品管理逻辑又叠加了宠物专属的预约到店、宠物档案、寄养服务等功能需要一个统一的线上平台来承接让用户能预约、能下单、能查看宠物动态让管理员能管商品、管预约、管会员。这篇就围绕这个项目的设计思路、表结构、核心代码实现、论文写法以及答辩高频问题做一个完整拆解顺带把源码里容易踩的坑一并说清楚给正在做类似选题、尤其是选了Spring Boot全家桶路线的同学一份可以直接参考的实操笔记。1. 项目整体设计与需求拆解1.1 先搞清楚这个平台到底在解决什么问题宠物咖啡馆和普通咖啡馆最大的区别在于它除了卖咖啡和甜点还提供跟宠物相关的服务。常见的场景包括主人带着宠物到店消费店里需要记录宠物信息品种、年龄、性格、是否绝育、疫苗情况有些宠物咖啡馆会设置独立的宠物活动区需要预约限定名额避免过多宠物聚集还有一部分店提供宠物寄养、宠物零食售卖、宠物洗护等服务。这些场景落到系统里就演变成几个核心模块用户端需要在微信小程序或者网页上完成注册登录、浏览商品、预约到店、下单购买、查看宠物信息、提交寄养申请管理员端需要处理商品上下架、订单发货/核销、预约审核、寄养记录管理、会员积分管理、数据统计。这样一个平台本质上就是“商城预约会员”的三合一系统只不过业务对象从纯粹的人变成了“人宠物”。从毕设的角度看Spring Boot天然适合做这种系统的后端因为它把SSM时代繁琐的配置简化到了极致内置Tomcat、自动配置、起步依赖开发效率很高。再加上MyBatis Plus作为持久层框架连基本的CRUD都能自动生成省下的时间可以全部投入业务逻辑的设计。前端可以选择Thymeleaf服务端渲染也可以选择VueElement UI做前后端分离甚至一些同学直接改造开源模板把管理后台和用户端分开实现。这一套组合既不会因为技术太偏门导致工作量堆不上去也不会因为技术太老被答辩老师质疑。1.2 角色权限与功能边界划分系统设计上标准做法是划分为三种角色普通用户、商家/管理员、系统超级管理员。如果做前后端分离用户的访问入口是H5/小程序端管理员的访问入口是Web管理端两套界面在功能上天然隔离。用户端功能清单通常包含注册登录、个人资料维护、宠物档案管理添加/编辑多只宠物、咖啡馆商品浏览/检索/详情、购物车、提交订单、在线支付模拟支付即可、预约到店选择日期时间段、填写宠物数量、查看预约记录、寄养服务申请、我的收藏、积分查询与兑换。管理端功能清单包含仪表盘统计今日订单量、预约数、商品销售额、会员增长、商品管理分类维护、商品上下架、库存调整、轮播图配置、订单管理订单列表、发货/核销、退款处理、预约管理排期设置、审核通过/拒绝、到店核销、寄养管理寄养登记、状态流转、会员管理会员列表、积分调整、宠物档案管理查看全店宠物档案、系统设置管理员账号、基础参数配置。这里有必要强调一点不要把用户端和管理端的功能做成对称的。很多同学的项目里用户能用的功能管理员也全都有界面塞得满满的答辩时反而说不清楚每个功能的使用场景。合理的做法是管理端只保留运营必须的操作入口用户端只保留顾客视角的购物与服务入口两个端在服务层可以复用但接口和页面必须解耦。1.3 技术栈选型与版本搭配参考如果是自己从零搭建项目推荐一套相对稳妥的组合后端Spring Boot 2.7.x对应JDK 1.8或Spring Boot 3.x对应JDK 17建议优先2.7因为网上资料和插件兼容性最好持久层MyBatis Plus 3.5.x自带分页插件、乐观锁插件、逻辑删除减少大量样板代码数据库MySQL 5.7或8.0字符集utf8mb4权限认证Spring Security JWT或者直接用拦截器Redis会话管理考虑到毕设体量JWT方案更轻接口文档Knife4j或Swagger集成方便答辩时展示接口测试前端用户端Vue 2 Element UI Axios或者ViteVue 3 Element Plus前端管理端vue-element-admin模板精简改造或者直接用若依等开源脚手架但用脚手架时一定要能说清楚每张表、每个接口是自己设计的不能只说“我改了一下”部署单机Docker Compose打包MySQL 后端Jar 前端Nginx镜像这里专门提一下如果论文里只写“基于Spring Boot”技术深度略单薄。建议在技术方案部分加入Redis缓存热点数据比如商品详情、轮播图、RabbitMQ如果涉及寄养到期通知、订单超时关闭或者Elasticsearch商品搜索作为亮点。哪怕只是简单整合也能在答辩时展示你有一定的系统设计思维。2. 数据库设计与核心表结构解析2.1 核心表清单与字段设计思路整个系统的表数量控制在14到18张之间比较合适太少体现不了业务复杂度太多会把自己累死。核心表大致如下用户表字段建议id、nickname、phone、password、avatar、gender、balance、points积分、status、create_time、update_time、deleted。余额和积分直接冗余在用户表里日常查询效率高不需要每次关联计算。积分流水单独建表方便追溯。宠物表id、user_id所属用户、pet_name、pet_type猫/狗/其他、breed品种、age、weight、gender公/母、is_neutered是否绝育、vaccine_status疫苗情况、personality性格描述、remark。这里要注意宠物表逻辑上挂在用户下但管理员也应该能查看全店宠物档案所以查询接口不能只按user_id过滤要提供一个管理端视角的全量列表接口。商品分类表和商品表分类表id、category_name、sort。商品表id、category_id、name、description、cover_image、detail_images、price、original_price、stock、sales、is_shelved是否上架、is_recommend是否推荐、create_time。平价商品、实则价格字段统一用BigDecimal避免浮点丢失精度。购物车表id、user_id、product_id、quantity、checked。合并商品项的逻辑要处理同一用户同一商品重复加入时直接在原记录上累加数量。订单表与订单明细表订单表id、order_no唯一订单号、user_id、total_amount、pay_amount、payment_method、status待支付/已支付/已发货/已完成/已取消、refund_status、remark、consignee_name、consignee_phone、consignee_address、pay_time、deliver_time、finish_time。订单明细表id、order_id、product_id、product_name、product_image、product_price、quantity、subtotal。订单明细冗余商品快照名称、图片、价格非常重要因为商品信息后续会变动但订单里必须保留下单那一刻的真实数据。预约表id、user_id、appointment_date预约日期、appointment_time时间段比如上午/下午/晚场、pet_ids逗号分隔、person_count、contact_phone、status待审核/已通过/已拒绝/已到店/已取消、response_note管理员审核备注、create_time。宠物可以是多只直接用逗号分隔存储或者单独建一张预约宠物关联表前者更简单后者更规范。建议用后者的同学把关联表建出来不算复杂还能在论文里加一个“多对多关系设计”的讨论点。寄养表id、user_id、pet_id、start_date、end_date、fee、status待接收/寄养中/已接走/已取消、care_note照料备注、剩余天数这个字段可以用定时任务计算也可以在查询时按结束日期动态计算。轮播图表id、image_url、redirect_url、sort、status。商品首页的装修元素加上这个表用户端页面会显得完整很多。积分流水表id、user_id、change_type获得/消费、change_points、description、create_time。积分获取规则可以是“实付金额1元1积分”消费规则是“100积分抵1元”。系统管理员表、操作日志表、反馈建议表根据情况取舍。操作日志表能增加系统完整性但如果是纯手动开发的毕设可以在论文里以“预留接口”的方式提及不必强求。2.2 关键设计为什么不建议把预约和订单做成一张表许多第一次做这类系统的同学会直觉地把“预约到店”和“购买商品”合并到一个订单模型里因为都是用户发起的一个“交易动作”。但这种设计在业务逻辑上很别扭预约关注的是“某个日期某个时段店内是否有空闲接待能力”购买商品关注的是“商品库存与金额结算”两者的核心判断条件完全不同。预约表要单独做“排期冲突检测”。比如用户选择周六下午到店系统需要判断该时间段是否已被约满这个规则可能来自管理员在后台设置的每日接待总量也可能来自一个硬性配置比如单日最多接待20只宠物。而商品订单的核心约束是库存扣减在秒杀/高并发场景下会用到Redis缓存库存在毕设场景下用数据库乐观锁控制就够了。所以订单表管“人货交易”预约表管“到店服务”两个模块可以各自演进也可以在店铺核销环节产生一次联动——预约到店后用户可以现场扫码点单订单状态流转为已完成预约状态流转为已到店。这是论文中一个很值得展开的业务闭环。2.3 导入一键建库SQL的注意事项大多数同学下载的源码会附带一个pet_cafe.sql直接导入数据库就能跑。倒入时注意MySQL版本兼容性如果SQL里有ENGINEInnoDB DEFAULT CHARSETutf8mb4 COLLATEutf8mb4_general_ci这样的字段MySQL 8.0默认就是对的如果是utf8mb4_unicode_ci在5.7上要确认字符集排序规则存在。导入全量脚本后重点检查三件事一是id是否都是雪花ID或自增主键有没有因为导入顺序导致外键约束失败二是各表的初始数据里有没有预设管理员账号一般是admin/123456密码如果是BCrypt加密的不要手动改数据库先登录旧账号再在管理端改密码三是优惠券、积分、轮播图等业务表里是否有空的JSON字段空值和NULL值在MyBatis Plus映射时要区分否则前端渲染locally会报错。3. 核心业务逻辑实现与实操重点3.1 登录鉴权JWT拦截器还是Spring Security如果是前后端分离架构推荐用JWT配合拦截器实现登录状态管理不引入Spring Security。原因很直接Spring Security的过滤器链复杂概念多在答辩时如果讲不清楚“为什么需要它”极易被追问到细节然后卡壳。JWT方案自己写一个拦截器步骤清晰好讲。实现思路用户登录成功后后端生成一个token里面带上userId和角色标识设置合理过期时间。前端每次请求在axios请求拦截器里把token放到Header的Authorization字段。后端定义一个WebMvcConfigurer注册拦截器拦截需要登录的接口路径解析token把用户信息放入ThreadLocal或请求上下文。管理端接口额外校验角色必须是ADMIN角色判断用自定义注解比如RequireRole(ADMIN)AOP或者拦截器里读取方法上的注解做鉴权。这里有三个细节值得注意密码存储是BCrypt加密不要明文入库。MyBatis Plus的BaseMapper提供selectOne配合LambdaQueryWrapper就能按用户名查出来然后用BCryptPasswordEncoder.matches(rawPassword, encodedPassword)校验。Token刷新机制可以不写但JWT的过期时间要设置合理比如24小时。如果答辩老师问“过期了怎么办”可以回答“后续可扩展刷新Token能力”或者“对某些低频管理端接口用Redis存储Token并滑动续期”。ThreadLocal存储用户信息后接口返回结束前一定要remove否则Tomcat线程池复用线程时可能串数据。3.2 宠物档案管理一对多关系的增删改查宠物档案是宠物咖啡馆平台的特色功能也是区分普通商城系统的关键点。用户登录后可以新增宠物字段里比较有意思的是性格温顺、活泼、怕生、是否绝育、疫苗接种情况。这些字段在后面预约审核时会被管理员用来判断宠物能否与其他宠物合群相处。新增宠物时user_id从当前登录用户上下文取不允许前端传入。修改宠物时按照id和user_id同时做条件过滤防止“越权修改他人宠物”。这里可以用LambdaUpdateWrapper比如petService.update(new LambdaUpdateWrapperPet() .set(Pet::getPetName, petName) .set(Pet::getBreed, breed) .eq(Pet::getId, petId) .eq(Pet::getUserId, currentUserId));删除宠物建议用逻辑删除即MyBatis Plus的TableLogic注解在表里加deleted字段。这样即使误删也能从数据库恢复。注意逻辑删除配置后MyBatis Plus的自动CRUD都会带上deleted0条件但自定义SQL不受保护如果在XML里写了连表查询记得手动加条件。3.3 商品订单拆解从购物车到支付成功的完整状态流商品订单的状态流转是项目里最复杂的一条线。合理的状态定义为待支付状态0用户提交订单后未支付。正常流程是跳转支付页面模拟支付接口直接返回成功。如果做了超时关闭功能可以在下单时把订单号写入Redis并设置10分钟过期Redis过期时回调关闭订单。但在毕设里更简单的做法是定时任务每1分钟扫描一次待支付订单对比创建时间超过15分钟则自动取消并释放库存。已支付状态1模拟支付回调里更新订单状态同时扣减库存。库存扣减有两种做法下单时预扣库存或者支付成功后扣减库存。预扣库存的体验更好超时取消时返还库存但逻辑更复杂支付后扣库存的实现简单但可能出现支付成功但库存不足的极端情况。建议选择下单时锁定库存、取消时释放库存的方案虽然代码多几行在答辩时可说“采用了预扣库存模式防止用户下单后抢不到货”。已发货状态2/配货完成虚拟商品不用物流可以用“核销码”代替发货。系统在支付成功时生成一个核销码用户在店内出示店员输入核销码完成核销订单状态变为已完成。核销码在订单表里增加一个verify_code字段核销接口必须校验订单是已支付状态防止重复核销。已完成状态3核销完成用户可在该订单上点“确认收货”或系统自动完成。已取消状态4用户主动取消仅限未支付订单超时自动取消。已退款状态5已支付订单可发起退款申请管理员审核通过后退款到余额并扣减积分。这个状态机在论文里值得画一张状态流转图用文字表格描述即可每个状态对应的用户操作、管理员操作各是什么逻辑闭环答辩效果很好。3.4 预约排期冲突检测如何判断某个时间段是否已满预约到店的核心算法是“容量校验”。管理员在后台配置每天每个时间段的最大接待人数或宠物数比如上午10:00-12:00最多同时接待3只宠物。用户提交预约时后端先查当前时间段已通过和已到店的预约记录统计宠物数量加上本次预约的宠物数量如果超过上限就拒绝预约。统计SQL用MyBatis Plus的QueryWrapperapply做也行直接写LambdaQueryWrapper配合selectOne的sum聚合也可以或者直接在Service层循环查出来在代码里累加。考虑到预约表数据量不大直接在代码里累加更直观ListOrder appointments appointmentService.list(new LambdaQueryWrapperAppointment() .eq(Appointment::getAppointmentDate, date) .eq(Appointment::getAppointmentTime, time) .in(Appointment::getStatus, Arrays.asList(1, 2))); // 已通过已到店 int petCount appointments.stream().mapToInt(item - item.getPetIds().split(,).length).sum(); if (petCount currentPetCount capacity) { throw new BizException(该时间段预约已满请选择其他时段); }这里需要提供一个配置表来管理“每日容量”、“每个时段容量”不要写死。可以把容量配置放在系统设置表里用key-value结构存比如key为appointment_capacityvalue为JSON字符串包含多个时间段。管理员在前端改配置后端读取配置后做校验这样的设计比写死参数更有说服力。另外还有一个小细节预约审核状态。有些咖啡馆是“即约即得”有些是“需要管理员二次确认”。论文里建议做成需要管理员审核的流程因为这样管理端就有了一个核心工作台也方便展示“待办事项”概念。用户提交预约后状态为待审核管理员在预约管理页点击通过系统给用户推送状态通知如果没有消息模块可以免去只在前端页面展示状态变化。3.5 积分与会员体系的挂载方式会员积分不必单独设计一套复杂的等级体系做成“积分累计积分抵扣”即可。用户每次完成订单按实付金额增加积分比如1元1分退款时扣回积分。积分的增减通过积分流水表记录用户积分余额等于流水表归总和。积分抵扣功能挂在订单确认页用户输入要抵扣的积分数量按100积分1元换算抵扣金额不能超过订单实付金额。后端接收的抵扣积分先做一个校验用户当前积分是否足够抵扣比例是否在允许范围内。生成订单时实际支付金额商品总金额-积分抵扣金额。这里有一个容易踩的坑积分抵扣产生的“负金额”异常。假设订单金额为5元用户用600积分抵扣折合6元那么支付金额就是-1元。这显然不合理所以业务的边界条件要写清楚抵扣积分不能使支付金额为0或负数最低支付金额为0.01元或者限定抵扣上限为订单金额的50%。3.6 管理端数据统计简单的SQL聚合即可出报表仪表盘统计用的基本都是GROUP BY和聚合函数不需要引入独立的大数据组件。四个核心指标可以直接查今日订单量订单表按创建时间和状态过滤、今日销售额SUM支付金额、今日预约数预约表按日期过滤、累计会员数用户表数量。图表类统计可以用一周或者一个月的趋势表按日期做GROUP BY。比如近7日销售额SELECT DATE(pay_time) AS day, SUM(pay_amount) AS total FROM orders WHERE status 1 AND pay_time DATE_SUB(CURDATE(), INTERVAL 7 DAY) GROUP BY DATE(pay_time)如果前端用ECharts展示后端接口返回一个日期数组和一个金额数组即可这个接口的实现难度很低但是视觉效果很好对论文的“系统功能实现”章节很有帮助。4. 论文怎么写才能拉开差距4.1 论文大纲推荐结构一篇合格的毕设论文不需要惊天动地的创新点但结构必须完整、逻辑要顺。推荐章节安排绪论研究背景与意义写宠物经济、咖啡馆业态升级、数字化运营的趋势引用两三篇行业报告即可。国内研究现状写“现有的宠物管理系统侧重于宠物医院或临时救助中心缺少咖啡馆场景的线上预约商城一体化方案”国外研究现状写“宠物咖啡馆在日韩和欧美发展较早配套的SaaS系统相对成熟但在本地化场景中仍有定制需求”这是万能杠杠。相关技术介绍Spring Boot、MyBatis Plus、MySQL、JWT、Vue。没必要长篇大论每个点写清楚“选型理由核心特性在系统里用在哪儿”即可。系统分析可行性分析技术可行性、经济可行性、操作可行性、需求分析功能需求、非功能需求、用例分析。用例图用PlantUML或者Draw.io画好不需要多精美但角色和动作要一一对应。系统设计总体架构图前后端分离架构、功能模块设计、数据库设计E-R图核心表字段解释、接口设计。E-R图注意表与表之间的关系连线要正确一对一、一对多、多对多标清楚。系统实现按功能模块写每个模块截图核心代码代码说明。代码不要大段贴贴的是核心业务逻辑。系统测试功能测试用例表部分测试结果截图性能测试可以简单写用JMeter进行接口压测展示TPS和响应时间。答辩老师一般不会追问性能细节但测试章节有截图确实会显得工作量大。总结与展望写自己在系统开发过程中解决了哪些问题还有哪些可以优化的地方比如引入区块链存证、AI识别宠物健康、消息推送提醒等点到为止。4.2 论文中的图、表、代码三大件论文不等于代码堆砌排版、配图和表单至关重要。图表质量直接决定答辩老师的第一印象。功能结构图用带层次的树状图系统架构图用分层架构前端Ubuntu层、网关层、业务层、数据层、基础设施层流程图重点画订单状态流转图和预约审核流程图E-R图至少包含用户、宠物、订单、预约、寄养五个核心实体界面截图要全屏截取分辨率清晰不要截图窗口边框和无关标签页。表格设计要做到自解释。非功能需求测试表包括高并发、大数据量、易用性、安全性四个维度功能测试用例表每行包含编号、测试项、操作步骤、输入数据、预期结果、实际结果、是否通过订单状态表字段包含状态名称、状态值、触发动作、前置状态、后置状态。代码块在论文里要用等宽字体中文推荐Courser New宋体英文行号去掉过长代码超过10行要精简为关键片段。核心代码的注释尽量自己写不要让代码贴出来像源码直出。4.3 答辩高频问题与应对Q为什么选择Spring Boot而不是Spring CloudA系统属于单体应用微服务架构会给部署和运维带来不必要的复杂度Spring Boot单体能快速交付且在数据一致性上更简单可靠。QMyBatis Plus和MyBatis有什么区别AMyBatis Plus在MyBatis之上扩展了通用Mapper、条件构造器、分页插件、逻辑删除、代码生成器减少了大量XML配置和重复CRUD代码。可结合项目里的LambdaQueryWrapper举例。Q怎么解决Token过期A前端拦截到401跳转登录页重新登录后端JWT设置了合理过期时间后续可扩展双Token方案RefreshToken刷新AccessToken降低用户频繁登录的感知。Q如果一个商品同时被多人下单库存怎么保证不超卖A采用了数据库乐观锁更新库存时用Update里的stock作为条件影响行数为0则重试。也描述了Redis预扣库存的思路说明自己理解并发的本质。Q预约和订单、用户和宠物之间的关系为什么这么设计A按照业务领域拆分预约服务和订单服务是独立的业务域但通过核销联动用户和宠物是一对多因为一个用户可能携带多只宠物到店这是业务需求的直接映射。5. 常见问题与排查技巧实录5.1 前端接口404/跨域问题前后端分离项目最容易在联调时遇到跨域。如果前端地址是localhost:8081后端是localhost:8080Axios发请求默认会被浏览器拦截。解决方案是在后端定义跨域配置类实现WebMvcConfigurer重写addCorsMappings方法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); } }注意allowCredentials(true)时allowedOriginPatterns不能是“”必须写具体的前端域名或IP否则浏览器会拒绝带Cookie的请求。如果用了JWT而无Cookie可以不用allowCredentials直接把allowedOriginPatterns写“”。接口404的另一个常见原因是Spring Boot的包扫描路径不对。启动类放在com.example.cafe下面所有的Controller、Service、Mapper都要在com.example.cafe下面或子包中否则Bean不会注入。另一个是Swagger路径没允许放行导致所有接口都报401。排查顺序是先看后端控制台有没有Controller的映射日志再确认是否是拦截器放行问题最后看前端请求的baseURL是否写对。5.2 数据库导入与中文乱码数据导入后中文显示乱码的概率非常高。原因一般是SQL文件的字符集与MySQL连接的字符集不一致。建库时统一指定CREATE DATABASE pet_cafe DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;连接字符串写完整jdbc:mysql://localhost:3306/pet_cafe?useUnicodetruecharacterEncodingutf8mb4serverTimezoneAsia/ShanghaiuseSSLfalse。注意characterEncodingutf8mb4在MySQL Connector/J 8.0以上版本可能不识别需要写成characterEncodingUTF-8但数据库必须是utf8mb4。如果已经导入仍未解决用命令行模式执行source指令导入不要用图形化工具复制粘贴后者容易因为转义符和换行符导致乱码或者SQL语法错误。5.3 图片上传存储路径与访问404管理端上传商品图、轮播图是常用功能最容易出现的问题是本地路径访问404。推荐的做法是自定义WebMvcConfigureraddResourceHandlers把文件存储目录映射到虚拟路径Override public void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler(/upload/**) .addResourceLocations(file: uploadPath /); }uploadPath在配置文件里设置比如/home/cafe/uploadLinux环境或者D:/cafe/uploadWindows开发环境。上传接口把文件写入uploadPath返回给前端的访问路径就是http://localhost:8080/upload/xxx.jpg。这样不管是本地调试还是部署到服务器上传文件都能正确访问而不需要依赖Nginx做静态文件映射。有个细节要提醒文件重名问题。用UUID重命名文件后拼接原始扩展名比如String fileName UUID.randomUUID().toString().replace(-, ) . suffix避免用户上传的文件名为中文或含空格导致路径解析异常。5.4 定时任务与预约过期自动关闭如果实现了订单超时关闭Spring Boot的定时任务非常简单在启动类或配置类上加上EnableScheduling然后在业务类上写Scheduled(cron 0 */5 * * * ?) public void autoCloseTimeoutOrders() { // 查出创建时间超过15分钟且状态为待支付的订单 // 更新订单状态为已取消恢复库存 }Cron表达式可以在线工具生成网上很多写之前先校对时区。如果部署到云服务器注意服务器的时间和本地时间有差异最好在系统初始化时统一用Asia/Shanghai时区。5.5 NullPointerException与MyBatis Plus的常见坑最典型的空指针来源有三个一是查出来的实体对象为null但未判空。用LambdaQueryWrapper查询单条记录时如果数据库中没有匹配数据返回null此时调用getXxx()必然空指针。解决方式是Optional包装或者先判断null。二是代码中status字段是Integer前端传字符串“1”JSON反序列化时类型转换失败。用一个全局Jackson配置把空字符串转为null即可。三是积分流水在扣减时未锁记录。两个并发请求同时扣积分可能导致扣除后的积分为负。用自己实现的更新语句时加上条件“积分余额大于等于本次扣除数”。6. 部署环境与上线经验6.1 服务器部署还是要完整过一遍毕设答辩前建议真机部署一次哪怕只是一台1核2G的低配云服务器也能让你在答辩时对部署流程说得头头是道。部署方案服务器装CentOS 7或Ubuntu 20.04安装JDK 1.8、MySQL 5.7、Nginx、Redis。后端用mvn package打成Jar包放到/opt/cafe目录写一个start.sh启动脚本#!/bin/bash nohup java -jar cafe-system.jar --spring.profiles.activeprod cafe.log 21 Nginx配置一个server块监听80端口将/api路径反向代理到后端8080端口将root指向前端文件目录server { listen 80; server_name your-domain.com; location /api/ { proxy_pass http://127.0.0.1:8080/; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } location / { root /opt/cafe/dist; index index.html; } }前端打包时注意把API请求的BASE_URL改成相对路径比如“/api”避免写死localhost这样生产环境才不需要改代码重新打包。6.2 演示数据怎么准备才加分答辩演示时数据一定要丰满。不要拿一个空壳系统演示至少提前准备商品分类4-5个每个分类下3-5个商品用户账号2个每个账号下挂2只宠物一只猫、一只狗预约数据覆盖今天、明天、后三天各有不同状态订单数据至少10条覆盖五个状态积分流水10条。当答辩老师看到仪表盘页面有图表走势、订单列表有历史数据、预约列表有审核进度第一印象就是“系统是真实跑过的”。6.3 源码目录结构规范源码拿到手后先重构包结构不要把所有文件堆在根包下。推荐结构com.example.cafe ├── controller ├── service ├── mapper ├── entity ├── dto ├── vo ├── config ├── common ├── utils └── CafeApplication.java其中config放全局异常处理器、跨域配置、Swagger配置common放统一返回对象、分页结果对象、业务异常类dto接收前端传参vo返回前端展示字段entity对应数据库表。这个结构不复杂但清晰体现了分层思想论文的“系统设计”章节可以直接放一张包结构截图很有说服力。7. 实用小工具与资源推荐一个毕设项目的开发周期通常在3-5周用好工具能节省大量体力。代码生成器是第一步。MyBatis Plus自带的代码生成器能根据数据库表直接生成entity、mapper、service、controller代码生成的代码质量中规中矩在此基础上改成自己的业务逻辑比从零手写快得多。网上有很多一键生成脚本直接用IDEA插件或MybatisX插件即可。数据库设计工具推荐用MySQL Workbench或者Navicat的逆向工程先把表建在数据库里再用工具生成E-R图导出图片直接放入论文比手画方便且规范。接口调试用Postman或ApifoxApifox的好处是能把接口文档、接口调试、Mock数据集合在一个工具里生成的文档可以直接导出为Word或PDF交付论文附录时省去手工整理接口列表的麻烦。前端页面如果不想从vite脚手架白写用户端可以参考H5商城模板管理端推荐vue-element-admin的简化版项目vue-admin-template它自带登录、侧边栏、面包屑、权限指令、404页面在这个基础上改起来很顺手。但务必注意版权问题Vue Element Admin是MIT License可以用保留版权声明就好。8. 写在最后的一些实话这个选题做完下来最大的感受是“麻雀虽小五脏俱全”。宠物咖啡馆平台虽然只是一个毕业设计级别的系统但它覆盖了商城交易、预约排期、档案管理、会员积分、寄养服务、后台统计这么几条业务线已经足够训练一个初学者的全链路开发思维怎么拆需求、怎么设计表、怎么写接口、怎么联调、怎么部署、怎么呈现。如果你现在拿到了源码第一件事不是急着运行而是把数据库脚本打开跟着建表顺序理解每一张表为什么存在、为什么长这样。然后把后端启动起来对照Swagger接口文档把用户端和管理端的每个页面对应到接口上理清楚数据流。最后再动手改代码比如给商品加上促销价格字段、给预约加上短信通知、给订单加上Excel导出。每加一个功能就多了一处能讲的故事。对于正在选毕设题目的同学如果不想跟大家挤破头做商城和论坛系统宠物咖啡馆这个方向性价比非常高。它听起来有差异化实际技术难度适中还自带社交属性演示的时候比普通商城有话题性。当然选定一个题目后动手比纠结重要把基础功能跑通再慢慢迭代细节最后写论文的时候你会发现自己比想象中更熟悉这个系统。如果你在做这个项目的过程中遇到连数据库都导入不了的玄学问题先别急着删了重来把报错信息完整贴到搜索引擎里十有八九是版本或字符集问题这种坑踩一次就记住了。祝顺利答辩拿到好成绩。
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进