基于SpringBoot+Vue的学生宿舍管理系统设计与实现

发布时间:2026/10/6 14:18:36
基于SpringBoot+Vue的学生宿舍管理系统设计与实现 “学生宿舍管理系统”这个项目我前后做过三个版本才真正跑顺。最早用JSPServlet写后来转到SpringBoot Vue从单体页面改造前后端分离中间踩了不少坑。如果你正打算做一套基于SpringBoot和Vue的宿舍管理类系统或者准备拿这个题目做课程设计、毕业设计那这篇文章应该能帮你省掉一大半查资料的功夫。我不会只贴项目结构和代码片段而是把整套系统的设计思路、表结构怎么建、核心功能怎么拆、部署联调有哪些隐藏问题全部掰开揉碎讲一遍保证你看完能直接上手复制。1. 项目概述与整体设计思路1.1 宿舍管理到底在管什么我们先把问题定义清楚。学生宿舍管理不是简单记录“谁住在哪个房间”它背后是一整套日常管理流程楼栋与房间资源维护、新生入住分配、学生调换宿舍、退宿清空床位、报修登记处理、卫生检查评分、晚归未归记录再加上公告发布和统计数据汇总。以前很多学校宿管科用Excel表加微信群信息分散不说数据一多就乱查一个学生的住宿历史得翻半天记录。这套系统要解决的就是让宿舍管理的核心数据有一个统一入口。管理员能看到全校宿舍的实时占用情况学生能在线提交报修、查看自己的住宿信息宿管员能处理报修、录入卫生检查结果。每一个动作都落到数据库随时可以追溯。说白了它是把一套线下的管理制度做成了软件系统。1.2 为什么选SpringBoot Vue而不是其他组合这个问题我被问过很多次。如果你只是交一个Demo用传统的服务端渲染也能做。但SpringBoot Vue是当前Java后端项目的主流组合好处体现在三个层面。第一个是开发速度。SpringBoot把Spring的XML配置全部干掉内嵌Tomcat一个mvn spring-boot:run就能启动。配合MyBatis Plus单表的增删改查甚至不用写SQL。对于宿舍管理这种以CRUD为主的系统开发效率非常高。第二个是前后端分离。Vue负责页面渲染SpringBoot只提供JSON接口两边通过Restful API通信。这样后端同学不用管HTML前端同学不用碰Java分工明确。哪怕学生管理系统是一个人写完的前后端分离也能让你后期改页面样式时不动后端代码。第三个是就业和答辩友好。SpringBoot和Vue是当前市场上Java后端和前端开发岗位的高频技能做这个题目既能覆盖技能点又能在答辩时讲清楚架构思路。如果是毕设外审老师看到“前后端分离 SpringBoot Vue MySQL”这个组合基本不会质疑技术深度。1.3 功能模块怎么划分才合理我画功能模块图前习惯先按角色分因为不同角色看到的操作入口完全不一样。这套系统我切成三个端。角色核心功能说明管理员楼栋管理、宿舍管理、学生管理、入住分配、调换审批、报修统计、卫生评比、公告管理拥有系统全部权限能查看所有数据宿管员入住登记、报修处理、卫生检查录入、晚归记录、来访登记负责日常楼栋事务不能修改基础数据学生个人信息查看、宿舍信息查看、报修申请、卫生自查、意见反馈面向学生只能管理自己的数据有人会问学生为什么不能自己调换宿舍因为调换宿舍涉及床位释放和重新占用必须有人审核否则会出现一间宿舍同时被多人占用的数据混乱。我最早做的时候就放了自主调换功能结果测试阶段就出了冲突后来改成“申请-审批”模式才稳下来。2. 技术选型与架构拆解2.1 后端技术栈的细节后端我用了SpringBoot 2.7.18不要用3.x。因为3.x是基于Jakarta EE的很多老教程的代码和依赖需要调整对于学生项目来说没必要给自己加难度。JDK用1.8或11都行我推荐1.8兼容性最稳。持久层用MyBatis Plus而不是原生MyBatis。原因很简单宿舍管理系统大部分表都是单表操作MyBatis Plus自带BaseMapper调用selectById、insert、updateById就能完成基本CRUD分页插件PageHelper也集成好了。如果你用原生MyBatis每张表都要自己写Mapper XML工作量翻一倍。数据库连接池我用Druid因为它的监控页面可以看到SQL执行情况排查慢查询很方便。登录认证用JWT 拦截器不引入Spring Security。Spring Security功能强但配置复杂对学生项目来说属于大炮打蚊子。JWT的做法是用户登录成功后生成一个token前端每次请求带上后端拦截器解析token没问题就放行。代码量少逻辑还清晰。2.2 前端技术栈的细节前端我选了Vue 2.6 Element UI。为什么不直接用Vue 3因为Element UI对应Vue 2Element Plus对应Vue 3。虽然Vue 3是趋势但Element Plus在部分组件细节上还有兼容调整网上教程质量参差不齐。对你做项目来说用Vue 2 Element UI反而最省心遇到问题搜索到的解决方案最多。辅助库方面路由用Vue RouterHTTP请求用Axios状态管理如果项目不太复杂根本不用Vuex。宿舍管理页面的筛选条件、表格展示、弹窗表单这些用Element UI的el-table、el-dialog、el-form组件就能搞定。图表统计我用ECharts用来展示各楼栋入住率、报修类型分布。2.3 前后端分离的工作流程讲一下完整的数据流这块答辩经常被问。用户在登录页输入账号密码前端把请求发到后端的/api/login后端验证成功后返回一个加密的JWT token前端把token存到localStorage。之后每一次请求Axios的拦截器会在请求头加上Authorization字段。后端有一个HandlerInterceptor在请求进入Controller之前先解析token如果解析失败直接返回401。后端接口的统一返回结构是一个Result对象包含code、message、data三个字段。code为200表示成功401表示未登录或token过期500表示服务器异常。这样前端拿到结果后根据code判断是提示错误还是渲染数据。每张表的CRUD接口都遵循这个规范代码风格统一后期维护也省事。注意统一返回结构这个习惯一定要养成。我见过很多新手项目接口有的返回Map、有的返回实体、有的直接返回String前端拿到数据一脸懵那才是真的灾难。3. 数据库设计与核心表结构3.1 数据库设计的两条原则宿舍管理系统的表不算多但设计不好照样出问题。我的原则是第一核心表之间用逻辑外键不建物理外键约束。就是说在业务层保证引用关系数据库层面不加外键。原因是物理外键在插入、删除时会有约束检查批量导入数据或者删除楼栋时会很麻烦性能上也有损耗。第二冗余字段适度保留。比如在宿舍表里冗余一个已住人数每次分配床位时更新这个字段。如果不冗余查某栋楼的入住率就得count所有入住记录数据量大一点就慢。宿舍表加一个floor_number字段直接按楼层筛选不用通过房间号字符串去模糊匹配。3.2 核心表结构设计我列几张核心表的建表SQL你直接用就行。用户表存登录账号。注意这里不能只建一张学生表因为管理员和宿管员也要登录所以我单独建sys_user表角色字段区分。sys_user和student表是一对一关联student表存扩展信息。CREATE TABLE sys_user ( id bigint NOT NULL AUTO_INCREMENT, username varchar(50) NOT NULL COMMENT 登录账号, password varchar(255) NOT NULL COMMENT 密码BCrypt加密, real_name varchar(50) DEFAULT NULL COMMENT 真实姓名, role tinyint NOT NULL COMMENT 1管理员 2宿管员 3学生, status tinyint DEFAULT 1 COMMENT 状态1启用 0禁用, create_time datetime DEFAULT NULL, update_time datetime DEFAULT NULL, PRIMARY KEY (id), UNIQUE KEY uk_username (username) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;宿舍表这个是核心中的核心。CREATE TABLE dormitory ( id bigint NOT NULL AUTO_INCREMENT, building_id bigint NOT NULL COMMENT 所属楼栋ID, room_number varchar(20) NOT NULL COMMENT 房间号如A101, floor_number int NOT NULL COMMENT 所在楼层, capacity int NOT NULL COMMENT 可住人数, used int DEFAULT 0 COMMENT 已住人数, gender_type tinyint NOT NULL COMMENT 1男寝 2女寝, status tinyint DEFAULT 1 COMMENT 状态 1可用 0维修中, PRIMARY KEY (id), UNIQUE KEY uk_building_room (building_id, room_number) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;报修表记录整个报修流程。CREATE TABLE repair ( id bigint NOT NULL AUTO_INCREMENT, student_id bigint NOT NULL COMMENT 报修学生ID, dormitory_id bigint NOT NULL, content varchar(500) NOT NULL COMMENT 报修内容, repair_type varchar(50) DEFAULT NULL COMMENT 报修类型水电/家具/门窗, status tinyint DEFAULT 0 COMMENT 0待受理 1维修中 2已完成 3已驳回, handler_id bigint DEFAULT NULL COMMENT 处理人ID, handle_reply varchar(500) DEFAULT NULL COMMENT 处理回复, create_time datetime DEFAULT NULL, finish_time datetime DEFAULT NULL, PRIMARY KEY (id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;其他表比如楼栋表、学生信息表、入住记录表、卫生检查表、公告表结构都比较直接。楼栋表就是楼栋名称、楼栋编号、性别类型、楼层数。入住记录表保存学生和宿舍的关联以及入住时间退宿时更新退宿时间保留历史。3.3 表关系梳理管理系统的表和表之间就那几种关系。楼栋和宿舍是一对多一个楼栋有多个房间。宿舍和入住记录是一对多一个宿舍在不同时间段会住多位学生但同一时间只能有一个学生占用一个床位。学生和入住记录是一对多因为学生可能调换宿舍每次调换生成一条新的入住记录旧记录标记退宿时间。报修表和宿舍是多对一宿舍和学生是一对多关联。卫生检查表和宿舍是多对一每次检查产生一条评分记录。理解这些关系后面写JOIN查询就不容易出错。4. 核心功能的实操实现4.1 登录认证与权限控制登录接口不复杂难的是权限控制不混乱。我用自定义注解配合拦截器实现。先写一个RequireRole注解value值表示允许访问的角色。在需要控制权限的Controller方法上加注解拦截器检查用户角色是否在允许列表里。JWT工具类主要做三件事生成token、解析token、判断token是否过期。token的payload里放userId和role设置过期时间24小时。public class JwtUtils { private static final String SECRET your-secret-key; public static String generateToken(Long userId, Integer role) { return Jwts.builder() .setSubject(String.valueOf(userId)) .claim(role, role) .setExpiration(new Date(System.currentTimeMillis() 86400000)) .signWith(SignatureAlgorithm.HS256, SECRET) .compact(); } public static Claims parseToken(String token) { return Jwts.parser() .setSigningKey(SECRET) .parseClaimsJws(token) .getBody(); } }拦截器里从请求头取Authorization去掉Bearer前缀解析token把userId和role放到request的attribute里方便后续Controller获取当前登录用户。这里有个坑前端用Axios设置请求头token时跨域场景下会先发一个OPTIONS预检请求预检请求不带token。所以拦截器里必须放行OPTIONS请求否则前端所有有自定义请求头的接口都会莫名404。4.2 宿舍分配与调换逻辑宿舍分配是所有功能里最容易出bug的。分配一个学生入住时要做四步验证第一宿舍和学生的性别必须匹配第二宿舍状态必须可用第三已住人数不能超过容量第四学生当前没有未退宿的入住记录。这四步全部通过才能插入入住记录并更新宿舍的used字段加1。因为整个操作涉及多张表更新必须加事务。在Service实现类上打Transactional保证插入入住记录失败时宿舍人数不会被污染。调换宿舍的逻辑是释放旧宿舍占用新宿舍。如果只更新入住记录而不处理两间宿舍的人数增减第二天看统计报表就会发现人数对不上。我第一版就是这个bug调换十个人后楼栋总人数凭空多了不少。正确做法是事务里先更新新宿舍used加1再更新旧宿舍used减1同时把入住记录的dormitoryId改成新房更新时间最后记录一条调换日志。注意宿舍分配功能里事务和并发是两大杀手。真实场景下两个宿管员同时给不同学生分配同一间宿舍的最后一个床位如果不做校验就会出现超住。简单解决方案是在dormitory表加一个校验SQLupdate时带上conditionupdate dormitory set used used 1 where id ? and used capacity。影响行数为0说明没床位了。4.3 报修流程的状态机报修流程是体现系统逻辑的一个好例子。我定义了一个状态机待受理(0) - 维修中(1) - 已完成(2)同时允许受理人点击驳回状态变为已驳回(3)。学生提交报修时前端只传content和repairType后端自动带上当前登录学生的ID和宿舍ID状态默认0。宿管员列表页看到待受理单据点击“受理”按钮状态变为1同时记录handlerId和处理时间。维修完成后宿管员填写处理意见状态变为2。学生端可以查看自己提交的报修单按状态筛选。有人会问为什么报修完成不由学生确认现实中有些学校是学生确认销单但这样容易产生纠纷宿管员说修好了学生说没修完单据就一直挂着。我更建议由宿管员闭环处理学生只能对处理结果留言评价。这样流程短、状态明确管理上也好考核宿管员的响应时效。4.4 卫生检查评分模块卫生检查的评分维度我设计了四个地面清洁、床铺整洁、桌面物品摆放、用电安全。每个维度满分25分总分100。检查记录表存四个维度的分数和总分同时关联宿舍和楼栋方便按楼栋汇总排名。评分的核心功能是月度统计。写一个SQL按楼栋分组求出当月平均分再在前端用ECharts做柱状图展示。这里要注意卫生检查数据会持续增长统计SQL必须加create_time的月份条件并且索引要建在create_time上不然几个月后查询速度就会明显下降。前端实现用el-table展示检查记录支持按楼栋、时间范围筛选每行后面一个“编辑”按钮弹窗修改维度分数。新记录的录入用el-form表单分数输入框用el-input-number组件限制范围0到25校验规则不能漏。5. 项目运行环境配置与部署5.1 本地开发环境准备后端需要JDK 1.8、Maven 3.6以上、MySQL 5.7或8.0前端需要Node.js 14以上。如果你用IDEA直接把项目pom.xml引入等Maven下载依赖。前端在工程目录下打开终端执行npm install安装时间长短看网络情况。我第一次搭建这个环境时被Node版本坑过。项目里的node-sass依赖对Node版本敏感Node版本太高直接编译失败。后来锁定了Node 14.21.3npm install才能通过。现在做Vue 2 Element UI项目建议直接用nvm管理Node版本避免环境问题浪费一下午。5.2 后端启动步骤后端启动的核心是数据库配置。在application.yml里填数据库连接信息注意MySQL 8的驱动类名和时区参数。server: port: 8080 spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/dormitory?useUnicodetruecharacterEncodingutf8serverTimezoneAsia/ShanghaiuseSSLfalse username: root password: yourpassword type: com.alibaba.druid.pool.DruidDataSource把项目附带的dormitory.sql导入数据库执行方式很简单在Navicat或命令行里source文件。启动类直接右键运行看到Spring Boot的启动日志最后一行显示Tomcat started on port 8080就说明成功了。可以用POSTMAN测试登录接口返回token就代表数据库连接正常。5.3 前端启动与打包方式前端启动执行npm run serve默认端口8080和前端端口一致会冲突。没关系前端配置里把代理指向后端开发环境的跨域问题就解决了。在vue.config.js里设置proxy。module.exports { devServer: { port: 8081, proxy: { /api: { target: http://localhost:8080, changeOrigin: true } } } };打包发布时执行npm run build会生成dist目录。这里有两种部署方式。第一种是前后端完全分离把dist目录放到Nginx服务Nginx配置反向代理/api开头的请求转发到后端SpringBoot的8080端口。第二种是合并部署把dist目录里的静态资源复制到SpringBoot的src/main/resources/static目录下打成jar包一起运行。server { listen 80; server_name yourdomain.com; location / { root /usr/share/nginx/html/dormitory; index index.html; try_files $uri $uri/ /index.html; } location /api { proxy_pass http://127.0.0.1:8080; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } }Nginx配置里try_files那行不能省否则前端路由用history模式刷新页面时会404。这个问题几乎所有Vue项目部署都会遇到我记不清帮人排查过多少次了。5.4 生产环境部署要点生产环境和本地有两点不同。第一MySQL密码不能明文写在application.yml里可以通过环境变量注入比如写成${DB_PASSWORD}。第二JWT的SECRET也要换成一个足够长的随机字符串不能把代码里默认的secret带上线。服务器上跑SpringBoot项目用java -jar dormitory-system.jar启动是最简单的。为了可靠建议用systemd配一个服务设置Restartalways这样进程意外退出会自动拉起。数据备份用crontab定期执行mysqldump备份文件保留一周的量就够。6. 常见问题与排查技巧6.1 前后端联调阶段的坑联调是出问题最多的阶段。我列几个高频问题给你参考。现象可能原因解决办法前端请求接口报404后端接口路径和前端请求路径不一致确认Controller的RequestMapping和Axios请求URL完全一致请求能发出但后端收不到参数JSON格式不对字段名映射不上后端用RequestBody接收前端data必须是JSON对象用RequestParam时前端要用params传带token的请求报跨域错误拦截器拦截了OPTIONS预检请求拦截器放行OPTIONS请求处理方式见4.1后端修改代码后前端看不到效果前端代理指向了旧地址检查vue.config.js的target端口确认后端启动端口这里还想多说一句排查思路。遇到接口问题先在浏览器Network里看请求URL、请求方式、请求体和响应体。大多数问题在这一步就能定位不要直接跑到后端打印日志那样效率很低。6.2 数据库连接和数据问题第一个常见问题是MySQL 8连接报Public Key Retrieval is not allowed。这是因为MySQL 8默认的caching_sha2_password认证插件要求客户端做RSA密钥交换。解决方法是JDBC连接串加上allowPublicKeyRetrievaltrue或者直接把依赖的MySQL驱动更新到8.0.20以上。第二个常见问题是中文乱码。建库时没指定utf8mb4存进去的中文变成问号。注意两点建库语句用CREATE DATABASE xxx DEFAULT CHARACTER SET utf8mb4JDBC连接串带characterEncodingutf8两处配合才能彻底解决。第三个问题是springboot版本太高导致的兼容性报错。如果你看到类似“Cannot resolve symbol ‘springframework’”或者依赖版本冲突建议直接改成2.7.18这种稳定版本。不要看到新版本就往上冲稳定压倒一切这句话在做项目时永远成立。6.3 MyBatis Plus的使用细节MyBatis Plus用起来方便但有几个细节不注意会浪费半天。实体类属性用驼峰命名数据库字段用下划线命名MyBatis Plus默认开启驼峰映射不需要加额外注解。但如果数据库字段是createTime不带下划线映射会失败需要TableField(create_time)显式指定。还有一个分页问题。MyBatis Plus的分页插件必须配置PaginationInnerInterceptor才能生效不是引入依赖就自动有分页的。没配置插件时page方法查出来的total永远是0这个问题我在交流群里见过至少五次。Configuration public class MybatisPlusConfig { Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor new MybatisPlusInterceptor(); interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); return interceptor; } }7. 扩展思路与个人经验7.1 把这个项目往上多走一步如果你的时间允许我建议在基础版本上做三个小升级。第一引入Redis缓存楼栋人数统计结果查宿舍首页时直接从缓存取减少数据库压力。第二增加Excel导入导出功能用EasyExcel实现学生批量导入和报修记录导出这也是实际宿管工作中很强烈的需求。第三用WebSocket做通知推送比如学生提交报修后宿管员的待办列表实时收到新提醒不需要手动刷新页面。三个功能在技术上都不复杂但能让你的项目从“毕设Demo”往“可用系统”方向迈一大步简历里也有东西可写。7.2 从做系统到做工程最后聊点个人的体会。做这个项目的过程中你会遇到很多问题搜索、阅读、测试、修复这个循环本身就是工程能力的训练。我在带新手做项目时经常说代码能跑起来只是第一步更重要的是知道“为什么这么写”——为什么分配宿舍要加事务、为什么拦截器要放行OPTIONS、为什么表结构要冗余占用人数。把这些为什么都想清楚以后再碰到类似的管理系统你就能快速设计出靠谱的方案。如果做这套系统是为了答辩建议把注意力放在数据库设计的完整性和权限控制的安全性上。这两个点是最容易展示专业性的地方也是评委老师最常追问的方向。愿你能顺利完成自己的项目。