
做宿舍管理系统这几年陆陆续续看过不少同类项目。市面上打着“学生宿舍信息管理系统”旗号的源码挺多但真能拿到手就跑、跑起来不出乱子的说实话没几个。要么是后端代码缺依赖要么是前端环境版本对不上要么是数据库脚本缺表搞得人一头雾水。今天分享的这套SpringBoot Vue MySQL的学生宿舍信息管理系统我自己在本地完整跑通过从数据库初始化到前后端联调每一步都梳理清楚了。不管你是拿它做毕业设计、课程设计还是想学前后端分离项目的完整写法这份代码都值得参考。这个系统解决的是宿舍管理中特别现实的几个问题学生入住退宿、床位分配、宿管查寝记录、学生报修、水电费登记。这些功能看着不难但真正要把流程跑顺前后端接口设计、数据库表关系、状态流转都需要仔细考虑。系统按角色分为学生和管理员含宿管两条线学生端查寝、报修、缴费管理端管房、管人、管账权限边界清晰。先交代一下我的运行环境后端SpringBoot 2.7.x前端Vue 2 Element UI数据库MySQL 8.0。这套组合也是目前高校项目里最稳的搭配后面我会讲为什么这么选以及如果换了版本会踩哪些坑。1. 项目定位与系统需求拆解1.1 宿舍管理系统到底在管什么先别急着看代码我们把需求捋清楚。很多同学下载了源码第一件事就是启动项目结果看到一堆表和接口根本不知道它们之间是什么关系。这其实是学项目最大的误区——代码只是业务的载体业务逻辑没吃透代码看再多也是散的。学生宿舍管理系统表面上是“管理宿舍”实际上管的是三件事管人、管房、管账。管人指的是学生信息、入住状态、归属楼栋以及管理员和宿管员的账号权限。管房指的是楼栋、楼层、房间、床位的状态维护——哪个房间住了几个人哪个床位空着房间当前是维修中还是可分配。管账就更好理解了学生宿舍不是免费住的涉及到住宿费、水电费、维修费用等记录虽然金额不大但账目得清晰。除了这三件主线的事还要处理一些“日常事务流”。比如学生报修——宿舍灯坏了、门锁坏了学生发起报修宿管或维修工处理并反馈结果再比如晚归记录——宿管每天晚上查寝记录晚归或未归的情况还有公告通知的发布比如停水停电、安全检查通知需要推送给对应的学生。这么一拆你就明白这套系统的核心数据模型了。用户表存不同角色楼栋和房间表维护物理空间学生表关联用户和房间业务表报修、缴费、查寝围绕这三张核心表展开。后面看数据库脚本的时候你会发现一切都是围绕这个逻辑在转的不会觉得表之间关系乱。1.2 角色与业务流程梳理系统里一共有三类角色我给你逐个说清楚超级管理员拥有全局权限可以增删改查所有数据。管理学院内的所有楼栋手动添加或导入学生信息给宿管员分配楼栋管理权限查看所有报修进度、缴费情况。宿管员权限范围限定在自己负责的楼栋内。办理入住和退宿记录晚归、查寝情况登记水电表读数处理本楼栋的学生报修。学生查看自己的入住信息、房间床位信息提交报修工单并查看处理进度查看本宿舍水电费明细并缴费查看楼栋公告。这里有一个设计细节值得注意。很多同学第一次做这种系统会给每个角色单独建一张表比如admin表和student表分开。这套项目没有这么做而是用一张user表存账号基础信息用role字段加以区分学生信息单独用student表扩展通过userId关联。这样做的好处非常明显——登录逻辑只需要查一张表权限控制也统一不需要为每个角色写一遍登录接口。拿入住流程举例。学生提交入住申请管理员在后台审核审核通过后为学生在指定楼层分配房间床位学生信息同步写入宿舍分配表房间的已住人数加一。退宿流程则相反学生申请退宿宿管确认无误后释放床位房间人数减一同时在宿管记录中留档。这个“状态流转”是整个系统的核心逻辑接口层很多方法都是在配合这个流程。2. 技术选型解析为什么是这套组合2.1 前后端分离架构的优势先问一个很实际的问题同样是宿舍管理系统为什么不用传统的JSP Servlet或者更简单的PHP原因在于这套系统面向的场景决定了它必须用前后端分离。学生宿舍管理系统虽然使用者是学生和宿管员但开发者和维护者往往是计算机专业的在校学生。前后端分离带来的最直接好处是分工清晰——有人专攻后端接口有人专攻前端页面两边只需要在接口约定上对齐就行。另一个好处是部署灵活前端打包成静态文件丢到Nginx里后端打成一个Jar包跑在服务器上互不干扰。从学习角度讲前后端分离也是目前企业开发的事实标准。你出去面试说你会SSM那是基础说你会SpringBoot Vue面试官才会觉得你有完整的项目经验。所以这套项目其实不只是一个“交差用的毕设”更是你学习主流开发模式的一个很好的跳板。2.2 SpringBoot、Vue、MySQL各自承担什么角色三个技术各自的定位我用大白话来说。后端SpringBoot负责的是“业务逻辑和数据处理”。所有和数据库打交道的操作入住分配、退宿释放、报修流转、费用计算都在后端完成。前端传过来的是一个HTTP请求后端经过Controller接收、Service处理、Mapper访问数据库最后把处理结果JSON返回给前端。SpringBoot最大的优势是自动化配置你不需要像SSM时代那样写一堆XML配置文件一个启动类就能把整个项目带起来。前端Vue负责的是“页面展示和用户交互”。学生点按钮提交报修网络请求发出去拿到后端返回值之后再刷新页面状态。Vue的双向数据绑定特性让页面状态和用户操作能同步更新不至于出现数据提交了页面还不刷新这种尴尬情况。加上Element UI的组件库表格、表单、对话框、下拉菜单基本都是现成的开发效率很高。MySQL负责“数据持久化”。所有业务数据最终都落在MySQL里。选MySQL而不是Oracle、SQL Server原因很简单它是开源免费的社区资料多安装配置也简单最重要的是在大学生这个群体里用的人最多遇到问题能找到大量现成的解决方案。2.3 为什么不用其他方案也有人问过我现在微服务这么火为什么不用Spring Cloud拆几个服务我要说的是宿舍管理系统这个体量微服务就是杀鸡用牛刀。一个单体应用足够应对几千人的学校宿舍管理需求拆成微服务反而增加了服务间通信和部署的复杂度对学习者和维护者都不友好。还有人问前端为什么不用Vue 3而用Vue 2。这个问题我在后面环境搭建部分会详细展开简单说一句Vue 2的生态更成熟Element UI直接能用网上资料多对新手友好。Vue 3 Element Plus的组合虽然也在推进但很多配套工具的兼容性还需要额外处理。如果你是毕业设计周期紧张用Vue 2的方案明显更稳。3. 后端核心实现从表设计到接口落地3.1 数据库表设计数据库是整套系统的地基。我打开项目的SQL脚本把核心表给你过一遍每一张表的定位和关键字段都会说清楚。第一张是用户表user字段包括id、username、password、role、realName、phone、createTime。password字段存的是MD5加密后的值登录时把前端传过来的密码也做MD5再比对。这里多说一句MD5说实话不是最安全的方案但在教学项目中足够用了真正要上生产可以用BCrypt。系统里role字段的取值是0学生、1宿管、2管理员登录后的所有权限判断都基于这个角色值。第二张是学生信息表student字段包括id、userId、sid学号、name、gender、college学院、className班级、buildingId、roomId、bedNo床位号、status住宿状态。这张表是整个住宿管理的核心表它通过buildingId和roomId与楼栋表、宿舍表建立关联。status字段很关键判断学生是“在住”“已毕业”还是“申请退宿”状态。第三张是楼栋表building字段包括id、buildingNo楼栋编号、buildingName楼栋名称、floors楼层数、managerName宿管姓名、managerPhone。第四张是宿舍表room字段包括id、buildingId、roomNo房间号、floor所在楼层、beds总床位数、occupied已住人数、status空置/部分入住/已满/维修中。房间的状态是通过occupied和beds动态计算的查询空房直接比较这两个字段就行不需要额外维护状态字段这是设计上的一个巧妙之处。第五张是报修表repair比如报修人、房间号、报修内容、报修时间、处理状态0待处理/1处理中/2已完成、维修人、处理时间。第六张是水电费表fee记录楼栋、房间号、月份、水表读数、电表读数、应缴金额、缴费状态。第七张是考勤表attendance记录查寝日期、学号、姓名、宿舍楼栋、房间号、状态正常/晚归/未归、登记人。这几张表之间的关联关系是这样的user和student通过userId关联student和room通过roomId关联room和building通过buildingId关联业务表repair和fee通过roomId绑定到具体的房间和用户。权限校验的逻辑就是沿着这些关联关系一层层查下去的。3.2 后端目录结构与分层打开SpringBoot后端项目的目录你会看到这样的结构src/main/java/com/example/dormitory/ ├── controller/ # 控制层接收前端请求 ├── service/ # 业务层处理核心逻辑 ├── mapper/ # 数据访问层操作数据库 ├── entity/ # 实体类对应数据库表 ├── config/ # 配置类比如CORS跨域配置 ├── interceptor/ # 拦截器比如登录验证 ├── util/ # 工具类比如MD5加密 └── common/ # 公共返回结果封装这个分层结构对应的是经典的Controller-Service-Mapper三层架构。Controller层只做参数接收和结果返回不在方法里面写业务逻辑。Service层是核心比如办理入住的方法要同时处理学生状态更新、房间已住人数更新、入住记录插入这三件事这就是一个完整的事务。Mapper层是MyBatis与数据库的交互层执行SQL语句并映射结果到实体类。这里要特别推荐这种项目里一个很常用的细节统一响应结果类。这个类通常叫Result或者AjaxResult里面包含code、msg、data三个字段。比如登录成功返回{code: 200, msg: 登录成功, data: {token: xxx}}登录失败返回{code: 500, msg: 用户名或密码错误, data: null}。前端接受到的每个响应先判断code是不是200再决定渲染还是报错这就避免了前端对错误格式做各种兼容处理凭空省掉一堆麻烦。3.3 接口设计与JWT认证后端接口的设计遵循RESTful风格我挑几个关键接口给你梳理POST /api/user/login登录接口接收用户名和密码验证通过后返回token和用户信息。这个token是整个系统登录态的核心。GET /api/room/available查询当前可以入住的房间列表根据楼栋过滤并且排除掉已满和维修中的房间。这个接口给分配宿位的流程用。POST /api/student/checkIn办理入住接口接收学生信息和房间ID内部执行学生信息更新、房间占用数1、初始化缴费记录三个操作。POST /api/student/checkOut办理退宿接口释放床位房间占用数-1更新学生住宿状态为“已退宿”。POST /api/repair/add学生提交报修工单其中报修人、房间号默认从当前登录用户的信息中提取学生不需要自己填。GET /api/repair/myList学生查看自己提交的报修列表按报修时间倒序排列。POST /api/fee/pay水电费缴费接口更新缴费状态为已缴记录缴交时间。关于登录认证这套项目用的是JWT的方案实现思路是用户登录成功后后端生成一个带有用户ID和过期时间的签名token前端把这个token存在本地存储里之后每次发请求都在请求头里带上Authorization: Bearer token后端写了一个登录拦截器对于除登录接口以外的所有请求都先检查token是否有效如果token无效直接返回401。JWT的好处是后端不需要保存session服务重启后用户也不需要重新登录对前后端分离的项目非常友好。坏处是token在过期之前无法主动失效对于学生项目来说这点影响不大。如果你想把代码写得更工程化一点可以在后端加一个拦截器把token的过期时间做成可配置项配合前端在axios拦截器里做401统一跳转到登录页。4. 前端核心实现Vue页面组织与交互4.1 前端项目结构前端项目是用Vue CLI初始化的打开目录同样能看出清晰的分层思路src/ ├── api/ # 接口请求封装 ├── assets/ # 静态资源 ├── components/ # 公共组件比如侧边栏、头部导航 ├── router/ # 路由配置 ├── store/ # 状态管理Vuex ├── views/ # 页面组件 │ ├── admin/ # 管理员端页面 │ ├── student/ # 学生端页面 │ └── login.vue # 登录页 ├── utils/ # 工具函数比如axios封装、token存储 └── App.vue # 根组件views目录下按角色分的这两个子目录admin和student是前端组织页面的关键思路。这样做的好处是页面归属清晰管理员相关的页面都放在admin目录里学生相关的页面放在student目录里新增一个页面时不需要纠结往哪里放。登录进来之后前端会根据当前用户的角色动态渲染不同的页面组件对应的路由配置里也会通过路由守卫做权限拦截。4.2 路由串联页面路由配置是前端的脉络我把关键的路径列出来/login登录页/admin/home管理员首页展示宿舍楼栋总数、学生总人数、今日报修工单数的统计面板/admin/building楼栋管理页支持楼栋的增删改查/admin/room房间管理页支持查看房间入住详情、分配学生入住/admin/student学生管理页支持学生信息的添加、修改、退宿、导入导出/admin/repair报修处理页支持查看所有报修工单、指派处理人、关闭工单/admin/fee水电费管理页支持按房间查看缴费状态、录入本月水电读数和费用/admin/attendance查寝记录页支持录入和查看晚归未归记录/student/home学生首页展示当前入住信息、本宿舍室友列表、最近公告/student/repair我的报修页学生提交报修、查看进度/student/fee我的缴费页查看水电费明细、在线缴费路由配置中我做了一个全局前置守卫每次跳转路由前先判断本地有没有token。如果没有token直接重定向到登录页。如果有token还要判断当前用户是否已经拉取了用户信息角色是否匹配目标路由的权限要求。这个判断逻辑对于防止用户在浏览器地址栏直接输入URL绕过登录很有用。4.3 Axios请求封装与权限控制前端所有的HTTP请求都集中在一个文件里统一管理而不是在页面里直接用axios乱发。核心思路是创建一个axios实例绑定baseURL和超时时间然后通过请求拦截器和响应拦截器做全局处理。请求拦截器的逻辑是发送请求前从localStorage取出token如果存在就加上Authorization请求头。响应拦截器的逻辑是收到响应后统一判断code如果code是200就正常返回数据如果code是401就清空本地存储并跳转登录页如果是其他错误就用Element UI的Message提示后端返回的错误信息。API文件也按功能模块分组比如repair.js里存放addRepair、getMyRepairs、getAllRepairs这些方法fee.js里存放getMyFee、payFee这些方法。页面组件里只需要引入对应的方法并调用完全不感知HTTP请求的细节。这样做的最大好处是如果后端的接口地址变了只需要改api目录里的一个文件不需要去每个页面里找。前端还有一个值得关注的细节不同的登录角色登录成功后跳转的首页路径不一样。管理员登录跳转到/admin/home学生登录跳转到/student/home。这个逻辑写在登录页的登录成功回调里根据后端返回的role字段判断。如果后端返回的role是0就跳学生端是1或2就跳管理端。5. 环境搭建、启动配置与可直接运行的保障5.1 环境版本匹配这套项目“可直接运行”的前提是你的开发环境版本要和项目用到的版本对得上。我按我的环境给你列一份清单JDK1.8或以上项目用的是Java 8的语法Maven3.6Node.js14.x或16.x推荐14Vue 2项目在14上跑最稳MySQL5.7或8.0都可以8.0需要注意驱动和连接串的配置差异IDE后端用IDEA前端用VS Code这里有一个很关键的坑点要提醒你。如果你用的是Spring Boot 2.7.x版本对应MySQL驱动应该是mysql-connector-java8.0.xpom.xml里不需要指定数据库驱动的版本号Spring Boot会自动匹配。但如果把SpringBoot升到3.x就必须把javax.*的包替换成jakarta.*代码里所有import javax.servlet的类都要改新手很容易卡在这一步。所以如果你不想折腾就用项目自带的SpringBoot 2.7.x版本跑不要图新版本。5.2 数据库初始化数据库初始化是整个“可直接运行”流程中最重要的一步。项目里自带了一个SQL脚本通常放在sql/dormitory.sql这个路径下。初始化的方法是先用Navicat或MySQL命令行创建一个数据库比如create database dormitory default charset utf8mb4;然后用source命令或图形化工具导入SQL文件。导入完成后你会看到项目中用到的所有表以及初始数据都被创建好了。初始数据里包含几个测试账号这是快速验证系统的钥匙。管理员账号通常叫admin密码是123456已做MD5加密存储学生账号可能是2023001密码同样是123456。用这些账号登录系统你就能立刻看到不同角色的页面效果。需要注意的是SQL脚本里的初始密码都是MD5加密后的值如果你临时改密码要记得用MD5方式重新生成。关于utf8mb4还有一个细节。MySQL的utf8字符集其实是不支持emoji和一些生僻字的utf8mb4是utf8的超集。如果你的SQL脚本里用到了emoji字符集相关的字段定义建立连接时一定要在连接串上加上characterEncodingutf8参数并确认JDBC连接串的最后没有多余的空格或字符。5.3 前后端启动步骤启动整个项目我建议按下面的顺序操作第一步启动MySQL服务。Windows用户可以在服务管理器里找到MySQL服务并启动MAC用户用brew services start mysql或sudo systemctl start mysqld。第二步导入数据库。用Navicat连接MySQL执行SQL脚本确认脚本能从头跑到尾不报错。这里如果报错多半是SQL脚本在生成时用的MySQL版本和你的环境不兼容问题一般出在字符集或语法上。第三步启动后端。用IDEA打开后端项目等待Maven自动下载依赖。下载完成后修改application.yml里的数据库连接配置主要是数据库名、用户名、密码。改好之后运行启动类看到Spring Boot的启动日志出现“Started DormitoryApplication”就说明后端已经跑起来了默认端口是8080。第四步启动前端。用VS Code打开前端目录在终端里执行npm install安装依赖这个步骤可能耗时几分钟。装完依赖后执行npm run serve看到编译成功的输出浏览器访问http://localhost:8081前端就起来了。第五步验证前后端联调。浏览器打开前端地址先用管理员账号登录。如果登录成功并跳转到管理端首页说明前后端联调成功。如果登录时提示跨域错误打开浏览器的开发者工具查看网络请求的响应头确认后端是否开启了CORS跨域配置。我在这个项目里看到后端config目录下专门写了CORS配置类允许了8081端口的跨域请求正常情况下不会出现跨域问题。6. 实际部署中常见的5类问题与排查技巧6.1 端口冲突与跨域启动后端时控制台报Port 8080 was already in use说明8080端口被其他程序占用了。解决方法是换一个端口改application.yml里的server.port配置项但改了之后要同步修改前端vue.config.js里的代理配置否则前端请求还是发到8080端口去。跨域问题一般表现为前端请求发不出去控制台报CORS policy: No Access-Control-Allow-Origin header。解决方案是在后端写一个WebMvcConfigurer的配置类重写addCorsMappings方法允许指定来源和指定请求方法的跨域请求。还有另一种做法是前端配置代理把/api开头的请求转发到后端这样浏览器看到的是同源请求就不会触发跨域拦截了。两套方案我都试过如果你是在本地开发调试用代理更省心如果你要把前端打包部署到Nginx上后端配CORS更合适。6.2 MySQL连接失败与驱动问题MySQL连接失败是最常见的问题具体表现是报Access denied for user rootlocalhost或者Communications link failure。前者是用户名密码不对改application.yml里的配置就行后者多半是MySQL服务没启动或者连接串里的端口号不对。还有一个容易被忽略的坑是时区问题报错信息里如果有CST相关字样就在连接串后面加上serverTimezoneAsia/Shanghai参数。如果你用的数据库是MySQL 8.0连接串里需要加useSSLfalse参数否则会报SSL证书验证错误。MySQL 8.0默认使用caching_sha2_password认证插件而连接驱动如果版本太老就会报Authentication plugin caching_sha2_password cannot be loaded的错误。这时候去pom.xml里看看有没有指定mysql-connector-java的版本如果没有就加上8.0.x版本的依赖。6.3 Vue依赖安装慢与node-sass报错npm install装了一半卡住或者报node-sass安装失败这是Vue 2项目最常见的坑。node-sass是一个需要编译本地代码的库国内网络环境下下载二进制文件经常超时。我建议在项目根目录建一个.npmrc文件内容写上registryhttps://registry.npmmirror.com和sass_binary_sitehttps://npmmirror.com/mirrors/node-sass/这样国内下载速度会快很多。另外提醒一下如果你本地的Node版本太高比如18以上可能出现node-sass编译失败的问题报错信息里通常会有Module build failed和node-gyp字样。解决方案是直接换成Node 14版本或者把项目里的node-sass换成dart-sass。换dart-sass的方法是把package.json里的node-sass删掉改成sass然后重新npm install。这个坑很隐蔽我当初弄了整整一个下午才搞明白。6.4 SpringBoot版本过高导致的依赖冲突下载源码的时候如果原项目用的SpringBoot版本比较老而你的Maven仓库里缓存了较高版本的依赖启动时可能报一些奇怪的错误比如NoSuchMethodError或者ClassNotFoundException。遇到这种情况我建议打开pom.xml看父pom里spring-boot-starter-parent的版本号把它降到一个已知稳定的版本。对于这个宿舍管理系统我推荐2.7.x。如果你的项目用了springfoxSwagger的依赖SpringBoot 2.6以上的版本会默认使用SpringMVC的PathPattern匹配方式而springfox不兼容这种新特性需要手动在application.yml里加上spring.mvc.pathmatch.matching-strategyant_path_matcher这个配置项否则Swagger会起不来。这种配置细节不踩一次是真的记不住。6.5 打包后前端刷新404与接口地址问题npm run build之后把dist目录部署到Nginx刷新页面时报404。这个问题的原因很简单前端是单页应用路由切换是通过history API实现的但Nginx不知道应该把请求全部指向index.html。解决方法是修改Nginx配置在server块里加一条try_files $uri $uri/ /index.html;让非静态资源请求都落到index.html上。还有一个容易忽略的问题打包部署后接口请求404。本地开发时前端通过proxy代理访问后端接口打包后没有dev server的代理了前端请求必须改为直接访问后端地址。一个解决办法是在vue.config.js里用环境变量控制baseURL本地用/api打包后配置一个完整的后端地址比如http://服务器IP:8080/api。这样部署到不同环境时只需要修改环境变量文件不需要动代码。写在最后这个项目的价值不只是“能跑起来交差”这么简单。如果你真的把每一张表的关系、每一个接口的调用链路都捋一遍会发现它其实是一套比较完整的前后端分离开发范式。从需求分析到数据库建模从后端接口设计到前端权限控制每一条线都能对应到一个实际业务场景。我自己在带毕设的过程中发现很多同学拿到源码后喜欢直接跑去运行跑通了就觉得自己“会了”。但这样其实错过了一个特别好的学习材料。我建议你按这样的顺序去读先读SQL脚本把表关系梳理出来再读后端的Service层看核心业务逻辑是怎么落地的然后读前端的页面把接口调用和数据显示串联起来最后才去修改功能、增加模块比如在系统里加一个宿舍调换模块或者把导出Excel的功能做成通用组件在你自己的毕业设计里就能体现创新点。如果你在这套系统的启动过程中遇到其他问题欢迎留言交流。问题截图、报错日志和你的环境版本一起发出来我看到了会尽量帮你定位。站在前人的肩膀上修改和扩展本来就是学习编程最有效的路径。