简介:这份资源面向计算机专业学生与Java Web初学者,提供一套基于Java的宿舍报修管理系统完整毕业设计资料,包含论文与配套源码,可用于课程设计、毕业设计参考或校园后勤维修管理场景的技术学习。压缩包共1个docx文件,约4.78MB,内容涵盖系统摘要、绪论、相关理论与技术、系统分析等章节,围绕Java语言、SpringBoot框架、Vue前端与MySQL数据库展开,并涉及Navicat、IDEA与Tomcat等工具的使用说明。系统功能覆盖用户管理、维修员管理、宿舍类型与信息管理、配件分类与设备管理、维修类型管理、宿舍分配、报修信息与接单管理、配件申请及维修进度管理等模块,论文对可行性分析、需求与设计思路有较完整论述。目前已有433人学习,适合需要参考完整论文结构、理解前后端分离实现方式并对照功能模块梳理开发思路的读者。
1. 从一张手写报修单说起:这套 Java 宿舍报修系统到底解决什么问题
宿舍楼管阿姨桌上那本翻烂的报修登记本,大概是很多高校后勤最真实的写照:学生跑来口头说一句“302 厕所漏水”,阿姨拿笔一记,维修师傅什么时候看到全凭缘分,修没修完也没人回访。这套基于 Java 的宿舍报修管理系统,干的就是把这本登记本搬进浏览器的事。后端 Java + SpringBoot 提供接口,前端 Vue 做交互,MySQL 存数据,Navicat 管库,IDEA 开发、Tomcat 部署,一套典型的教学级全栈组合。它把管理员、用户、维修员三类角色串成一条完整链路:学生在线下单报修,维修员接单并申请配件,管理员在后台盯着宿舍信息、配件库存和维修进度。适合拿来做课程设计、毕业设计,也适合想练手 SpringBoot + Vue 前后端分离的开发者照着跑一遍。
2. 技术栈与目录结构:一套标准的前后端分离骨架
2.1 为什么是 SpringBoot + Vue 这套组合
这个项目的技术选型没有太多花活,但每一步都踩在教学项目的舒适区里。后端用 Java 语言配 SpringBoot 框架,最大的好处是省掉了传统 SSM 那套 XML 配置的折磨——SpringBoot 自带容器扫描和自动装配,一个启动类加几个注解就能把 Web 服务拉起来,对于要在一两个月内交出完整系统的场景来说,这是实打实的效率。前端选 Vue,是因为它上手曲线平缓,模板语法接近 HTML,配合 Element UI 这类组件库,表格、分页、弹窗这些后台管理页面的高频元素基本是复制粘贴改字段名。数据库 MySQL 负责持久化,Navicat 做可视化管理,建表、改字段、导数据都比命令行顺手。服务器用 Tomcat 承载,IDEA 作为集成开发环境把编码、调试、打包串起来。
需要说清楚的是,这套组合里前后端是分离的:Vue 打包后的静态资源可以单独部署,通过 HTTP 请求调用 SpringBoot 暴露的接口,两边靠 JSON 通信。这种结构的好处是前端改页面不用重启后端,后端改逻辑也不影响前端调试,坏处是跨域问题得自己处理——常见做法是在 SpringBoot 里加一个全局跨域配置类,或者在 Vue 开发服务器里配 proxy 代理。我一般倾向后者,开发阶段省事,上线时再用 Nginx 统一转发。
2.2 目录结构长什么样
拿到源码后先别急着点运行,把目录翻一遍心里才有底。这类项目通常是两个独立工程放在一个压缩包里,一个后端一个前端,结构大致如下:
dorm-repair/ ├── backend/ # SpringBoot 后端工程 │ ├── src/main/java/ │ │ └── com/example/repair/ │ │ ├── RepairApplication.java # 启动类 │ │ ├── controller/ # 接口层,按业务分文件 │ │ │ ├── UserController.java │ │ │ ├── RepairController.java │ │ │ └── ... │ │ ├── service/ # 业务逻辑层 │ │ ├── mapper/ # 数据访问层(MyBatis) │ │ ├── entity/ # 实体类,与表字段对应 │ │ └── config/ # 跨域、拦截器等配置 │ ├── src/main/resources/ │ │ ├── application.yml # 数据库连接等配置 │ │ └── mapper/ # MyBatis 的 XML 映射文件 │ └── pom.xml # Maven 依赖 ├── frontend/ # Vue 前端工程 │ ├── src/ │ │ ├── views/ # 页面组件,按模块分目录 │ │ ├── api/ # 接口请求封装 │ │ ├── router/ # 路由配置 │ │ └── main.js # 入口 │ ├── package.json │ └── vue.config.js # 开发代理配置 └── sql/ └── dorm_repair.sql # 建库建表脚本后端的分层是标准的 Controller → Service → Mapper 三层,实体类字段和数据库表一一对应,MyBatis 的 XML 里写 SQL。前端 views 目录下每个业务模块一个文件夹,里面放列表页和编辑弹窗。sql 目录里的脚本是跑通项目的关键,先导入它再启动后端,否则接口一调就报“表不存在”。
2.3 数据库表设计的关键几张
从论文的物理设计部分能看出,这套系统的表是按业务实体拆的,核心几张值得先摸清:
| 表名 | 作用 | 关键字段 |
|---|---|---|
| users | 管理员账号 | username、password、role |
| yonghu | 用户(学生)信息 | 用户账号、姓名、联系方式 |
| sushexinxi | 宿舍信息 | 宿舍名称、类型、楼栋、房间号、可住/已住人数 |
| sushefenpei | 宿舍分配 | 用户账号、床位号、分配日期 |
| token | 登录凭证 | userid、token、过期时间 |
token 表的存在说明登录不是简单的 session 方案,而是登录成功后发一个 token,后续请求带着它做身份校验。这种设计在前后端分离项目里很常见,因为前端拿 token 存本地,刷新页面不掉登录态。宿舍信息表里“可住人数”和“已住人数”分开存,是为了分配床位时能实时算剩余容量,避免超分。
3. 跑起来:从导库到登录的完整步骤
3.1 环境准备与数据库导入
动手之前把环境对齐,版本不匹配是新手翻车的第一大来源。需要准备的东西:JDK 8 或以上(SpringBoot 2.x 系列对 JDK 8 友好)、Maven 3.6+、MySQL 5.7 或 8.0、Node.js 14+ 配 npm、IDEA 和 Navicat。装好后先确认命令行里java -version、mvn -v、node -v都能正常输出。
数据库这一步别偷懒,用 Navicat 连上本地 MySQL,新建一个库,字符集选 utf8mb4,然后运行 sql 目录下的脚本:
-- 新建数据库,字符集用 utf8mb4 避免中文乱码 CREATE DATABASE dorm_repair DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; -- 导入脚本后确认核心表是否建好 USE dorm_repair; SHOW TABLES; -- 预期能看到 users、yonghu、sushexinxi、sushefenpei、token 等表脚本里通常还会插入一条管理员初始账号,导入完去 users 表里看一眼,记下用户名和密码,后面登录要用。如果 SHOW TABLES 出来的表名是乱码或者缺表,多半是脚本编码不对,用 Navicat 的“运行 SQL 文件”功能重新导一次,别用复制粘贴。
3.2 后端配置与启动
后端工程用 IDEA 打开 backend 目录,等 Maven 把依赖拉完。然后改application.yml里的数据库连接,这是必须动的地方:
spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/dorm_repair?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai username: root password: 你的数据库密码serverTimezone这个参数别省,MySQL 8.0 驱动不配时区经常报连接失败。url 里的库名要和上一步建的一致。改完找到启动类,右键 Run,控制台出现 Tomcat started on port 8080 之类的日志就说明起来了。这时候浏览器访问http://localhost:8080可能是个 404 或者 Whitelabel 页面,正常,因为后端只提供接口,没有首页。
验证接口通不通,可以随便挑一个查询接口在浏览器里敲,比如用户列表接口,能返回 JSON 就说明数据库链路是通的。如果报 500,先看控制台异常栈,十有八九是表名或字段名对不上,回去核对实体类和表结构。
3.3 前端启动与联调
前端工程进 frontend 目录,先装依赖再跑:
# 安装依赖,国内网络慢可以换镜像源 npm install # 启动开发服务器,默认 8081 或 8082 端口 npm run serve启动前看一眼vue.config.js里的代理配置,确认它把/api之类的请求前缀转发到了http://localhost:8080。如果没配代理,前端直接请求后端就会撞上跨域,浏览器控制台一片红。配好代理后,浏览器打开前端地址,用之前记下的管理员账号登录,能进后台首页、左侧菜单能点开各个管理模块,这条链路就算跑通了。
提示:前端端口和后端端口不能冲突,如果 8080 被后端占了,前端开发服务器会自动换端口,以控制台实际输出为准。
3.4 三类角色的功能走查
跑通登录后别急着改代码,先把三类角色的主流程各走一遍,心里才有业务全貌。管理员登录后能看到用户管理、维修员管理、宿舍类型、宿舍信息、配件分类、配件设备、维修类型、宿舍分配、报修信息、报修接单、配件申请、维修进度这一整排菜单,每个菜单基本是“列表 + 新增/编辑/删除”的套路。用户(学生)登录后能查宿舍信息、提交报修单、看自己的报修记录和维修进度。维修员登录后能看派给自己的单子、接单、申请配件、更新维修进度。走查时重点看报修单从提交到接单再到完成的状态流转,这是整个系统的主线,其他模块都是围着它转的。
4. 核心模块拆解:一条报修单的完整生命周期
4.1 登录与 token 校验链路
登录是整个系统的入口,也是理解权限设计的钥匙。前端提交账号密码到后端,后端查 users 表比对,成功后生成 token 写进 token 表并返回给前端。核心逻辑大致是这样:
// 登录接口:校验账号密码,生成 token 并落库 @PostMapping("/login") public Result login(@RequestBody LoginForm form) { // 按用户名查管理员记录 Users user = usersService.findByUsername(form.getUsername()); if (user == null || !user.getPassword().equals(form.getPassword())) { return Result.error("账号或密码错误"); } // 生成唯一 token,设置过期时间 String token = UUID.randomUUID().toString().replace("-", ""); TokenRecord record = new TokenRecord(); record.setUserid(user.getId()); record.setUsername(user.getUsername()); record.setRole(user.getRole()); record.setToken(token); record.setExpiratedtime(new Date(System.currentTimeMillis() + 2 * 60 * 60 * 1000)); tokenService.save(record); return Result.ok(token); }这段代码里几个点值得注意:密码是明文比对,教学项目常见做法,真上生产得加 BCrypt 之类的哈希;token 用 UUID 生成,去掉了横杠方便前端存;过期时间设了两小时,过期后前端请求会被拦截器挡下来,跳回登录页。拦截器的逻辑一般是在config目录下,对除登录注册外的接口校验请求头里的 token 是否存在且未过期。改这块的时候,如果想让登录态更持久,把过期时间调大就行,但别忘了 token 表会越积越多,得配个定时清理或者登录时先删旧记录。
4.2 报修信息管理与接单流转
报修单是系统的核心实体,用户提交时写入报修信息表,字段包括报修人、宿舍、故障描述、报修类型、状态等。维修员在接单管理里看到待接单列表,点接单后状态变更,同时把维修员信息和接单时间写进去。下面是一个典型的接单接口:
// 维修员接单:更新报修单状态并绑定维修员 @PostMapping("/accept") public Result accept(@RequestParam Long repairId, @RequestParam Long workerId) { RepairInfo repair = repairService.getById(repairId); // 只有待接单状态才能接,防止重复接单 if (repair == null || !"待接单".equals(repair.getStatus())) { return Result.error("该报修单已被接单或不存在"); } repair.setStatus("维修中"); repair.setWorkerId(workerId); repair.setAcceptTime(new Date()); repairService.updateById(repair); return Result.ok(); }这里的并发问题在教学项目里通常被忽略,但值得知道:两个维修员同时点接单,如果不在数据库层加乐观锁或者用update ... where status = '待接单'的条件更新,可能出现重复接单。我一般会把更新语句改成带状态条件的写法,影响行数为 0 就说明被别人抢先了。状态字段用中文字符串存,好处是前端直接展示不用映射,坏处是后期加状态得改代码,规范做法是用枚举或者数字字典表。
4.3 配件申请与库存联动
维修员修东西要用配件,所以有配件申请模块。维修员提交申请,管理员审批,审批通过后从配件设备表里扣减库存。这条链路的关键是库存扣减不能扣成负数:
// 审批配件申请:通过则扣减库存,库存不足直接拒绝 @PostMapping("/approve") public Result approve(@RequestParam Long applyId, @RequestParam boolean pass) { PartsApply apply = partsApplyService.getById(applyId); if (apply == null || !"待审批".equals(apply.getStatus())) { return Result.error("申请单状态异常"); } if (pass) { // 条件更新:库存足够才扣减,避免超卖 int rows = partsService.reduceStock(apply.getPartsId(), apply.getCount()); if (rows == 0) { return Result.error("配件库存不足,无法通过"); } apply.setStatus("已通过"); } else { apply.setStatus("已驳回"); } partsApplyService.updateById(apply); return Result.ok(); }reduceStock对应的 SQL 是update parts set stock = stock - #{count} where id = #{id} and stock >= #{count},靠 where 条件保证不会扣成负数,返回影响行数判断成败。这种写法比先查再改安全,是库存类业务的常规操作。配件分类和配件设备是两级结构,分类管大类,设备管具体型号和库存,建表时用分类 id 关联。
4.4 宿舍分配与容量控制
宿舍分配模块把用户和宿舍床位绑起来,分配时要校验宿舍剩余容量。宿舍信息表里存了可住人数和已住人数,分配成功后已住人数加一,退宿则减一。核心校验逻辑:
// 分配宿舍:校验剩余床位后再写入分配记录 @PostMapping("/assign") public Result assign(@RequestBody AssignForm form) { DormInfo dorm = dormService.getById(form.getDormId()); int remain = Integer.parseInt(dorm.getKezhurenshu()) - Integer.parseInt(dorm.getYizhurenshu()); if (remain <= 0) { return Result.error("该宿舍已满员"); } // 写入分配记录 DormAssign assign = new DormAssign(); assign.setYonghuzhanghao(form.getUserAccount()); assign.setChuangweihao(form.getBedNo()); assign.setFenpeiriqi(new Date()); dormAssignService.save(assign); // 已住人数加一 dormService.increaseOccupied(dorm.getId()); return Result.ok(); }注意可住人数和已住人数在表里是 varchar 类型,代码里得转成整数再算,这是建表时类型选得不严谨留下的坑,二次开发时建议改成 int。床位号是否重复、同一用户是否已分配,这些校验也得补上,否则数据会乱。
5. 避坑与排查:跑这套系统最容易栽的几个地方
5.1 中文乱码从建库就开始了
现象:页面上的宿舍名称、故障描述显示成问号或者方块。原因:建库时字符集用了 latin1 或者默认值,或者 JDBC url 里没带characterEncoding=utf8。解决:建库语句显式指定DEFAULT CHARACTER SET utf8mb4,连接串加上useUnicode=true&characterEncoding=utf8,Navicat 里看表设计确认字段字符集也是 utf8mb4。已经建错的库,改字符集比重建还麻烦,直接删库重导脚本更快。
5.2 端口冲突导致前端连不上后端
现象:前端登录一直转圈,控制台报ERR_CONNECTION_REFUSED或者 404。原因:后端没起来、端口不是 8080,或者vue.config.js里的代理目标写错了。解决:先看后端控制台确认实际端口,再核对代理配置里的 target 地址,两边端口必须一致。如果 8080 被别的程序占了,改后端application.yml里的server.port,同步改前端代理。
5.3 表字段和实体类对不上
现象:接口报 500,异常栈里出现Unknown column或者字段值为 null。原因:实体类属性名和数据库字段名不一致,MyBatis 没配驼峰映射。解决:在application.yml里加mybatis.configuration.map-underscore-to-camel-case: true,让下划线字段自动映射到驼峰属性;或者检查 XML 里的 resultMap 是否写全。改表结构后记得同步改实体类,两边脱节是这类项目最常见的低级错误。
5.4 登录后刷新页面掉登录态
现象:登录成功进首页,一按 F5 就跳回登录页。原因:token 只存在了 Vuex 内存里,没持久化到 localStorage,刷新就丢。解决:登录成功后把 token 同时写进 localStorage,路由守卫里优先从 localStorage 读,请求拦截器统一带上。退出登录时清掉。这个改动不大,但体验差别明显。
5.5 配件库存扣成负数
现象:配件申请审批通过后,库存显示为负。原因:扣减逻辑是先查库存再更新,中间没有条件约束,并发或者重复提交时穿透了。解决:把更新语句改成where stock >= #{count}的条件更新,用影响行数判断是否成功,失败就回滚申请状态。同时前端提交按钮加防重复点击。
6. 二次开发:从能跑到能用的改造思路
这套系统跑通之后,真正花时间的是把它往“能用”的方向推。我一般按优先级排三件事。第一件是把权限做细,现在 token 表里存了 role,但接口层未必每个都校验角色,容易出现学生调管理员接口的情况。改造方式是在拦截器里解析 token 拿到 role,配合自定义注解在 Controller 方法上标注允许的角色,拦截器统一比对,比在每个方法里写 if 判断干净得多。第二件是把状态字段规范化,报修单的“待接单/维修中/已完成”这类中文字符串散落在代码各处,改成枚举类集中管理,前端通过字典接口拿状态列表渲染下拉框,以后加“已取消”状态只改一处。
第三件是补统计报表,管理员端现在只有列表,没有数据看板。加一个统计接口,按维修类型分组统计报修量、按月份统计完成率,SQL 用group by加聚合函数就能出,前端用 ECharts 画两个图,答辩或者演示时观感提升明显。下面是一个按类型统计的示例:
-- 按维修类型统计报修单数量与完成数 SELECT weixiuleixing AS type, COUNT(*) AS total, SUM(CASE WHEN status = '已完成' THEN 1 ELSE 0 END) AS finished FROM baoxiuxinxi GROUP BY weixiuleixing ORDER BY total DESC;验证改造是否生效,别只看页面,用 Postman 或者浏览器直接打接口,确认返回结构和前端渲染一致;改数据库字段后,先跑一遍全流程走查,从登录到报修到接单到完成,任何一环断了都能立刻定位。还有个小技巧:把application.yml里的 SQL 日志打开(mybatis.configuration.log-impl: org.apache.ibatis.logging.stdout.StdOutImpl),控制台能直接看到执行的 SQL 和参数,排查字段问题时比猜快得多。
血泪经验是,这类教学项目最容易犯的错是拿到就改业务代码,结果改崩了不知道哪一步出的问题。我现在的习惯是先把原始版本完整跑通、走查一遍、打个压缩包备份,再动第一行代码。每改一个模块,先确认原功能没坏,再往下走。希望帮到你。
本文还有配套的精品资源,点击获取