宠物领养管理系统全栈实战:从前后端分离到Docker部署完整指南
发布时间:2026/9/7 17:39:09 锦皓数字建站

做前后端项目练手最难的不是某个页面而是怎么把一套完整业务从头到尾串起来。宠物领养管理系统就是一个非常典型的选择它既有宠物档案、用户中心这类常规增删改查又有领养申请、审核状态流转这类带业务流程的功能还能把 AI 能力自然地塞进去比如智能推荐、图片识别、领养文案生成。换句话说当你把这样一个项目完整做出来并部署上线前后端分离、权限控制、文件上传、AI 接口集成、容器化部署这些实际工作里高频出现的点基本都能碰到一遍。适合什么人看我把目标读者切成三类。第一类是刚接触前后端分离的初学者想找一个能完整跑起来、能写进简历的项目第二类是前端想往后端延伸、或者后端想补前端整体认知的开发者第三类是准备做毕业设计或团队内部 Demo 的人。三类读者侧重点不一样但都可以把下面的内容当作一条完整主线先照这个路径跑通再按自己的需求加深。先说明一下宠物领养管理系统的功能和流程不同实现里差别很大。这里讲的是最主流、最适合学习的方案具体版本号和依赖要以你自己的环境为准不要看到一个配置就直接套用。1. 先搞清楚它到底是个“增删改查”还是“业务系统”1.1 宠物领养管理系统的五个核心模块按主流设计这个系统至少需要五个模块。用户与权限模块。系统一般分两类角色普通领养人和管理员。普通用户可以注册、登录、提交领养申请、查看申请进度管理员负责宠物档案维护、领养审核、用户管理和公告发布。这里涉及 JWT 登录、角色权限拦截、用户状态管理不是一个简单的登录页能覆盖的。宠物档案模块。这是信息中心。宠物要有图片、名称、品种、性别、年龄、体型、疫苗情况、绝育情况、性格描述、所在救助站或收容所、当前状态。列表页需要支持分页、关键词搜索、按品种或体型筛选。宠物图片上传是这个模块最容易翻车的地方后面单独讲。领养申请模块。用户看到合适的宠物后提交申请包括个人情况、居住条件、养宠经验、是否有其他宠物等。管理员看到申请后决定通过或拒绝通过后宠物状态要从“待领养”变成“已领养”。这里最要命的不是写接口而是状态判断同一只宠物不能被两个人同时申请成功。公告与消息模块。可以简化成公告列表和已读状态也可以做到站内信提醒用户“你的申请已通过”。如果时间紧这个模块用一张公告表加一个未读字段就能顶住。AI 能力模块。按标题里的 AI 定位常见落地方式是智能推荐、宠物图片识别和领养文案生成。这三项能力可以做成可选功能先跑通再逐步完善。1.2 为什么这个题目能撑起一套完整项目很多人练手项目只做 CRUD做完发现不知道业务逻辑、事务、权限这些知识点该往哪里放。宠物领养系统好就好在它有一条完整的状态链路宠物从入库到被浏览到有人提交申请到管理员审核再到宠物状态变更。每一步都有明确的业务规则都能用代码验证。这个项目同时覆盖了数据库设计、后端接口、前端交互、文件存储、AI 接口对接和部署上线是少见的“一个题目打通全栈”的选择。如果再把并发申请、状态回滚这些边界问题处理好它就不再是学生作业而是一个有真实业务味道的系统。2. 技术选型与项目结构先把组合定下来2.1 前端、后端、数据库怎么选常见的全栈组合有两种我分别说清楚适用情况。第一种是 Spring Boot Vue 3。Java 后端适合想走企业级开发路线的读者招聘需求多社区资料全但环境准备相对重需要 JDK、Maven、IDE 配置。前端用 Vue 3 Element Plus 是当前前后端分离项目里很常见的组合Element Plus 的表格、表单、上传组件能大大减少写页面样式的时间。如果你时间非常紧张也可以考虑直接基于若依这类开源脚手架改但练手阶段我更建议从零搭一遍否则框架帮你做的事你完全没有概念。第二种是 Python FastAPI 或 Flask Vue 3。如果对 Python 更熟或者想快速把 AI 能力接进来用 Python 写后端会顺很多。主流大模型的接口 SDK 几乎都是 Python 优先数据处理和模型推理的示例代码也基本以 Python 为主。缺点是 Python 在后端工程化、部署生态上需要自己多踩一些坑。数据库这块直接用 MySQL 8.x 最稳妥。PostgreSQL 也可以但没有特殊理由不需要在练手阶段引入额外变量。文件存储先用本地磁盘目录别一上来就接对象存储——本地能跑通再换对象存储只改一个存储实现类。2.2 AI 能力接入方式本地模型还是接口调用AI 能力的接入方式决定了项目的复杂度。这个项目没有指定具体模型或厂商所以这一步你可以完全按自己的实际情况选。最省事的是调用成熟的大模型接口用现成的图片分类或通用对话能力实现宠物识别和文案生成。这种方式好处是效果稳定、接入快代价是需要申请接口密钥并且每次调用都有成本和使用限额批量测试时要注意消耗。第二种方式是本地跑模型。宠物品种识别可以用现成的图像分类模型文案生成可以用开源的语言模型。好处是不依赖外部服务、没有接口费用坏处是对硬件有要求。低配置机器上模型加载慢接口响应时间可能长达几十秒前端很容易超时。我的建议是学习阶段优先选接口调用把 AI 模块封装成一个抽象接口这样以后换模型、换服务商都不会影响业务代码。等把整条链路跑通再考虑要不要本地化。2.3 前端目录、后端目录和包结构这里给一个实际可参考的目录划分。前端按页面和组件拆frontend/ src/ api/ // 接口请求封装 router/ // 路由配置 store/ // 登录状态、用户信息 views/ // 页面 components/ // 公共组件后端按模块拆而不是把 controller、service、mapper 全部塞在一起。每个业务模块有自己的 controller、service、mapper 和实体类backend/ src/main/java/ com.example.petadopt/ common/ // 统一返回结果、异常处理 config/ // 跨域、安全、文件上传配置 module/ user/ // 用户与登录 pet/ // 宠物档案 adoption/ // 领养申请 ai/ // AI 接口封装能坚持按模块划分到后面加功能、排查问题都会轻松很多。新人最常见的做法是把所有接口写在一个类里前期看不出问题等做到领养审核和用户中心打通时就会发现改一个字段要搜索所有文件。趁项目小把结构定好。3. 数据库设计与状态流转表和表之间不只是外键关系3.1 核心表设计数据库是这个项目的地基。表设计不对后面每写一个接口都在打补丁。核心表我列一个参考结构字段名用下划线风格前端返回时再处理成驼峰。用户表id、username、password_hash、phone、role、status、created_at。密码绝对不能存明文要存哈希值。role 字段区分普通用户和管理员status 字段处理禁用账号。宠物表id、name、breed、species、gender、age、size、vaccinated、neutered、description、cover_image、status、adopter_id、created_at、updated_at。关键字段是 status它决定宠物能不能被申请领养。adopter_id 可以为空领养成功后写入领养人用户 id。领养申请表id、pet_id、user_id、reason、living_condition、experience、status、admin_remark、created_at、updated_at。注意这张表不要只存一个 pet_id 字符串一定要建立外键或至少建索引否则后面统计“某人申请过多少只宠物”“某只宠物被申请过几次”都会变成全表扫描。公告表和配置表按需加。公告表用于首页展示和高亮通知配置表可以存领养须知、联系方式这类经常变化的文本。3.2 状态机设计才是业务核心状态设计直接决定系统容不容易出 bug。宠物的状态建议只保留三到四种待领养、审核中、已领养再加一个可选的已下架。领养申请的状态则是待审核、已通过、已拒绝、已完成。这里很容易写出的错误是宠物状态只用一个 text 字段想改就 update完全不校验。正确的做法是在后端服务层加状态校验逻辑。比如用户提交领养申请时先查这只宠物当前 status 是否是“待领养”不是就直接返回“这只宠物已被人申请或已被领养”。管理员通过申请时要在一个事务里同时做两件事更新申请状态为已通过更新宠物状态为已领养并写入 adopter_id。两个操作任何一个失败都要回滚否则会出现申请通过但宠物还是待领养的脏数据。在数据库层面领养申请可以给 pet_id 加唯一约束但这只能防止同一个用户重复申请同一只宠物拦不住多个用户同时申请同一只宠物。所以在代码里用事务加条件更新才是最稳的做法。3.3 接口返回结构和错误码约定联调时最烦的就是每个人返回结构不一样。建议后端统一返回格式code、message、data。code 为 0 表示成功非 0 表示业务错误HTTP 状态码只表示请求是否到达服务器。未登录返回 401无权限返回 403参数错误返回 400服务器异常返回 500。把这些约定写在接口文档第一页前后端各自按这个协议开发能省掉大量口头沟通。4. 后端核心模块登录鉴权、宠物档案与领养审核4.1 登录鉴权与角色权限先实现注册和登录。注册时校验用户名是否重复、密码长度、手机号格式密码做哈希存储。登录成功后后端签发一个 JWT token前端存到本地并在每次请求的请求头里带上。后端用一个拦截器或过滤器校验 token并把当前用户信息写入请求上下文。角色权限的常见实现是在 JWT 里带上 role 字段后端写一个权限注解或拦截规则只有 admin 才能操作宠物上下线和领养审核普通用户只能查看、申请和操作自己的数据。这里要特别注意判断“是否自己的数据”时不要用前端传过来的 userId一定要从 token 里解析否则用户可以伪造参数访问别人的记录。4.2 宠物档案接口的设计思路宠物列表接口建议做成带分页和筛选条件的查询参数一般有page、page_size、species、size、keyword、status。返回的列表里宠物图片只返回文件相对路径由前端拼完整地址这样以后换存储方式不用改接口。宠物详情接口返回宠物信息和领养要求AI 生成的性格摘要可以放在 description 字段里。新增和修改宠物只有管理员能操作。图片上传接口建议单独做前端先调上传接口拿到文件路径再随表单一起提交这样比直接把文件转 base64 塞进接口更利于文件处理和错误排查。上传时要限制文件类型和大小建议图片不超过 5MB格式限制为 jpg、png、webp。大图片可以在后端做一次压缩或让前端在上传前压缩否则服务器磁盘很快会被撑满。4.3 领养审核流程的事务与并发处理领养申请接口和审核接口是本项目最值得写进简历的两段逻辑。用户提交申请时后端服务里按这个顺序处理校验用户是否存在且未被禁用校验宠物存在且状态为待领养检查该用户是否已经对这只宠物提交过待审核的申请然后插入申请记录。这里要处理并发场景。如果两个请求同时通过校验就可能让同一只宠物被申请了两次。稳妥的办法是给宠物表的状态做条件更新// 示例提交领养申请的核心逻辑代码结构参考非完整实现 Transactional public Long applyAdoption(Long petId) { // 1. 校验宠物存在且状态为待领养 Pet pet petMapper.selectById(petId); if (pet null || !AVAILABLE.equals(pet.getStatus())) { throw new BizException(该宠物当前不可申请); } // 2. 乐观占位条件更新影响行数为 0说明已被并发占用 int updated petMapper.updateStatusById(petId, AVAILABLE, PENDING); if (updated 0) { throw new BizException(该宠物已被他人申请); } // 3. 插入申请记录 Application app new Application(petId, currentUserId(), PENDING); applicationMapper.insert(app); return app.getId(); }管理员审核时思路类似。通过申请时在一个事务里把申请状态改为已通过、宠物状态改为已领养、宠物 adopter_id 写成当前申请人。拒绝申请时要把宠物状态从“审核中”恢复为“待领养”否则一只被拒绝的宠物永远不能再被申请。这个恢复逻辑经常被漏掉是演示时最容易暴露的问题。注意审核拒绝时宠物状态必须恢复为“待领养”。这个分支被漏掉是领养系统里最经典的一个 bug。5. AI 能力落地推荐、识别和文案生成5.1 智能推荐不要以为一定要上向量数据库领养系统的推荐和电商推荐完全不同。用户量不大、宠物数量也就是几百上千条没必要上向量检索、协同过滤这些重方案。更实用的是标签匹配打分把宠物和用户偏好都打上标签比如品种、体型、性格、可否与小孩相处、能否与其他宠物共存然后用简单规则打分按分数倒序展示前 10 条。具体做法用户填写偏好表单或根据历史申请记录提取偏好后端在宠物列表查询结果上做一次过滤和排序。宠物有性格标签用户有偏好标签匹配一个加一分。这个方案好在逻辑透明、可解释、实现成本低演示时还能很直观地说“因为你选择了适合公寓饲养的中型犬所以把这几只排在了前面”比硬凹一个 AI 推荐更像真实业务。5.2 宠物图片识别与自动填充宠物品种识别是比较适合演示的 AI 功能。用户可以上传一张宠物照片后端调用图像识别接口返回识别出的品种和置信度自动填充宠物档案里的品种字段。这个功能落地时要注意三点。第一识别结果只能作为预填值管理员必须能手动修改因为宠物混血、拍摄角度、光线都会影响识别准确率。第二接口调用是耗时的前端要显示“识别中”状态并且设置合理超时时间而不是让用户干等。第三识别服务不稳定时不能影响用户手动填写档案——AI 只是辅助不能成为阻塞项。5.3 领养文案生成与人工复核领养文案生成是另一个容易做出效果的功能。管理员录入宠物基本信息后点一个“生成领养介绍”按钮AI 根据品种、年龄、性格、救助背景生成一段温暖但不夸张的介绍文案自动填入描述区管理员确认后发布。实现上就是一个接口调用把宠物字段拼成一段提示词调用语言模型接口把返回文本写入 description。难点不在调用而在提示词和输出格式控制。建议在提示词里明确要求输出 100 字以内、自然口语、不含价格信息和领养条件并且在前端设置“重新生成”按钮和人工编辑区。AI 生成内容必须有人工复核环节不要让未审核的文案和识别结果直接对外展示。5.4 AI 模块要留好扩展口不管选哪种 AI 能力代码层面都建议做一层抽象。定义一个 AIService 接口接口里有 recommendPets、recognizePet、generateDescription 三个方法然后写一个 Provider 实现类内部封装具体模型的调用。这样以后从接口调用换成本地模型只改一个实现类业务代码完全不用动。我在实际项目里吃过没有抽象层的亏一开始把某个模型 SDK 直接写在 service 里后来要换方案结果所有业务代码都在改。对练手项目来说多写一个接口多花十分钟后期省的时间是按小时计的。6. 前端页面与联调细节两个角色三种视图6.1 普通用户视角的页面普通用户能看到的主页面至少有四五个首页宠物列表、宠物详情页、领养申请表单、我的申请列表、个人资料。宠物列表页要加筛选器按种类、体型、性别、状态筛选还要支持关键词搜索。卡片上要显示宠物图片、名字、品种和状态标签状态标签颜色要区分待领养是绿色审核中是橙色已领养是灰色。宠物详情页除了基础信息要突出两个区块领养条件和申请按钮。没有登录时点申请按钮要跳到登录页而不是光弹一个“请先登录”的提示。已登录用户如果已经申请过这只宠物按钮要变成“已申请等待审核”并且禁用。这些交互看起来小但演示时特别加分。用户能明显感觉到这个系统是“被设计过”的不是把接口返回数据直接铺到页面上。6.2 管理员视角的页面管理端和用户端建议单独用一套布局路由前缀不一样例如用户端是 /管理端是 /admin。管理端页面包括宠物管理列表、宠物编辑表单、领养申请审核列表、用户列表、公告管理。领养申请审核列表是本系统的核心页面。表格每行要显示申请宠物、申请人、提交时间、理由摘要、状态。点击查看详情弹窗里展示申请人的居住条件、养宠经验、联系方式然后两个按钮通过、拒绝。审核通过前最好再弹一次确认框提醒“通过后宠物状态会变为已领养”。这种确认不是多此一举是防止管理员误点导致宠物被错误占用。6.3 接口联调跨域、字段名和 token前后端联调时最容易出问题的三个点第一是跨域。开发环境前端跑在 5173 端口后端跑在 8080 端口默认会被浏览器的同源策略拦住。解决方案是在后端配置跨域允许或者在前端开发服务器配置 proxy 把 /api 开头的请求转发到后端。生产环境用 Nginx 反向代理更合理具体在部署章节讲。第二是字段命名。数据库用下划线Java 返回驼峰前端如果直接拿后端字段名容易对不上。建议后端在全局配置下驼峰映射并且所有接口字段名一开始就定好。比如宠物状态后端返回 pending、adopting、adopted 这种英文枚举前端映射成中文标签而不是后端直接返回“待领养”三个字。枚举的好处是稳定前端换文案不用改接口。第三是 token 处理。前端封装 axios 实例在请求拦截器里统一把 token 放进 Authorization 头在响应拦截器里统一处理 401跳转到登录页并清除本地登录态。不要在每一个接口里手动传 token那是在给自己埋定时炸弹。7. Docker 部署本地能跑不代表服务器能跑7.1 容器化方案怎么切分现在做前后端项目部署基本绕不开 Docker。最常用的方案是用 docker-compose 把三个服务编排在一起前端容器用 Nginx 托管打包后的静态文件后端容器跑 Spring Boot 或 Python 服务数据库容器跑 MySQL。前端 Nginx 除了托管静态文件还要做一件事把 /api 路径的请求反向代理到后端容器。这样浏览器只访问前端域名不需要暴露后端端口接口地址在前端代码里也保持相对路径换环境不用重新打包。下面是一个编排结构示例实际镜像和版本按你自己的环境调整# 示例docker-compose 服务编排按实际镜像版本调整 services: mysql: image: mysql:8 volumes: - ./data/mysql:/var/lib/mysql environment: MYSQL_ROOT_PASSWORD: ${DB_PASSWORD} backend: build: ./backend environment: DB_HOST: mysql DB_PORT: 3306 depends_on: - mysql frontend: build: ./frontend ports: - 80:807.2 部署时常见的四个坑本地跑得好好的部署到服务器上就挂是每个全栈新人都要经历的。常见原因有这些数据库地址写错。本地开发时数据库地址是 127.0.0.1但在 docker-compose 里后端要连的是 MySQL 容器的服务名比如 mysql。很多人忘了改这个配置导致后端启动时报数据库连接失败。文件上传目录没有挂载。宠物图片上传到容器里的目录如果容器被删掉图片就全丢了。部署时要把上传目录挂载到宿主机并且把目录权限设置好否则容器内进程没有写权限上传接口直接 500。内存不够。服务器内存小后端启动和 AI 接口调用都可能超时。先看服务器可用内存再决定要不要限制 JVM 或 Python 进程的内存占用。如果引入了本地模型推理那对内存的要求还会再上一个台阶。Nginx 配置里缺少反向代理块。前端页面能打开但接口全部 404基本都是 Nginx 只配置了静态文件没有把 /api 转发到后端。部署问题里数据库连接失败和图片目录没有挂载占掉了七成以上的报错。先想环境再怀疑代码。7.3 上线前的验证流程部署完成不是“能打开首页”就算结束。我的验证顺序是先看容器状态和日志确认后端启动成功、数据库连接正常再从前端页面走一遍最核心的登录和宠物列表然后测试一次图片上传确认文件写入了宿主机挂载目录并能通过 Nginx 访问最后测一遍领养申请到审核通过的完整流程。如果服务器上没有图形界面可以用 curl 直接调接口验证比打开浏览器更快定位问题。这一轮验证做完系统才算真正具备演示条件。8. 全功能演示验收从注册到审核的完整路径8.1 一条主线用例一个完整的演示路径建议这样走注册一个普通用户走完验证流程登录成功。在宠物列表页搜索“适合公寓的中型犬”找到一只待领养宠物打开详情页。查看 AI 生成的领养介绍点击申请领养填写居住条件、养宠经验提交。退出登录用管理员账号登录进入审核列表看到这条新申请。打开申请详情查看申请人信息点击通过。回到普通用户视角刷新“我的申请”状态从待审核变成已通过宠物详情页状态变成已领养。再注册第二个用户尝试申请同一只宠物应该收到“该宠物已被领养”的提示。这条链路跑通说明系统的权限、状态流转、事务、关联查询都是正常的。如果任何一步状态不对优先去看对应表的 update 语句是不是漏了条件。8.2 验收清单与关键检查点检查点预期行为失败时优先排查注册登录token 生成并在请求中生效拦截器配置、密码哈希普通用户访问管理员接口返回 403权限注解、角色字段宠物图片上传返回可访问路径且大小合理目录权限、文件类型限制重复申请同一宠物提示已申请或已领养宠物状态条件更新审核通过后宠物状态同步变为已领养事务是否生效拒绝申请后宠物状态恢复为待领养拒绝分支的状态重置AI 文案生成输出可控、可编辑提示词、超时设置部署后接口访问页面和接口都走域名或公网地址Nginx 反代、容器网络8.3 演示时最容易翻车的三个点第一个是图片不显示。很常见因为图片是相对路径本地开发时代理能处理生产环境代理没配好图片全部 404。处理办法是统一用一个静态资源前缀比如 /files/在 Nginx 里单独配置这个路径让它指向上传目录。第二个是审核后宠物状态没变。这不是前端问题是后端事务问题。检查你的领养审核方法上有没有事务注解或者 Python 后端是否真的提交了两次写操作。没有事务时申请状态改了但宠物状态没改用户看到的状态就是矛盾的。第三个是 AI 接口超时。演示现场网络一波动AI 调用十几秒没返回前端就会显示请求失败。建议在开发时给 AI 封装一个超时和重试机制并在前端把 AI 部分的加载状态和错误提示做友好一点。如果演示环境不稳定还可以准备一个降级逻辑AI 识别失败时让管理员手动填品种不影响主流程演示。9. 项目完成后还能往哪三个方向深挖9.1 从“能跑”走向“像生产项目”的三个方向先声明一个观点这个项目做到“能演示、能部署、能讲清楚状态流转”已经是一个合格的练手项目。不用非得加得特别大才算完整。真正值得深挖的是下面三个方向按你的时间和兴趣选一个。第一个方向是图像上传的工程化。把封面图从单张换成多图相册支持拖拽排序、裁剪、压缩图片文件接入对象存储。这个方向会让你把文件上传从入门水平提升到接近生产项目的要求。第二个方向是通知系统。审核通过后给用户发通知可以是站内消息也可以是邮件接口。做这个方向你会接触到消息模板、异步任务、失败重试这些后端常见话题。第三个方向是 AI 能力更深入。比如用图片识别给宠物自动打标签用语义搜索让用户用自然语句找宠物或者根据用户已领养的宠物做后续照料知识推荐。注意每次新增 AI 能力都要保证不影响主流程AI 模块必须能降级。9.2 简历和面试里该怎么讲这个项目如果你打算把项目写进简历比起写“实现了宠物领养系统”更有说服力的写法是写具体问题。比如“通过乐观更新解决了同一宠物被多人并发申请的问题”“通过状态机设计避免了领养流程脏数据”。面试官更在意的是你有没有想过边界而不是功能列表有多长。如果面试官问你“这个项目里最难解决的 bug 是什么”不要回答“登录不好使”。你可以讲并发申请的问题两个用户同时申请一只宠物条件更新影响行数为 0 的那个直接被拒绝申请记录不会落到表里。这个答案能同时体现你对数据库、并发和业务状态的理解。9.3 给不同背景读者的收尾建议给初学者先把主线用例跑通不要急着加花活。图片上传和领养审核能顺利走完你已经超过大部分练手项目了。给想转全栈的开发者重点放在接口设计、权限和事务上。前端页面做得再漂亮接口没有约束系统照样是脆弱的。给做毕业设计或团队 Demo 的人可以在主流程稳定之后再加一个数据统计模块比如领养成功率、饲养周期分析这类功能的演示效果好也能体现数据意识和分析能力。现在也有很多开发者用 AI 编程工具辅助写整个项目这完全可以但前提是你自己清楚每一步在做什么否则排错会非常痛苦。AI 可以帮你写代码不能替你理解业务。我一直觉得练手项目的价值不在于代码量而在于有没有把业务状态、异常边界和部署链路想清楚。宠物领养管理系统题目不大但该踩的坑一个都不少。把它从本地跑通到上线你会获得的不是一段能复制的代码而是一套判断“系统能不能上线”的经验。
锦
锦皓数字建站
深耕本土企业品牌数字化升级,专注原创端正雅致商务官网,从视觉设计到稳定运维全程保驾护航。