每年到了毕设选题季、课设冲刺期,“学生宿舍管理系统”这个名字总会反复出现在各个技术社区、开源平台和问答帖里。我带了这么多次项目,也看过很多学生拿着类似题目来找我调代码。这个选题之所以经久不衰,核心原因很简单:它足够贴近真实业务,又不过度复杂;技术栈既能体现全栈能力,数据量级也不会把新人吓退。SpringBoot + Vue + Java + MySQL 的组合,更是目前这类毕业设计项目中应用最广泛的技术方案之一。
这篇文章我不打算给你复述一遍源码里的类名和接口名,而是想从“为什么这么做”的角度,把宿舍管理系统拆开揉碎:业务设计怎么想、数据库怎么建、后端骨架怎么搭、Vue 前端怎么对接,以及那些答辩时、部署时、联调时最容易踩的坑。无论你是准备拿它做毕设、课设,还是纯粹想通过这个项目把前后端整条链路打通,下面的内容都值得你花十分钟认真读完。
1. 学生宿舍管理系统:为什么每年都是毕设爆款
1.1 业务复杂度适中,踩不到天花板也够得着门槛
一个合格的管理系统题目,不能太简单也不能太复杂。太简单会被老师批“工作量不足”,比如只做单表 CRUD;太复杂又会把自己绕晕,比如非要搞微服务、分布式事务、消息队列,技术还没学明白先把自己劝退了。
学生宿舍管理系统恰好卡在中间。它有一套完整的业务闭环:宿舍楼管理、房间分配、学生入住与退宿、报修处理、水电费登记、公告发布。这些都是能看得见摸得着的现实场景,哪怕没有任何项目经验,你也很容易理解每个功能是干什么用的。与此同时,它又包含了多表关联查询、状态流转、权限控制、批量导入这类真实企业项目里的高频操作。用一句话概括:麻雀虽小,五脏俱全,正好拿来练手。
1.2 角色权限体系天然清晰,适合讲清楚“权限控制”
宿舍管理系统的用户角色一般分三类:系统管理员、宿管员、学生。三个角色对应的操作边界非常明确。
- 管理员:管楼栋、管宿管账号、看全局统计数据。
- 宿管员:负责分配房间、登记报修、抄水电表、发公告。
- 学生:查看自己的住宿信息、提交报修单、查水电账单。
这个角色设计直接对应着后端接口的权限校验逻辑,也对应着前端路由的访问控制。你在毕业论文或者答辩PPT里讲权限设计,不需要绕圈子,直接从实际业务出发就能解释清楚“为什么要区分角色”以及“每种角色能做什么”。
1.3 技术栈经典,招聘市场认可度高
SpringBoot + Vue 这套组合在中小型公司、外包团队和外包培训机构里使用率极高。SpringBoot 解决了 Spring MVC 时代的配置地狱问题,自带内嵌 Tomcat,一个 jar 包就能跑起来;Vue 的组件化开发让前端代码不再是一堆杂乱的 HTML 和 JS 混在一起。你把这个项目做完,简历上写“熟悉 SpringBoot 后端开发 + Vue 前端开发”,面试官至少不会觉得你的技能树点歪了。
MySQL 更不用说,关系型数据库里最常用的开源方案。这个项目里你能练到表设计、索引、关联查询、事务,够应付大多数初级岗位的要求了。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 技术选型背后的逻辑:SpringBoot + Vue 不是随便选的
2.1 前后端分离 vs 传统 JSP,差距到底在哪
二三十年前的宿舍管理系统往往用 JSP + Servlet 写前后端不分的页面,JSP 里既写 Java 又写 HTML,维护起来极其痛苦。现在毕设如果还这么做,除非老师明确要求,否则基本是自找麻烦。
SpringBoot 作为后端,只负责提供 RESTful 接口、处理业务逻辑、读写数据库;Vue 作为前端,只负责渲染页面、调用接口、维护用户交互状态。两边通过 JSON 数据交互,这就是前后端分离架构。它的好处非常直接:后端接口可以独立测试,前端页面可以在 mock 数据下单独开发,两边互不阻塞。真到了实习或者工作环境里,你会发现大团队普遍就是这个模式。
2.2 版本选择:SpringBoot 2.x 还是 3.x,Vue 2 还是 Vue 3
这是很多刚接触这个选题的人最纠结的问题。
SpringBoot 目前企业生产环境里用的最多的还是 2.x(特别是 2.5 ~ 2.7 版本),因为生态成熟、第三方 starter 齐全、搜问题一搜一大堆。SpringBoot 3.x 基于 JDK 17,整体更新,但对初学者来说很多老教程里的配置会失效,踩坑成本高。做毕设和课设,我建议优先选 2.7.x + JDK 8 这个稳定组合,网上资料最多,遇到问题基本都能搜到答案。
Vue 这边,Vue 2 官方已停止维护,新项目建议直接用 Vue 3。配套的组件库选 Element Plus,界面颜值和处理表单、表格这些常见场景足够优秀。哪怕你学的是 Vue 2,转 Vue 3 也就是一周内的事,语法差异主要在 setup 函数和响应式 API 上,组件化思维是通用的。
2.3 ORM 选型:MyBatis-Plus 为什么是新手友好看板
持久层框架我推荐 MyBatis-Plus,它是在 MyBatis 基础上的增强包,既保留了 MyBatis 手写 SQL 的灵活性,又提供了大量的单表 CRUD 封装。像分页查询,只需要调用 selectPage 方法,传入一个分页对象就搞定;条件查询可以用 QueryWrapper 链式拼接条件,不用像原生 MyBatis 那样写一堆 XML 标签。
这样设计的好处很实际:项目里简单的增删改查不用自己写 SQL,省下大量时间;遇到多表关联这种复杂操作,再手写 SQL,保证你能在答辩时讲清楚 SQL 是怎么写的。
3. 功能模块与数据库设计:先画清楚业务地图再动手
3.1 业务模块拆解:从需求到功能的一步
我见过太多人拿到题目就打开 IDEA 开始建包写代码,结果写到一半发现表结构不对、页面缺功能,推倒重来。正确的顺序是先把业务模块画出来。
宿舍管理系统按我的经验,至少需要分成以下模块:
- 系统管理:管理员/宿管员账号管理、角色权限分配、登录与登出。
- 宿舍楼管理:维护楼栋信息(楼名、楼层数、房间总数、宿管员)。
- 宿舍房间管理:房间号、所属楼栋、床位容量、已住人数、房间状态(空闲/部分入住/已满/维修中)。
- 学生信息管理:学号、姓名、性别、学院、专业、班级、联系方式、入学年份。
- 入住与退宿管理:入住登记(将学生分配到具体房间床位)、退宿登记、调宿记录。
- 报修管理:学生提交报修(房间号、设备类型、问题描述)、宿管受理、完成状态流转。
- 水电费管理:按月录入每个房间的用水量/用电量、自动算费、学生查看账单记录。
- 公告管理:发布公寓通知公告,学生端可查看公告列表。
这些模块并不是互相孤立的,它们之间有很强的数据关联。比如学生入住要先查房间是否还有空床位、房间所属楼栋是否正常开放;报修单要关联房间号,而房间号又对应到楼栋。理顺这些依赖关系,是下一步数据库设计的前提。
3.2 核心表结构设计:字段和类型是一次性的基础
数据库设计是这个项目的命根子。后面所有代码都是围着表转的,表建错了,代码再漂亮也白搭。我按业务域拆成几张核心表,这里把关键字段和类型理由说一下。
第一张是楼栋表 dorm_building。核心字段包括楼栋ID、楼栋名称、楼层数、宿管员ID(外键关联到管理员表)。楼层数用 int,宿管员ID用 bigint。两个楼的宿管员不能混,所以宿管员ID这里可以加唯一约束,简单粗暴但有效。
第二张是房间表 dorm_room。核心字段有房间ID、所属楼栋ID、房间号、床位数量、已住人数、房间状态。房间号和楼栋ID可以做联合唯一索引,防止同一个楼里出现两个101。已住人数在分配和退宿时要处理并发问题,后面我会讲到。
第三张是学生表 student。核心字段:学生ID、学号、姓名、性别、学院、专业、班级、手机号、入住状态。学号必须加唯一索引,这是学生身份的天然主键。注意一个细节:很多学生毕业后学号会被复用,但项目范围内一般不考虑这种事。
第四张是入住信息表 dorm_assignment。核心字段:记录ID、学生ID、楼栋ID、房间ID、床位编号、入住时间、退宿时间、状态。这张表是宿舍管理系统的业务核心流转表,学生与房间的关系都记录在这里。每次入住都新增一条记录,而不是直接改 student 表里的宿舍字段,这样能保留学生住过哪间宿舍的历史轨迹。
第五张是报修表 repair_order。核心字段:报修单ID、学生ID、房间ID、报修类型、问题描述、上报时间、处理状态、处理人ID、完成时间、处理备注。
第六张是水电费表 utility_bill。核心字段:账单ID、房间ID、月份、用电量、用水量、电费金额、水费金额、缴费状态、创建时间。月份和房间ID建议做联合唯一索引,避免同一个房间同一个月被录两次。
还有公告表、操作日志表,逻辑比较简单,不占用太多篇幅。所有表在 MySQL 5.7 以上用 InnoDB 引擎、utf8mb4 字符集。为什么强调 utf8mb4?因为它能存储完整的 Unicode 字符,包括表情,避免用户昵称或者公告内容里出现特殊字符导致报错或乱码。
3.3 表关联关系怎么理,外键要不要建
讲完表结构,再回答一个几乎所有学生会问的问题:表之间要不要建物理外键?
在学校课堂上学数据库原理,老师会强调外键约束的重要性。但在真实的项目开发中,大型系统通常不建物理外键,而是靠代码层保证关联字段的逻辑一致性。物理外键会带来几个麻烦:插入数据必须严格遵循顺序,删除数据受约束限制,高并发写入时还需要额外的锁校验,性能会有损耗。
做毕设的话,我建议在表设计中不建物理外键,但在逻辑上明确外键关系。比如 dorm_room.building_id 对应 dorm_building.id,在实体类里配置好这些关联映射,用逻辑外键的方式维护。答辩时如果老师问起来,你可以从性能和可维护性两个角度说清楚取舍,反而会加分。
4. 后端落地:分层架构与核心接口实现
4.1 包结构与分层思想:不要把所有代码堆在一个类里
SpringBoot 后端代码的组织方式直接反映一个人的工程素养。我推荐按 controller -> service -> mapper 三层结构组织包,每一层只干自己的事。
code复制com.example.dorm
├── controller // 接口层,接收前端请求,返回 JSON
├── service // 业务层,承载核心业务逻辑
│ └── impl // 业务实现类
├── mapper // 数据访问层,MyBatis-Plus 的 Mapper 接口
├── entity // 数据库表对应的实体类
├── dto // 数据传输对象,接收前端参数
├── vo // 视图对象,返回给前端的数据
├── config // 配置类,如跨域、拦截器、MyBatis-Plus 分页插件
├── common // 公共类,统一返回值、异常处理、工具类
├── security // 登录认证、JWT 工具、拦截器
└── DormApplication.java
Controller 里不要写业务逻辑。它的职责很窄:接收参数、调用 Service、返回统一结果。业务逻辑全部放进 Service,这样不同 Controller 复用同一个 Service 方法时,不会出现逻辑重复。
Service 和 ServiceImpl 分开,虽然是很多初学者觉得繁琐的习惯,但这也是目前企业里最常见的规范。它的价值在于接口可以定义契约,实现可以替换,写单元测试时也更容易 mock。很多毕设项目其实不需要如此严谨,但我仍然建议你保留这种写法,因为它是面试时能拿得出手的习惯。
4.2 统一返回结构与全局异常处理
前后端联调最怕的就是接口返回格式不统一。一会儿返回一个 Map,一会儿返回一个 List,一会儿又直接抛异常,前端拿到数据没法处理。我强烈建议先定义一个统一的返回类,不管成功失败,都包一层。
java复制@Data
public class Result<T> {
private Integer code; // 业务状态码
private String message; // 提示信息
private T data; // 数据
}
接口成功时返回 Result.success(data),业务出错时返回 Result.error("房间已满")。前端拿到响应后,先看 code 再取 data,处理逻辑统一、干净。
除了统一返回结构,还要配置全局异常处理。用 @RestControllerAdvice 注解定义全局异常处理器,捕获 BusinessException(业务异常)、参数校验异常、数据库异常、兜底异常。这样即使代码内部出了问题,返回给前端的依然是一个结构明确的 JSON 对象,而不是一个大白页或者一段堆栈信息。这个细节通常不会被写进期末报告里,但答辩时能加不少印象分。
4.3 登录与权限控制:JWT + 拦截器方案
宿舍管理系统的接口不能裸奔,需要登录才能访问。目前最常用的方案是 JWT(JSON Web Token)。
整体流程是这样的:用户登录时传入用户名和密码,后端校验成功后,生成一个带过期时间的 JWT 令牌返回给前端。前端把令牌存在本地,之后每次请求都在 Header 里带上 Authorization: Bearer <token>。后端写一个拦截器(Interceptor),拦截除登录接口以外的所有请求,从 Header 里取出令牌、解析、校验,通过就放行,不通过就返回 401。
角色权限控制我建议用两个层面的组合:
- 后端接口层:在需要权限的接口上用
@RequireRole这类自定义注解,拦截器里读取 JWT 中的角色字段,判断当前用户是否有权限访问。 - 前端路由层:Vue Router 的路由配置里增加路由守卫,根据当前用户的角色过滤页面菜单,学生登录后看不到管理员的界面入口。
前端隐藏入口只是体验层的控制,真正的安全控制一定要在后端实现。这个原则我会在避坑章节再强调一次,也建议你写进毕业论文的安全设计小节里。
4.4 核心业务接口的代码路径:从请求到响应的完整旅程
场景一:学生入住分配房间
这个功能是整个系统的门面,也是最容易被答辩老师问到底的环节。我讲讲它的实现路径。
前台传来一个请求,参数包括学生ID、楼栋ID、房间ID。Controller 接收后丢给 Service。Service 里首先查询房间里当前「已住人数」和「床位容量」做比较,如果已满则抛出 BusinessException("房间已满")。然后开启事务,更新房间的已住人数加一,写入入住信息表,修改学生的入住状态为“已入住”。
这里要注意并发问题。比如最后一个床位,两个学生同时申请,如果代码里先查状态再更新,就存在超卖风险。解决方式很简单:在更新房间已住人数的 SQL 里加一个条件,只有当前已住人数小于床位容量才执行 update。这样并发时即使两个线程都查出已住人数是9,update 时也只会有一个线程成功。
java复制@Transactional(rollbackFor = Exception.class)
public void assignRoom(AssignRoomDTO dto) {
DormRoom room = roomMapper.selectById(dto.getRoomId());
if (room.getOccupied() >= room.getCapacity()) {
throw new BusinessException("房间已满");
}
// 这里通过 SQL 条件更新,防止并发超卖
int rows = roomMapper.increaseOccupied(dto.getRoomId(), room.getCapacity());
if (rows == 0) {
throw new BusinessException("房间已满,请选择其他房间");
}
// 写入入住记录、更新学生状态
...
}
事务的 @Transactional 一定要加上。因为入住涉及三步操作(更新房间、插入记录、改学生状态),任何一步失败都应该整体回滚,否则会出现房间人数变了但学生没住进去的脏数据。
场景二:报修状态流转
报修单状态,我的习惯是这样设计:待处理(0) -> 处理中(1) -> 已完成(2)。学生只能提交新报修和查看自己提交过的报修详情;宿管员可以把待处理改成处理中,处理完成后填写处理备注并标记为已完成。
状态流转的时候要校验当前状态是否合法。比如一个已完成(2)的报修单不能直接改回待处理(0)。项目里可以写一个状态机校验方法,根据当前状态和操作类型判断是否可以流转,这是很能体现业务思考深度的细节。
4.5 数据统计:宿管阿姨最关心的大屏
现在的管理系统如果只有基础 CRUD,工作量不太够看。建议加一个数据统计模块,用 ECharts 做可视化图表。常见的数据指标包括:
- 各楼栋入住率排行
- 院系/专业学生分布
- 月度报修数量趋势
- 水电费收入统计
后端只需要提供几个对应的聚合查询接口,比如按楼栋统计已住人数与床位总数,前端拿到数据后用 ECharts 渲染柱状图、折线图、饼图。这个模块工作量不大,但视觉效果极好,放在论文的截图展示里非常加分。
5. 前端落地:Vue 页面是怎么把数据跑起来的
5.1 前端工程结构:组件化是 Vue 的核心思维
Vue 3 项目的标准目录结构如下:
code复制src
├── api // 每个模块的接口调用函数集合
├── assets // 静态资源,图片、样式
├── components // 公共组件,比如文件上传、表格分页、富文本
├── router // 路由配置与守卫
├── store // Pinia/Vuex 状态管理,存用户信息、token 等
├── views // 页面组件,一个路由对应一个页面
├── utils // 工具方法,封装请求、时间格式化
└── App.vue // 根组件
我强调一下 api 目录的价值。很多初学者喜欢在 .vue 文件里面直接写 axios.get("http://localhost:8080/api/user/list"),这样有两个问题:一是接口地址散落各处,后端一改路径,前端要全文搜索替换;二是没办法统一处理请求拦截和响应拦截。正确的做法是,在 utils 里封装一个统一的 request.js,所有接口按模块拆分到 api 下的不同文件里。
javascript复制// utils/request.js
import axios from 'axios'
const request = axios.create({
baseURL: '/api',
timeout: 10000
})
// 请求拦截器:每次请求自动携带 token
request.interceptors.request.use(config => {
const token = localStorage.getItem('token')
if (token) {
config.headers.Authorization = `Bearer ${token}`
}
return config
})
// 响应拦截器:统一处理 code 与错误提示
request.interceptors.response.use(
res => {
// 仅当业务状态码正常时返回 data
return res.data
},
err => {
ElMessage.error(err.message || '网络异常')
return Promise.reject(err)
}
)
export default request
5.2 路由与登录态:路由守卫与动态菜单
前端路由设计按角色区分,至少包含以下页面:
/login登录页/student学生端首页、我的住宿、报修、账单、公告/admin管理员端:数据看板、楼栋管理、房间管理、宿管员管理/dormitory宿管端:入住管理、报修处理、水电录入、公告发布
在 router/index.js 里配置全局前置守卫。用户没有 token 时强制跳转登录页;有 token 但访问无权限页面时,跳转到个人首页并给出提示。
javascript复制router.beforeEach((to, from, next) => {
const role = localStorage.getItem('role')
if (to.path === '/login') {
next()
} else if (!role) {
next('/login')
} else if (to.meta.roles && !to.meta.roles.includes(role)) {
next('/403')
} else {
next()
}
})
5.3 核心页面开发案例:宿舍分配页面
宿舍分配页面是管理端最复杂也最核心的页面。页面布局大概是这样的:左侧是楼栋树形菜单,点击楼栋后右侧展示该楼栋的房间列表,每个房间卡片上显示房间号、剩余床位、状态。点“分配”按钮弹出一个对话框,输入学号查询学生信息,确认后把学生分配给该房间。
这里涉及两个值得注意的点:一是房间卡片上的“剩余床位”必须实时刷新,分配成功后不仅要调用接口,还要更新当前房间的本地数据;二是分配前最好在对话框里展示该房间的已住名单,宿管员可以看到这个房间住的是谁,避免误分配。这些细节不复杂,但能让系统看起来像一个真正可用的产品,而不是课设演示品。
5.4 前后端联调:不是把接口地址写对就算完
联调阶段常见的问题有三个。
第一个是跨域。开发环境用 Vite 的 proxy 解决。在 vite.config.js 里配置代理,把 /api 前缀的请求转发到后端地址:
javascript复制server: {
proxy: {
'/api': {
target: 'http://localhost:8080',
changeOrigin: true
}
}
}
不要在生产环境依赖前端代理,而是后端配置跨域允许,或者生产环境用 Nginx 反向代理。开发时用 Vite 代理是最省心的方案。
第二个是时间格式。Java 后端返回的 LocalDateTime 默认序列化格式是 yyyy-MM-ddTHH:mm:ss,中间带 T 在页面上很丑。在后端配置里指定格式即可:
yaml复制spring:
jackson:
date-format: yyyy-MM-dd HH:mm:ss
time-zone: GMT+8
第三个是枚举值与前端 label 的映射。比如房间状态 0/1/2,前端显示需要转换成“空闲/已入住/维修中”。我建议后端借助 VO 对象直接返回描述文字,或者提供字典接口,由前端获取映射关系。最忌讳的是前端硬编码拿着数字进行 switch 展示,一旦后端新增状态,前端就会漏。
6. 毕设答辩与实战避坑:那些文档里不会写的经验
6.1 最容易被答辩老师追问的六个问题
我带过的学生里,答辩时不慌的人很少,但凡是真正上手改过代码、做过联调的,面对提问基本都能应对。我总结了六个高频问题,提前准备好就不怕卡壳。
- 为什么选 SpringBoot 而不是 SSM?回答方向:SSM 五个核心配置类手动串联,SpringBoot 自动装配,开发效率高、内嵌容器部署简单。
- 你的系统如何保证数据安全?回答方向:JWT token 过期、密码 BCrypt 加密存储、后端接口权限校验、防 SQL 注入(PreparedStatement)。
- 房间分配并发问题怎么解决?回答方向:SQL 条件更新 + 事务。
- 如果宿舍楼有一万间房,分页查询怎么做?回答方向:MySQL limit + MyBatis-Plus 分页插件,再说一下大偏移量分页的优化思路。
- 登录的 token 存在哪里?会被盗用吗?回答方向:前端 localStorage、考虑加入过期时间与登录设备校验。
- 报表统计怎么实现的?回答方向:聚合查询 + ECharts 渲染,聊聊 MySQL 的 group by 和 count。
6.2 部署打包的常见坑
后端打包发布时,application.yml 里的数据库密码不要用弱密码明文,至少做到环境隔离。有学生把数据库密码写成 root/123456 就因为本地改不仔细,结果部署到服务器之后被黑,整个库被加密勒索。虽然毕设环境一般不会发生,但这种习惯不能留。
前端打包运行 npm run build 之后,产物都在 dist 目录。你可以用 Nginx 托管 dist 目录,同时把后端服务和 Nginx 配在一起。我这里给出一个最小可用的 Nginx 配置思路:
nginx复制server {
listen 80;
server_name localhost;
root /usr/share/nginx/html/dist;
location / {
try_files $uri $uri/ /index.html;
}
location /api/ {
proxy_pass http://localhost:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
注意一定把前端刷新路由的 try_files 配好,否则刷新非首页路径会出现 404。这个坑几乎每个部署 Vue 项目的人都会踩一次。
6.3 数据库乱码、时区、连接池问题的排查清单
数据库相关的坑,我列一个排查清单:
- 表、字段、连接 URL 全部确认是
utf8mb4。 - JDBC 连接串加
useUnicode=true&characterEncoding=utf8,这个参数对 MySQL 5.7 需要显式声明。 - MySQL 8.0 的时区问题比较突出,连接串加
serverTimezone=Asia/Shanghai,否则接口返回的时间会差 8 个小时。 - 连接池报
Too many connections,检查是不是没有释放数据库连接。MyBatis-Plus 的默认连接池是数据库自带的连接池,推荐引入 HikariCP 并设置最大连接数,SpringBoot 2.x 默认自带 HikariCP,直接用即可。
6.4 答辩前一定要走一遍的演示清单
很多学生代码没问题,答辩现场却翻车,原因是没提前走一遍真实流程。我建议答辩前至少完整走五遍以下流程:
- 从零启动后端和前端,不要在答辩现场才临时装依赖。
- 用管理员账号登录,创建楼栋、房间、宿管账号。
- 用宿管员账号登录,完成学生入住、水电录入、报修处理。
- 用学生账号登录,提交报修、查看账单、查看公告。
- 测试错误场景,比如分配已满房间、重复学号录入,确认系统会提示错误而不是崩溃。
6.5 常见问题速查表
| 现象 | 原因 | 解决办法 |
|---|---|---|
| 前端请求报 404 | 请求路径和后端接口不匹配 | 检查 Controller 类上是否有 @RequestMapping 前缀,加上 api 目录中 baseURL 也要对应 |
| 提示 CORS 跨域 | 前端端口和后端端口不一致 | 开发环境使用 Vite 代理;生产环境用 Nginx 反代或后端配置跨域 |
| 时间相差 8 小时 | 数据库连接时区不对或 JVM 时区不对 | 连接串加 serverTimezone=Asia/Shanghai,配置 Jackson 的 time-zone |
| 中文乱码 | 字符集不统一 | 统一为 utf8mb4,注意页面 meta 标签、后端响应编码、数据库编码三处 |
| 启动报找不到主类 | 项目导入不完整或 Maven 未刷新 | 重新 mvn clean install,刷新 Maven 项目 |
| 前端打包体积过大 | 组件库按需引入没配好 | 使用 Element Plus 的按需导入插件 |
写在最后的几点个人体会
做学生宿舍管理系统这个项目的过程中,我反复跟学生强调的一句话是:不要为了“做出来”而写代码,要为了“讲清楚”而设计代码。你写每一段逻辑的时候,都可以问自己一个问题——如果老师问“为什么这里要加一个事务”,我该怎么回答?如果答不上来,说明你还没真正理解这行代码。我对这个项目的定位始终是一致的:它是一件趁手的工具,帮你把前后端分离开发、权限控制、事务管理这些核心概念变成肌肉记忆。这些经验不会只停留在毕设里,以后你进入团队做任何业务系统,都会反复用到相同的思想。真到了那一天,你会发现当年折腾宿舍管理系统时踩过的坑,其实都是最值钱的学费。
