代码这东西,有时候光看文档是学不进去的,必须得有个具体的项目抓手才行。之前一直在折腾 Java 后端的东西,Spring Boot 玩得还算溜,但前端一直是我的短板,Vue 只是停留在“能看懂”的程度。直到我下决心做了这个“基于 SpringBoot + Vue 的动物领养平台管理系统”,才算是把前后端分离开发的整条链路给彻底打通了。今天就把这个项目的设计与实现过程完整写出来,包括技术选型的心路历程、数据库怎么设计、核心代码怎么写、还有我踩过的一堆坑,希望能给正在做类似练手项目或者毕业设计的同学一点参考。
这个系统说白了就是一个连接“想领养宠物的人”和“待领养动物”的线上平台:管理员可以发布动物信息、审核用户的领养申请;普通用户能浏览动物列表、查看详情、在线提交领养申请,还能在个人中心管理自己的申请记录。技术上就是标准的 Java 全栈组合——SpringBoot + Vue + MySQL + MyBatis,没有引入太复杂的东西,但前后端联调、权限控制、文件上传这些实战中一定会遇到的场景全都有。
1. 项目整体设计与技术选型思路
先说为什么选这套技术栈,而不是别的方案。如果你是一个人在开发这种管理系统,最忌讳的就是在技术选型上追求“大而全”或者“新而炫”,把微服务、分布式、容器编排全上来了,结果业务还没写几行就得先折腾架构,项目基本就烂尾了。SpringBoot + Vue 这套组合在中小型管理系统里几乎是事实标准,后端开发效率高、生态成熟,前端组件化开发上手快,最关键的是遇到任何问题都容易搜到解决方案。
1.1 后端核心框架选型:SpringBoot 的取舍
市面上 Java 后端框架选项不少,SSH(Struts2 + Spring + Hibernate)已经过时了,SpringMVC + JSP 的传统单体方案开发体验太差,而 SpringBoot 则把配置简化到了极致。它内嵌 Tomcat,打成一个 jar 包就能直接跑,不用单独部署 Web 容器,这对本地开发调试来说体验提升是颠覆性的。
有一点提醒一下想用新版本的朋友,现在 SpringBoot 3.x 已经出来很久了,但它基于 JDK 17,并且把javax包名改成了jakarta,很多老教程和老配置都会失效。我自己做这个项目的时候选的是SpringBoot 2.7.x + JDK 8/11,别看版本“老”,这是目前整个生态兼容性最稳的一个组合:主流教程、面试题、公司旧项目基本都扎堆在这个版本区间。如果你只是为了把系统做出来跑通,别追求版本最新,不然光一个spring-boot-starter-parent版本号冲突就能让你耗掉一晚上。
1.2 持久层方案:为什么是 MyBatis 而不是 JPA
说句实话,当初在 MyBatis 和 Spring Data JPA 之间我也摇摆过一阵。JPA 的自动建表、CRUD 全部交给框架,代码量确实少;但一旦查询条件复杂起来,或者需要多表关联加上各种动态条件,JPA 的 Query DSL 和 @Query 注解就会让 SQL 变得很别扭,而且出了问题极难排查。
MyBatis 的思路就非常纯粹:SQL 是你自己写的,每一个查询都在你的完全掌控之下。比如动物的列表页,我需要根据物种、年龄、性别、是否已领养等多个条件组合筛选,搜狗搜索这种查询用 MyBatis 动态 SQL 拼条件就是几分钟的事;用 JPA 去拼 Specification 就没那么直观了。另外,MyBatis 的 SQL 复用、缓存机制这些面试常考的点,你在做项目的过程中能亲手摸一遍,对理解框架底层也很有帮助。
1.3 前端方案:Vue 2 + Element UI 的稳定组合
前端我选了 Vue 2(配合 Vue Router、Vuex 和 Axios),UI 组件库配套用 Element UI。现在 Vue 3 和 Element Plus 当然是主流,但 Vue 2 的生态成熟度和中文资料量依然是最庞大的。特别是对于后端开发者来说,你的主要精力应该花在业务逻辑和数据交互上,而不是花一整天去调前端框架的兼容性问题。
Element UI 的表格、表单、弹窗、上传组件都是封装好的,拖过来改改就能用,能帮你把大量的前端开发时间压缩到最少。这个项目的前端虽然看起来页面不少,但真正需要手写样式的其实没几处,从“前端劝退”到“能独立写页面”,靠的就是这种成熟的组件库。
1.4 功能模块与角色权限梳理
这个系统的用户角色非常简单,就两类:管理员和普通用户。设计权限之前一定要先把业务场景想清楚,别一上来就整 RBAC 那套多角色多权限的模型,项目复杂度会成倍上升。管理端和用户端我拆分成了两个不同的登录入口和路由空间,登录时根据用户的role字段做跳转,这样做最直观,也最不容易出逻辑混乱。
整个系统的核心模块我大致框定为这几块:用户管理(注册、登录、个人信息修改)、动物管理(发布动物、编辑、下架)、领养申请管理(提交申请、审核、状态流转)、系统公告管理,以及管理员后台的登录首页数据统计。如果把这些模块全部实现完,你的 CRUD 熟练度、关联查询能力、状态流转设计能力基本都能覆盖到了。
2. 核心功能模块与数据库设计要点
很多新手拿到项目需求后第一件事就是写代码,这是本末倒置的。一个系统能不能撑得住业务扩展,数据库表设计占了七成。我把所有需求在纸面上画成表结构图,反反复复改了三版才开始动手写代码,后来的开发效率出奇的高——因为表结构清楚了,业务逻辑的底子就牢了。
2.1 数据表结构全景解析
这个系统我一共建了六张核心表,不算多,但足够覆盖所有业务场景。每张表都必须在建表之初就预留必要的字段,比如常用的create_time、update_time,不然后面做列表排序和操作日志的时候你就会发现源头数据缺失了。
CREATE TABLE `user` ( `id` int(11) NOT NULL AUTO_INCREMENT, `username` varchar(50) NOT NULL COMMENT '用户名/登录账号', `password` varchar(100) NOT NULL COMMENT '密码(BCrypt加密)', `nickname` varchar(50) DEFAULT NULL COMMENT '昵称', `phone` varchar(20) DEFAULT NULL COMMENT '联系电话', `avatar` varchar(255) DEFAULT NULL COMMENT '头像URL', `role` tinyint(1) NOT NULL DEFAULT '0' COMMENT '角色:0普通用户 1管理员', `create_time` datetime DEFAULT NULL, `update_time` datetime DEFAULT NULL, PRIMARY KEY (`id`), UNIQUE KEY `uk_username` (`username`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户表';动物表animal是系统的主数据表,字段包括动物名称、种类(猫/狗/其他)、品种、性别、年龄、毛色、是否绝育、是否打过疫苗、健康状态描述、所在城市、封面图片路径、领养状态(0待领养/1已领养/2已下架)、性格描述等等。这里有一个业务细节值得注意:“已领养”状态不应该直接由用户或管理员手动去改,而是由领养申请审核通过这个行为自动触发,这样能保证整条操作链路的逻辑自洽。
领养申请表adoption_application是连接用户和动物的桥梁,也是整个系统业务逻辑最重的表。核心字段包括user_id、animal_id、apply_reason(申请理由,这个字段对审核人做判断至关重要)、status(0待审核/1已通过/2已拒绝)、create_time、update_time。为了避免同一个用户对同一只动物重复提交申请,这里我还加了user_id + animal_id的联合唯一索引。
其余还有系统管理员发布的公告表notice、用户与管理员交流的留言表message,以及后续扩展可能需要用到的操作日志表log。建表时统一使用 InnoDB 引擎和 utf8mb4 字符集,前者支持事务,后者能存下生僻字和表情符号,对中文业务系统来说这两点都是底线。
2.2 领养状态机的设计:保证业务不乱的关键
别看这是个练手级项目,领养业务中“状态”的流转反而最考验设计功底。如果只是简单地把状态字段设置为可随意改写的数字,任何一步操作都能直接把它改得乱七八糟——比如用户一提交申请,管理员还没审核呢动物就被标成了“已领养”,这明显是不合理的。
我采用的方案是对状态的操作做接口级约束:用户提交领养申请时,后端只允许创建status = 0(待审核)的申请记录,并且把这个动物状态改为“审核中”(借用原业务的2号状态对应“申请中”),此时动物在前端列表中的展示要带标签但不可重复申请;管理员点击“通过审核”,后端事务里同时更新申请记录状态为 1 和动物状态为 1(已领养),确保要么都成功、要么都失败;点击“拒绝”则只把申请状态改成 2,动物状态回归待领养。这一段逻辑里用到了@Transactional事务注解,正好也是个很好的练手点。
2.3 接口设计的 Restful 风格约定
前后端分离的项目,接口约定直接决定了联调是否顺畅。我定义了统一返回体Result,包含code(200成功/500失败/401未认证)、msg、data三个字段。所有的接口路径都遵守/api/**开头,后端接口分成/api/admin/**(需要管理员权限)和/api/user/**(登录用户可访问)两组,再配合拦截器统一做登录校验,逻辑非常清晰。
举个例子,动物列表查询的接口设计为GET /api/animal/list?pageNum=1&pageSize=10&type=cat&status=0,这种条件查询 + 分页的写法是后端接口最标准的形态。前端通过 axios 封装的实例统一在请求头里带token,后端接口通过拦截器去解析校验这个token,这套流程走到位了你就会发现,给系统加任何新功能都变得很顺滑。
3. 后端核心实现与关键代码深度拆解
数据库搞定之后,就要开始写真正的业务代码了。这一部分我把后端里面最具代表性的几个环节拿出来拆开讲——登录鉴权、文件上传、动态 SQL 查询、以及领养申请的审核事务。这些都是面试的时候被反复问到的点,也是实际开发中出问题最多的点。
3.1 注册登录模块:BCrypt加密与Token鉴权
用户密码直接明文存储到数据库?这在实际项目中是绝对不能接受的,万一数据库泄露,所有用户的密码全部直接暴露。这里我用的是 Spring Security 中的BCryptPasswordEncoder,它不像是 MD5 那样确定性地对同一个密码生成同一个摘要,而是每次加密都会带一个随机盐,即使两个人密码完全相同,存到数据库里的密文也是不一样的,极大地提高了安全性。
// 注册时加密密码 String encodedPwd = new BCryptPasswordEncoder().encode(user.getPassword()); user.setPassword(encodedPwd); // 登录时校验密码 BCryptPasswordEncoder encoder = new BCryptPasswordEncoder(); if (!encoder.matches(rawPassword, user.getPassword())) { throw new RuntimeException("用户名或密码错误"); }Token 鉴权这块,我没有特意去集成 JWT 框架,而是用了一个更轻量的思路:登录成功后服务端生成 UUID 字符串作为token,以user:token:用户ID为 Key 存到 Redis,没有 Redis 的时候用 ConcurrentHashMap 内存缓存也一样能跑。每次请求进来,拦截器从请求头的Authorization字段里取出token并解析出用户身份,校验通过才放行。因为不用处理 JWT 的过期时间、签名算法这些细节,整个代码量大幅缩小,而且逻辑单线程好排查。
3.2 动物信息发布:图片上传与静态资源映射
动物领养平台最核心的信息载体就是图片,用户看列表时第一眼关注的就是照片。图片上传我实现的是一个通用接口POST /api/upload/image,接收 MultipartFile 文件参数,然后用UUID.randomUUID()生成不重复的文件名,按日期分目录存储在本地磁盘(比如D:/upload/2025/xx/),这样既避免了一个目录下文件过多影响性能,也好做后续的定期清理。
本地存储有一个容易踩坑的点:前端页面上展示的是图片的 URL,但这个图片不是放在后端项目的静态资源目录里的,直接访问是 404。解决方案是给后端添加一个资源映射配置类,把磁盘路径映射成虚拟 URL 路径,比如请求/files/2025/xx/xxx.jpg时,Spring Boot 自动从磁盘上对应位置读取文件返回,这套配置几行代码就能写完,但很多新手搞不定。
3.3 动物列表的动态条件查询
动物列表页用到了两个维度的筛选条件:一是动物自身的属性(种类、性别、年龄范围、所在城市),二是用户的搜索关键词(按名称模糊查询)。如果每一种条件的组合都写一个独立接口,你的 Controller 马上就会爆炸。MyBatis 的<where>标签 +<if>标签来这里简直就是绝配:
<select id="selectAnimalList" resultType="map"> SELECT a.*, u.nickname AS publisher_name FROM animal a LEFT JOIN user u ON a.publish_user_id = u.id <where> <if test="type != null and type != ''"> AND a.type = #{type} </if> <if test="keyword != null and keyword != ''"> AND a.name LIKE CONCAT('%', #{keyword}, '%') </if> <if test="status != null"> AND a.status = #{status} </if> </where> ORDER BY a.create_time DESC </select>这里有个细节必须强调:动态 SQL 拼接不等于直接String concatenation,MyBatis 用的是预编译#{}占位符,底层是PreparedStatement的参数绑定,这样天然规避了 SQL 注入问题。如果图省事用${}去拼接传入的排序字段或者表名,你把接口服务到公网以后,会有无数人用 SQL 注入工具分分钟把你库里的数据拿走,别问我是怎么知道的。
3.4 领养申请审核的数据库事务
一块完整的 OAuth 协议流程中,最容易出错的是回调地址的拼接。 审核操作横跨了两个数据表,必须用事务把多步写操作包起来,保证任何一步失败,之前的操作都自动回滚。Spring 里加个@Transactional注解,传播行为、隔离级别默认值就可以满足大部分情况。
@Transactional(rollbackFor = Exception.class) public void auditAdoption(Integer applicationId, Integer auditStatus, Integer operatorId) { Application application = applicationMapper.selectById(applicationId); if (application == null || application.getStatus() != 0) { throw new RuntimeException("领养申请不存在或已处理"); } // 只有动物存在且仍处于待领养/申请中状态,才能继续走审核逻辑 Animal animal = animalMapper.selectById(application.getAnimalId()); if (animal == null) { throw new RuntimeException("关联的动物不存在"); } if (auditStatus == 1) { application.setStatus(1); applicationMapper.updateById(application); animal.setStatus(1); animal.setAdopteeUserId(application.getUserId()); animalMapper.updateById(animal); } else if (auditStatus == 2) { // 拒绝:只更新申请状态,把动物“申请中”状态回滚为“待领养” application.setStatus(2); applicationMapper.updateById(application); animal.setStatus(0); animalMapper.updateById(animal); } // 发送站内信/系统公告通知申请人审核结果 messageMapper.insert(new Message(...)); }事务的rollbackFor = Exception.class这个细节我给个特别提醒:Spring 的事务默认只在遇到运行时异常(RuntimeException 和 Error)时回滚,如果业务方法里抛出的是自定义的普通 Exception,默认是不会回滚的。代码里所有业务异常我统一继承RuntimeException,这样每条规则都能被可靠地处理。
4. 前端页面设计与交互流程实现
后端接口全部调通了以后,剩下最重的活就是把前端页面搭起来。我对前端的要求一直是“能跑就行但别太丑”,Element UI 在这方面帮我解决了 70% 的样式问题。
4.1 Vue 项目搭建与路由设计
使用 Vue CLI 创建项目是标准的起步方式,先npm install -g @vue/cli安装脚手架,然后执行vue create animal-frontend生成项目骨架。目录结构上我会把src里的内容按功能拆分:api目录统一放 axios 请求封装,views目录放页面级组件,router管路由,store管全局状态。
路由权限是整个前端安全链路上的重要一环。虽然后端已经做了接口拦截,但前端如果不做处理就会有各种诡异问题——比如用户直接手动修改 URL 跳去/admin/dashboard,后端 401 返回以后页面还是白屏的。我实现的方式是在router.beforeEach全局前置守卫里检查目标路由的meta.requiresAuth,结合当前 vuex 里存储的userInfo.role来判断是否能进入该路由,不满足条件就next('/login')并提示无权限。管理员和普通用户的路由都是动态拼接的,通过router.addRoutes实现。
4.2 毛孩子列表页:卡片式展示与条件筛选
用户端的首页核心就是待领养动物的卡片列表。我用 Element UI 的el-row+el-col栅格布局做三列展示,每张卡片上展示封面图、动物名称、主要标签(种类、性别、年龄)、领养状态。点击卡片跳转到详情页,需要带上动物 ID,Vue Router 处理成/animal/detail?id=123查询参数即可。
查询条件我用的是el-select和el-input,当条件值变化时重新请求接口,把pageNum重置为 1 并且用新参数重新拉取数据。这里有一个交互细节要重点处理:图片加载失败的兜底。动物图片可能来自网络图或者长期未维护的外链,一旦加载失败整个卡片都会稀碎,所以我对每个img标签绑定了@error事件,把默认图替换成本地的一张猫咪占位图,这个小改动让整个页面稳定性瞬间提升了一个档次。
4.3 领养申请表单:前端校验到后端校验的双保险
领养申请页面的核心是一个表单,需要用户填写自己当前的居住情况、养宠经验、申请理由。前端我用el-form的rules属性加了必填和长度校验,比如申请理由最少写 20 字,理由写得太敷衍的申请会在前端直接被打回。
但前端校验只是做用户体验的,真正的安全边界必须落在后端校验。后端在接收申请时我会校验:用户是否登录、动物是否存在、动物当前状态是否处于可申请状态(0 或申请中)、当前登录用户是否已经申请过这只动物。如果后端这层校验写的扎实,如果未来有人避开前端直接调你的接口,系统也能稳稳兜住。
4.4 管理后台:数据概览与审核工作台
管理员的页面相对更加“后台化”。登录后跳转/admin/dashboard,顶部是大数字卡片——今日新增用户数、今日新增动物数、待审核申请数、总领养成功数,数据来源是一个聚合查询接口selectCountDashboard,后端写几条带COUNT(*)和GROUP BY的 SQL 就能完成。
管理员的动物列表复用el-table表格组件,每一行都可以对动物进行“编辑 / 下架”操作。领养申请审核页则是这个平台最紧张的一块工作台:表格里展示所有待审核的申请,每条申请旁边有“通过”和“拒绝”两个按钮,点击后弹 Dialog 确认二次确认,通过后自动刷新动物状态。这里实践中有个重要经验:审核操作一定不能做成在表格内直接改数据然后调 update 接口,必须走后端完整的auditAdoption方法,否则状态机的约束就形同虚设了。
5. 环境配置、联调部署与完整实操流程
一个项目哪怕代码写得再漂亮,如果别人拉下来跑不起来,基本等于零。我见过太多项目文档写了“请自行配置环境”,这对新手来说是一句灾难。这里把整套环境搭建和部署运行的步骤完完整整写出来,照着做就一定跑得起来。
5.1 后端环境配置与数据库初始化
后端方面我最建议用的 IDE 就是 IntelliJ IDEA,装好之后直接导入 Maven 项目。JDK 8 或者 11 都行,Maven 仓库建议配置阿里云镜像,不然拉依赖的速度会让你怀疑人生。打开src/main/resources/application.yml需要修改的内容集中在数据源和上传路径两处:
server: port: 8080 servlet: context-path: / spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/animal_adoption?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai username: root password: 你的数据库密码 mybatis: mapper-locations: classpath:mapper/*.xml type-aliases-package: com.example.entity configuration: map-underscore-to-camel-case: truemap-underscore-to-camel-case: true这个配置必须开,它能自动把数据库的create_time映射成 Java 实体里的createTime,省去一堆注解。每次启动项目前先用 Navicat 或者命令行执行项目里准备好的init.sql脚本建库建表,再顺手往用户表里插一条管理员账号(role=1),MD5 或者 BCrypt 加密后的密码随便填一个能登录的即可。
5.2 前端环境配置与代理转发
前端需要安装 Node.js(14.x 以上),Vue 项目启动后默认跑在 8080 端口,为了跟后端错开,我配置 devServer 跑在 3000 端口,同时还要做一个核心配置——代理转发。前端在开发环境下请求/api开头的接口,会默认请求前端服务器http://localhost:3000/api,而实际上后端接口地址是http://localhost:8080/api,跨域问题此时就会显现。在vue.config.js里配置devServer.proxy,把/api的请求全部转发到http://localhost:8080,这个配置一加上,开发联调阶段就不需要后端去做 CORS 跨域放行了。
devServer: { port: 3000, proxy: { '/api': { target: 'http://localhost:8080', changeOrigin: true } } }有一个特别隐蔽的坑:后端接口返回的图片 URL 是/files/xxx.jpg这种形式,前端代理如果没有配置/files的转发规则,图片请求就会仍然发给 3000 端口导致 404。我的解决方案是在代理规则里再加一条'/files'同样指向后端,这样图片在开发环境就能正常加载了。
5.3 打包部署
开发全部搞定之后,生产环境部署的路子也非常直接。后端执行mvn clean package -DskipTests打包成animal-backend.jar,扔到装了 JDK 的服务器上java -jar animal-backend.jar就行;前端执行npm run build,产物是dist静态目录。最大的部署坑在于前端的接口地址:生产环境构建出来的 JS 里不会带着localhost:8080,需要在前端项目里建.env.production文件,把VUE_APP_BASE_URL = '/api'配成相对路径,再由 Nginx 通过反向代理把/api转发到本地 8080 端口,这样一个域名就能同时复用前端静态资源代理和后端接口,跨域问题也被彻底消解。
6. 常见问题与排查技巧实录
这一节算是整个项目里最有价值的部分了,因为我上面写的那些配置和代码,全都是从一个个具体的问题里摸爬滚打出来的。新手时期遇到的这些问题,随便一个都能卡住一整天,我把它们整理成了速查表格,你们对号入座即可。
6.1 启动类问题速查表
| 问题现象 | 根本原因 | 解决方案 |
|---|---|---|
启动直接报Failed to configure a DataSource | 没连上数据库 | 检查 MySQL 是否启动、密码是否正确,useSSL=false先加上 |
| 后端启动成功但访问接口 404 | @Mapper注解漏了或 mapper XML 路径配置错 | Mapper 接口加@Mapper,确认mapper-locations指向真实路径 |
前端npm run serve报sass相关错误 | Node 版本过高/过低 | 切换 Node 14 或者直接删除node_modules重新 install |
| 前端请求接口 404 但接口能 Postman 调通 | 代理正向配置丢了 | 检查vue.config.js,确认proxy规则覆盖了所有需要代理的路径前缀 |
| 图片上传成功但页面显示 404 | 静态资源映射没配或代理漏配 | 配置WebMvcConfigurer的 addResourceHandlers,前端代理加/files |
MyBatis 报Invalid bound statement (not found) | Mapper XML 没有被扫描到 | 检查mapper-locations路径,确认 XML 中 namespace 与接口全限定名一致 |
6.2 排查技巧与经验心得
排查问题的时候,最忌讳的事儿就是盯着报错信息看一次就瞎改代码,改完还不行再改,越改越乱。我的经验是先复现、再定位、最后才动手。前端报错优先看浏览器开发者工具Network面板,看请求有没有发出、状态码多少、返回体是什么;后端报错优先看控制台完整的堆栈信息,定位到具体是聊到了哪一层出的错,然后带着这个信息去搜索。很多问题搜一次带异常类的关键词组合,比如“MyBatis Invalid bound statement”,精准程度会高很多。
另一个经验是:补偿性的数据修正代码要果断写。比如我做状态机的时候,审核通过的动作因为一次脏数据把动物状态改错了,于是我直接在代码里加了启动时数据修正的脚本,扫描所有“已通过领养申请”对应的动物状态不一致的,自动重置。这个看似不优雅,但业务就是这样,脏数据不及时清代价会更大。
6.3 关于性能与安全的几个额外建议
这种管理系统虽然数据量不大,但有些好习惯值得从现在开始养成。数据库连接池、SQL 执行耗时这些监控点位提前埋在代码里以后排查线上问题会快很多;上传文件要做格式和大小白名单校验,后缀名不能只判断最后一个点之后的字符;所有接口校验好参数空指针;密码永远不能明文入库;对外的管理接口一定要做权限控制,否则系统上线以后被别人扫一下就只剩尴尬了。
7. 写在最后的一点心得和扩展建议
复盘整个动物领养平台的开发过程,最大的收获并不是写了几千行代码,而是通过一整套完整系统把“前后端分离开发”的完整链路彻底串了一遍:从数据库设计开始,到后端接口开发、动态 SQL 构建、事务处理、权限控制,再到前端页面编写、接口联调、打包部署,每一步都踩过坑、填过坑,然后再回看那些面试题和框架文档,理解就完全不一样了。
最后分享一个小技巧:做这种全栈项目的时候,接口文档一定不能偷懒,每写完一个后端接口就把请求路径、参数、返回规则随手记到一个 Markdown 文件或者直接用 Swagger 注解生成在线文档。即便项目里只有你一个人在开发,半个月后再来看自己写的接口也可能想不起字段含义,更别说未来答辩的时候评审老师伸手就要看接口文档了。
如果你也想拿这个项目练手,我的建议是不要只满足于把功能基本跑通,试着把它一步一步升级成一个“能接得住流量”的正式项目:给密码改造成 Spring Security + JWT 的完整方案,给图片迁移到 OSS 对象存储,给数据库查询加上 Redis 缓存,再给前后端代码加上 Docker 容器化打包。你会发现每往前多走一步,自己的技术视野就会往外扩一大圈。
系统本身做完了以后,我还给它做了一个很有意思的延伸——在“领养成功”节点自动给用户发送一封欢迎养宠邮件,顺便推送几条科学的养宠指南。这些细节虽然技术难度不高,但能让整个系统从“课设作品”真正变成“有价值的产品”,做项目的乐趣也在这里面。