起因

校园宿舍管理系统听起来很像课程设计。

学生信息、宿舍号、报修工单、公告管理,这些功能都很常见。刚开始我也觉得它就是一个 CRUD 项目,写几个接口、连个数据库、页面能点就行。

但真正写完之后才发现,CRUD 只是最外面那层壳。只要你稍微把功能做完整一点,就会遇到很多实际问题。

项目在这个仓库里:yfgug/project

做了哪些功能

这个系统主要有几个模块:

  • 学生管理:增删改查、多条件搜索、批量删除、头像上传。
  • 报修工单:提交、处理中、已解决、删除。
  • 公告管理:发布、编辑、删除。
  • 登录保护:连续输错密码后短时间锁定账号。
  • 文件上传:限制后缀、限制大小、UUID 重命名。

技术栈是 Spring Boot 2.5 + MyBatis + MySQL。后端用 RESTful API,返回值统一包了一层 Result<T>,配置放在 YAML 里,数据库连接池用 HikariCP。

最先踩到的是查询

学生管理里最常见的需求就是搜索。

只按姓名搜很简单,只按宿舍号搜也很简单。但真实页面里经常是组合条件:姓名、性别、宿舍号、入住日期范围,用户想填哪个就填哪个。

如果每种组合都写一条 SQL,很快就会变成灾难。

后来我用 MyBatis 动态 SQL 来处理:

  • 有姓名就拼姓名条件。
  • 有性别就拼性别条件。
  • 有宿舍号就拼宿舍号条件。
  • 有日期范围就拼日期范围。
  • 批量删除用 <foreach> 展开 id 列表。

这件事让我第一次比较直观地感觉到,框架不是为了炫技,是真的能救命。

文件上传比想象中麻烦

头像上传一开始看起来也很简单:前端传文件,后端存起来,再把路径写进数据库。

但问题很快就来了:

  • 用户传的文件是不是图片?
  • 文件太大怎么办?
  • 两个人上传同名文件会不会覆盖?
  • 上传目录怎么映射成可访问路径?

最后的处理方式是:

  • 只允许 jpg/jpeg/png/gif/bmp/webp
  • 限制 2MB 大小。
  • 用 UUID 重命名。
  • 单独做上传配置和资源映射。

这些细节不写,功能也许能跑。但一旦真的给别人用,就很容易出问题。

登录防暴力破解

这个功能不复杂,但我觉得挺有意思。

我用 ConcurrentHashMap 记录登录失败次数。同一个账号连续输错 3 次,就锁定 5 秒。

这当然不是专业安全方案,也不能替代验证码、限流、审计日志这些东西。但对一个练习项目来说,它至少让我开始思考”接口不能只考虑正常路径”。

以前写登录接口,我只会想密码对不对。现在会多想一步:如果有人一直试密码怎么办?

写完之后的感觉

这个项目最大的价值,不是它有多少功能,而是它把后端常见的几件事都串了一遍:

  • 接收请求。
  • 校验参数。
  • 调用业务层。
  • 访问数据库。
  • 处理文件。
  • 返回统一结果。
  • 让前端页面真的能用。

写之前我觉得 Spring Boot 是一堆注解。写完之后再看,它其实是在帮我把这些重复但重要的工作组织起来。

项目不大,但它让我对”一个后台系统应该长什么样”有了更清楚的感觉。