Spring Boot+SSM宠物领养平台实战:从需求到部署
宠物领养这事最难的不是没有爱心而是信息根本传不到对的人手里。我以前帮一个民间救助站做过登记表他们每周在公众号推一次待领养猫咪评论区挤满还在吗管理员得一个个私聊确认结果一半猫咪都送出去了帖子还挂着。后来我干脆用 Spring Boot SSM 给他们撸了一个宠物领养平台把信息发布、领养申请、审核跟踪全部搬到线上。这套东西做完之后我最大的感受是技术上没有多高深但把业务逻辑捋顺、把状态流转做对比堆一堆花哨框架值钱得多。这篇就完整复盘一下设计和实现过程给正在做同类毕设、或者想用 SSM 做完整项目练手的朋友一条可以直接照抄的路线。1. 宠物领养平台的定位与需求拆解1.1 真实场景为什么需要平台而不是微信群线下救助站的典型流程是这样的志愿者在朋友圈发图——有意向的人留言或者私聊——志愿者挨个回答问题疫苗打了吗、驱虫做了吗、能不能接受回访——筛选出靠谱的人——约时间看猫——然后再填一张纸质登记表。这个流程最致命的问题有三个第一信息不对称。同一个宠物可能同时在五个群发布领养人看到的是零星碎片很难集中比对哪一只适合自己。第二领养资质无法审核。谁都可以在评论区说我要养但有没有养宠经验、家里是否封窗、家人是否同意这些关键信息完全没人记录。第三状态不可追溯。宠物到底是被领走了还是还在等除了管理员脑子里的记忆没有任何系统能回答。平台的定位因此很明确它不是一个简单的宠物展示橱窗而是一个撮合加审核的双向渠道。送养人发布宠物信息领养人浏览并提交申请管理员在中间做资格审查和流程推进宠物状态从待领养到审核中再到已领养每一步都有据可查。这就是整个系统的核心价值后面所有表结构和接口设计都在为这个目标服务。1.2 用户角色与核心业务流程我把系统的用户拆成三类每类权限完全不同角色核心能力典型操作送养人管理员可兼任发布宠物信息、查看申请、确认领养上传宠物照片、填写健康状况、筛选申请人领养人普通注册用户浏览宠物、提交申请、查看进度搜索筛选、填写领养理由、上传个人资料系统管理员用户管理、宠物审核、全局配置审核宠物上架、冻结违规账号、统计运营数据这里有个容易搞混的点很多同类平台把送养人和管理员完全分开但实际运营中救助站的志愿者往往一人分饰两角。所以我设计成送养人可以是注册用户管理员拥有全部权限同时管理员后台也可以直接发布宠物信息避免角色过碎导致流程卡住。核心业务流程我梳理成这样一条链路送养人提交宠物资料 → 管理员审核宠物是否合规 → 宠物状态变为待领养 → 领养人浏览并发起申请 → 送养人查看申请列表并选择合适的人 → 双方线下交接 → 管理员将宠物标记为已领养。中间任何一个环节卡住系统都应该有对应的状态和操作入口而不是靠线下沟通去补救。1.3 功能模块清单与优先级划分真正动手写代码之前先列需求清单分好优先级这一点比写代码本身更重要。我当时把功能切成四个梯队第一梯队不做平台跑不起来用户注册登录、宠物信息发布与展示、领养申请提交、个人中心。第二梯队没有体验不完整管理员后台、宠物审核上下架、领养状态流转、搜索与分类筛选。第三梯队锦上添花留言评论、收藏关注、站内消息通知、领养回访记录。第四梯队画饼阶段推荐算法、积分体系、小程序端、数据可视化大屏。我给自己的原则是第一梯队和后端工程结构同步搭第二梯队逐个补齐第三梯队看时间第四梯队只在文档里提一嘴。事实证明这个取舍非常对——很多同学一上来就想做全功能大平台结果注册登录还没写完就开始画饼最后代码烂尾。2. 技术选型Spring Boot SSM 的搭配逻辑与版本选择2.1 为什么是 Spring Boot 2.x而不是 3.x这个标题叫基于SSM的宠物领养平台但全文都在用 Spring Boot很多人会疑惑这两者是不是冲突。其实完全不是——SSM 指的是 Spring Spring MVC MyBatis 这套框架组合而 Spring Boot 只是改变了 Spring 的装配方式让原本需要在 XML 里写一堆配置的 SSM 变成自动配置。换句话说Spring Boot 是 SSM 的现代化载体对应关系大概是传统 SSM 组件Spring Boot 中的体现Spring 核心容器spring-boot-starter自动装配Spring MVCspring-boot-starter-webMyBatismybatis-spring-boot-starter我选的是 Spring Boot 2.7.18。这是 2.x 家族的最后一个版本为什么要卡在这个版本而不是追最新的 3.x理由很实在3.x 要求 JDK 17 起步而很多学校的机房、老服务器的 JDK 还是 8另外 MyBatis 官方对 Spring Boot 3 的适配在早期并不顺畅虽然现在没问题了但考虑到部署环境和踩坑成本2.7.18 之于 SSM就像 Python 3.8 之于爬虫项目——够用、稳、资料多。如果你准备答辩老师问为什么不用更高的版本你完全可以说项目面向实际部署环境JDK 8 生态下 2.7.18 是兼容性最稳妥的选择。2.2 核心依赖清单与版本对应关系pom.xml 里的依赖不需要多但每一条都要明确它解决什么问题。我的核心依赖配置如下parent groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-parent/artifactId version2.7.18/version relativePath/ /parent dependencies !-- Web 层内嵌 Tomcat Spring MVC Jackson -- dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-web/artifactId /dependency !-- MyBatis 与 Spring Boot 的官方桥接 -- dependency groupIdorg.mybatis.spring.boot/groupId artifactIdmybatis-spring-boot-starter/artifactId version2.3.1/version /dependency !-- MySQL 驱动 -- dependency groupIdmysql/groupId artifactIdmysql-connector-java/artifactId version8.0.33/version /dependency !-- 分页插件 -- dependency groupIdcom.github.pagehelper/groupId artifactIdpagehelper-spring-boot-starter/artifactId version1.4.7/version /dependency !-- 参数校验 -- dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-validation/artifactId /dependency !-- 简化代码 -- dependency groupIdorg.projectlombok/groupId artifactIdlombok/artifactId optionaltrue/optional /dependency /dependencies这里我要特别提一下 Lombok很多人图省事直接全项目Data这在课程设计里没问题但如果你要把它当成一个认真的工程建议只对实体类和 DTO 使用Controller 和 Service 里尽量避免。因为答辩时老师问你这个 Getter/Setter 哪来的你至少得能说清楚 Lombok 的编译期注解处理器原理。2.3 前端方案取舍服务端渲染还是前后端分离宠物领养平台这种项目前端有两种主流选择一是用 Thymeleaf 做服务端渲染二是用 Vue Element UI 做前后端分离。我最终选了前者原因有三第一单体架构下服务端渲染的联调成本最低。前后端分离意味着你要维护两套工程、两套启动方式、跨域配置、Token 鉴权这些额外复杂度对一个以业务流转为核心的平台来说收益不高。第二Thymeleaf 模板直出有利于 SEO 和后台上传。管理员发布的宠物详情页可以直接被搜索引擎收录这在真实运营场景里是实际需求。第三部署简单。一个 Spring Boot 可执行 JAR 包全搞定不需要 Nginx 同时代理静态资源和后端接口。当然这不代表前后端分离不好。如果你后续确定要接小程序或者移动端那核心接口在设计时就该按 REST 风格走Thymeleaf 页面只是消费同一套接口的其中一个客户端。我在实际项目里采用了折中方案页面用 Thymeleaf 渲染但所有动态数据交互都通过独立的/api/接口返回 JSON这样就算以后要换前端后端逻辑不用动。2.4 环境准备开发环境我建议按这个组合来兼容性最省心JDK 1.8不要用 11 或者 17除非你做好了换 Spring Boot 3 的准备Maven 3.8镜像源配阿里云否则下载依赖会让人崩溃MySQL 5.7 或 8.0建议 8.0连接串记得加serverTimezoneAsia/Shanghai开发工具IDEA 2023 以下版本即可付费版和学生版都行Redis 可选如果要做会话共享或者缓存起步阶段可以先不引入注意MySQL 8.0 以上的驱动类名还是com.mysql.cj.jdbc.Driver不用改。但 8.0 对时区要求很严格连接串里不带serverTimezone会在启动时直接报错这是新手最容易卡住的第一道坎。3. 数据库设计与最容易被忽视的业务约束3.1 核心表结构用户、宠物、领养申请数据库设计是整个项目的地基我踩过的坑有一半都在这里。平台最少需要五张业务表加三张基础表我来逐个说明设计意图和字段讲究。用户表t_user字段类型说明idbigint 自增主键用户唯一标识usernamevarchar(50) 唯一索引登录名passwordvarchar(100)存 BCrypt 密文长度至少 60phonevarchar(20)联系方式领养审核时必须roletinyint0-普通用户 1-送养人 2-管理员avatarvarchar(255)头像 URLis_bannedtinyint是否被冻结0/1create_timedatetime注册时间密码长度这个细节特别容易翻车如果用 MD5 存32 位就够但 BCrypt 的密文是 60 位如果建表时规划成 varchar(32)注册接口一调就报数据库异常而且这个异常出现在 MyBatis 的底层定位起来很绕。宠物表t_pet宠物是平台的核心资源字段我拆得比较细pet_name宠物名、category猫/狗/其他、breed品种、age_month月龄用整数方便筛选、gender、vaccine_status疫苗状态、sterilization_status绝育状态、health_desc健康描述、images图片支持多图逗号分隔、city所在城市、detail_addr详细地址脱敏显示、status0-待审核 1-待领养 2-审核中 3-已领养 4-已下架、publisher_id送养人、create_time。这里有个关键设计status字段不要用枚举值直接存字符串用数字加注释。因为状态流转逻辑复杂数字才能高效做索引和条件查询——比如首页只需要展示status 1的宠物如果存字符串 待领养那所有查询都要带上字符比较性能差一截。领养申请表t_adopt_apply字段类型说明idbigint 主键申请编号pet_idbigint申请领养的宠物user_idbigint申请人reasonvarchar(500)领养理由experiencevarchar(500)养宠经验home_conditionvarchar(500)住房/家庭环境描述statustinyint0-待审核 1-已通过 2-已拒绝 3-已撤销apply_timedatetime申请时间audit_timedatetime审核时间这张表是整个平台业务密度的集中体现。注意我没有把审核结果直接放在宠物表里而是单独建申请单——因为一只宠物可能会收到多份申请送养人需要逐份审阅、择优选择如果只拿一个字段记录谁被选中了多申请场景就支撑不了。3.2 领养状态机的设计每一步都要能回去状态机这个概念听起来高大上实际上就是彻底想清楚每个状态在什么条件下可以跳到什么状态跳转时哪些字段必须跟着变化。我的宠物状态流转这样定义待审核0送养人刚提交只有管理员能看到首页不展示。可跳转到待领养审核通过、已下架审核不通过或撤回。待领养1正常对外展示。可跳转到审核中有用户提交申请后自动进入、已下架送养人主动撤下。审核中2已经有人提交申请送养人正在筛选。可跳转到待领养所有申请被拒绝重新开放、已领养成功交接。已领养3终态。宠物从列表消失进入领养记录。已下架4终态。可能是被管理员下架也可能是送养人主动撤下。这个设计里最容易漏掉的是审核中回退到待领养这条路径。很多新手只想到申请通过就领养成功完全没考虑送养人拒绝了所有申请的情况结果拒完一个以后宠物永远显示审核中首页直接失去一条展示位这就是状态机不闭环的典型症状。3.3 关于外键和索引的教训我最初建表很喜欢加物理外键想着关联完整性靠数据库兜底。但实际运维几次后发现物理外键在业务系统里就是一个隐形的性能杀手——每次插入子表记录MySQL 都要去检查父表是否存在高并发下外键检查会锁父表记录而且分库分表时外键直接失效。所以这套系统的表间关系全部用逻辑外键也就是只保留关联字段如pet_id不声明FOREIGN KEY关联完整性由 Service 层保证。索引方面我吃过一个亏查询记录表时pet_id和user_id都分别建了单列索引但实际最频繁的查询是某个用户的所有申请记录按时间倒序也就是WHERE user_id ? ORDER BY apply_time DESC。单列索引只能加速前半段排序还是要 filesort。后来加了联合索引(user_id, apply_time)才把这条慢查询干掉。设计索引时不要想当然直接对着业务 SQL 来。4. 核心功能实现从注册登录到领养申请的全链路4.1 用户认证模块BCrypt 加密和登录态管理用户认证是每个系统都有的模块但很多人把它写成了查一次数据库就放行的玩具。我的做法是三层防护第一层密码绝不存明文。Spring Security 全家桶对这类项目来说太重了我单独引入spring-security-crypto这个轻量包只用到它的BCryptPasswordEncoder。注册时对密码做 BCrypt 加密登录时用matches方法校验。BCrypt 的特点是每次加密结果都不同随机盐所以即使两个用户密码相同落库密文也不一样有效防止了彩虹表攻击。Component public class PasswordUtil { private static final BCryptPasswordEncoder ENCODER new BCryptPasswordEncoder(); public String encode(String rawPassword) { return ENCODER.encode(rawPassword); } public boolean match(String rawPassword, String encodedPassword) { return ENCODER.matches(rawPassword, encodedPassword); } }第二层用 Session 但配合过滤器做登录校验。单体服务端渲染项目用 HttpSession 存登录态是最自然的方案。我写了一个LoginInterceptor实现HandlerInterceptor在preHandle中检查当前 Session 是否有loginUser没有就重定向到登录页有就把用户对象塞进 request 供 Controller 直接使用。这样每个接口不需要重复写判断是否登录的模板代码。Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { HttpSession session request.getSession(); Object loginUser session.getAttribute(loginUser); if (loginUser null) { response.sendRedirect(/login); return false; } // 每30分钟刷新一次有效期限模拟类似滚动的会话过期 session.setMaxInactiveInterval(30 * 60); return true; }第三层角色权限在拦截器或注解层控制。管理员接口必须校验user.getRole() 2不能普通用户改个 URL 就进入后台。我用自定义注解RequireAdmin Spring AOP 的方式实现这样 Controller 里只需要在方法上标一下代码非常干净。4.2 宠物发布与管理图片上传的存储策略宠物发布页最核心的功能是图片上传这个模块的存储策略直接影响后续运维。我当时对比过三种方案方案优点缺点Base64 直接存数据库实现简单一张表搞定数据库膨胀查询极慢完全不可取本地磁盘 Nginx 映射部署简单访问快无需额外服务分布式环境下文件难以共享需要做磁盘同步云对象存储OSS/COS扩容方便自带 CDN需要额外申请账号配置相对繁琐毕设和中小型项目我推荐第二种本地磁盘存储 Nginx 静态映射。实现思路是上传接口接收MultipartFile重命名为 UUID 字符串保留原扩展名按日期分目录存储如/data/pet-images/2025/06/xxx.jpg落库时只存相对 URL/images/2025/06/xxx.jpg。这样既避免了文件名冲突又方便按时间归档清理Nginx 里加一条location /images/指向磁盘目录就能直接访问不经过 Java 应用层响应快很多。这里有一个非常容易踩的坑是重命名时丢失扩展名。我一开始直接用System.currentTimeMillis()当文件名结果用户传的图片无论 JPG 还是 PNG存下来全是无后缀文件浏览器无法正常解析。后来改成从原始文件名里截取扩展名再拼上 UUID 主体彻底解决。图片这块另一个坑是尺寸和大小限制。我最初没限制结果有人传了一张 8MB 的照片当天服务器内存直接被打满。后来在配置里做了约束单张图片最大 2MB并且用 Java 的ImageIO读取宽高超过 2000px 的等比压缩后再落盘。压缩逻辑不复杂但能实实在在省下大量带宽和磁盘空间。4.3 领养申请与审核流程事务和状态更新的坑领养申请是业务核心我把它设计成一个需要事务保护的跨表操作。流程是这样的用户提交申请 → 系统往t_adopt_apply插入一条待审核记录 → 同时把宠物状态从待领养改成审核中 → 同一个事务里两个操作要么全成功要么全失败。如果这两个操作不在一个事务里就会出现极端情况申请记录写进去了但宠物状态没改用户刷两次页面提交了两次申请送养人那边看到的还是一只待领养状态的宠物。所以 Service 方法必须加Transactional(rollbackFor Exception.class)注意这里要声明rollbackFor否则默认只在运行时异常时回滚检查异常时事务照样提交事务形同虚设。审核操作同样需要事务送养人通过某个申请时要做三件事——把申请记录状态改为已通过把宠物状态改为已领养同时把同宠物下所有其他待审核申请批量置为已拒绝。最后这个批量拒绝非常关键否则用户会看到一只已经送出去的宠物还挂着审核中的申请单体验很差。4.4 后台管理端的设计思路管理后台我采用左菜单 右侧内容区的经典布局功能集中在四个页面宠物审核页展示所有待审核宠物支持详情展开、通过/驳回操作。驳回时必须填写原因并且系统自动给送养人发送一条站内信。用户管理页查询用户列表支持冻结/解禁操作。冻结用户后其发布的宠物要同步下架这是一个级联业务操作不能只改用户表一个字段。领养记录页所有成功领养的宠物和领养人信息支持按时间筛选。这里的数据既用于人工回访也用于运营统计。数据概览页展示总数、待审核数、今日新增领养申请数等简单统计。后台管理端最需要注意的是越权防护。我在拦截器基础上加了一层管理员 AOP 切面在进入所有/admin/**路径的 Controller 方法前校验角色。同时新增管理员账号这种高危操作做了二次授权——必须用主管理员权限才能操作防止团队内部一个人手滑把另一个管理员提权成系统管理员。5. 实测踩坑这些错误我花了两周才解决5.1 MyBatis 分页插件和统计查询的 N1 问题系统首页的宠物列表我用了 PageHelper 做分页。正常流程很简单查询前调用PageHelper.startPage(pageNum, pageSize)紧接着的 MyBatis 查询会自动拼接 LIMIT。但我在列表接口里犯了一个经典错误——查询宠物列表时需要关联显示送养人的昵称和头像我当时直接在collection标签里嵌套了另一条 SQL 查询结果列表每展示 10 只宠物就会额外执行 10 次用户信息查询这就是传说中的 N1 问题。排查方法很简单在 MyBatis 配置里打开 SQL 日志观察一次列表请求实际发了多少条 SQL。如果发现主查询一次、关联查询多次基本就是 N1。修复方案有两种如果关联数据不多用连表查询替代嵌套查询一条 SQL 搞定这也是最推荐的方式。如果关联数据复杂且复用率高就先把主数据查出来再按关联 id 批量查一次内存里做映射。5.2 JSON 返回的 LocalDateTime 格式化问题页面表格里要显示申请时间我最初在实体类里用了 Java 8 的LocalDateTime结果前端收到的 JSON 是一段数组[2025, 6, 1, 14, 30, 25]而不是字符串。这是因为 Jackson 默认对 JDK 8 时间类型的序列化支持不完整——需要引入jackson-datatype-jsr310模块并且注册JavaTimeModule才能按yyyy-MM-dd HH:mm:ss格式输出。在 Spring Boot 2.x 里如果引的是spring-boot-starter-webJackson 时间模块已经默认注册了问题一般出在配置上。在application.yml里加这一段即可spring: jackson: date-format: yyyy-MM-dd HH:mm:ss time-zone: GMT8但要注意date-format对LocalDateTime不生效这两个类型走的序列化器路径不同。对LocalDateTime需要单独加注解JsonFormat(pattern yyyy-MM-dd HH:mm:ss, timezone GMT8) private LocalDateTime createTime;或者用全局配 Jackson 自定义序列化器的方式统一处理。我一开始只配了 yml 里的date-format页面还是显示数组排查了半天才发现LocalDateTime要单独指定。5.3 Docker 部署时数据库连接失败和时区问题部署阶段把 Spring Boot 打成 Docker 镜像运行在容器里MySQL 也跑在 Docker 里。第一次启动时应用日志里报的连接错误让我排查了很久——宿主机访问 MySQL 没问题容器里访问同一个地址却连不上。原因很典型容器之间通信不能用localhost要用服务名或者具体的容器 IP。在 docker-compose 里services: mysql: image: mysql:5.7 environment: MYSQL_ROOT_PASSWORD: root123 TZ: Asia/Shanghai volumes: - ./mysql-data:/var/lib/mysql app: build: . depends_on: - mysql environment: SPRING_DATASOURCE_URL: jdbc:mysql://mysql:3306/pet_adopt?useSSLfalseserverTimezoneAsia/ShanghaicharacterEncodingutf8应用容器里的jdbc:mysql://mysql:3306解析到的是 compose 网络中名为mysql的容器而不是宿主机的 MySQL。很多教程教你用localhost在容器化环境下就是通不了。还有蛙泳了一个下午的时区问题——代码里new Date()明明是下午三点存进数据库却变成了早上七点。原因是 MySQL 容器默认时区是 UTC和北京时间差 8 小时设置环境变量TZAsia/Shanghai可以解决容器时区但 JDBC 连接串里的serverTimezoneAsia/Shanghai也不能少两处都设置才算彻底根治。5.4 Linux 服务器上 Tomcat 文件上传临时目录清理问题这个坑真的很隐蔽。Spring Boot 的spring.servlet.multipart.location默认没有指定时上传文件会写入系统临时目录/tmp。Linux 服务器有个定时清理机制会自动删除超过一定时间未访问的/tmp文件。结果就是白天用户上传的图片在 Nginx 里还能访问第二天早上一刷新图片全 404 了磁盘上的文件被系统清掉了。解决办法是在应用配置里指定一个独立于/tmp的上传目录spring: servlet: multipart: location: /data/upload_tmp并且把这个目录确认纳入容器卷的挂载里否则容器重建又丢了。这个坑对部署在真实 Linux 服务器上的项目尤其致命本地开发时根本发现不了。6. 项目上线与后续可以延伸的方向6.1 用 Docker Compose 一键部署 Linux 服务器整个项目我最终在 Linux 服务器上跑通了部署方式是 Docker Compose 编排两个容器——MySQL 和 Spring Boot 应用。Nginx 放在宿主机上主要做三件事代理静态图片请求、反向代理后端接口、托管 Thymeleaf 渲染出来的页面其实 Spring Boot 自带页面访问Nginx 只是统一入口。我把配置文件的完整思路列一下方便你照抄Dockerfile基于openjdk:8-jre-alpine把可执行 JAR 复制进镜像暴露 8080 端口。启动命令直接java -jar。docker-compose.yml定义两个 serviceMySQL 用mysql:5.7挂载数据卷应用服务depends_on: mysql通过环境变量注入数据库连接信息。Nginx 配置文件location /images/指向本地磁盘目录location /反向代理到 8080 端口。Docker Compose 的好处是服务器上一条docker-compose up -d --build就能把整套环境拉起来后续更新只需要重新构建应用镜像。这对毕设答辩演示非常友好——你不需要现场去装 MySQL、配 JDK直接把 Compose 跑起来几分钟就能让老师看到系统在运行。6.2 可以让项目更出彩的几个扩展方向如果你的毕设要做差异化或者项目想持续运营我有几个方向推荐按投入产出比排序推荐算法。宠物领养平台天然适合基于行为的推荐——用户浏览过哪些猫、申请过哪些宠物都可以沉淀成特征数据。最简单的方式是协同过滤找那些和你浏览记录相似的人看他们申请了什么宠物。这一步可以用 Redis 存行为数据MySQL 里加几张行为表算法本身不必很复杂能解释清楚召回-排序的链路就足够加分。Elasticsearch 搜索。当宠物数量超过几千条MySQL 的模糊搜索性能会明显下降。引入 Elasticsearch 做全文检索支持品种 城市 疫苗状态的组合筛选搜索体验会提升一个档次。当然这会对系统架构复杂度有要求如果你只想要效果对几百条数据量来说 MySQL 的 LIKE 查询完全够用。微信小程序端。服务端渲染的页面在手机上体验一般如果有一套 RESTful API做一个微信小程序端是很自然的延伸——用户在小程序里浏览宠物、提交申请管理员在 Web 后台审核。小程序端用原生或者 uni-app 都可以工作量大约是 Web 端的三分之一。这也是最容易被答辩老师认可的应用落地方向。最后再分享一点个人体会我这套系统从建表到部署前后折腾了大概三周真正写业务代码的时间其实只有一半另一半全花在状态流转捋顺和上面这些坑上。说实话宠物领养平台本身的技术难度并不高就是标准的增删改查加状态管理但正因为业务逻辑不复杂反而逼着你把每一个细节做扎实——比如 BCrypt 加盐、事务边界、逻辑外键、容器时区这些东西在玩具项目里看不出来上线跑三天就会原形毕露。如果你正在准备类似的毕设或者想练手 SSM我的建议是先别急着抄代码把状态机画好、表结构敲定、接口清单列出来这三样做好了后面就是填代码的事。项目源码可以在本地搭起来后再尝试用 Docker Compose 部署到云服务器上跑一跑你会发现从本地跑通到线上稳定中间还有很多这里没写完整的细节值得亲身踩一遍。
上一篇/下一篇内容由系统自动关联
返回资讯列表 →