ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

基于SpringBoot+Vue的学生宿舍管理系统课设实战解析

基于SpringBoot+Vue的学生宿舍管理系统课设实战解析 简介基于Springboot与Vue构建的学生宿舍管理系统是一套面向计算机专业毕业设计、课程设计与期末大作业的完整工程。项目采用前后端分离架构涵盖学生信息管理、宿舍分配、报修服务、费用管理等核心模块适合正在完成毕设的学生及需要项目实战的Java学习者。压缩包共436个文件包括161个svg图标、122个java后端源码、46个vue前端组件、16个xml配置及数据库脚本sql、部署视频、开发文档等总大小8.69MB。资源包已通过严格调试确保可运行并配套开发说明文档、部署视频、代码讲解视频及全套软件可直接作为毕设使用。目前已有125人学习浏览内容覆盖从需求分析、系统设计到编码测试、部署上线的完整软件开发流程能有效帮助学习者理解SpringBoot简化配置与Vue交互设计的实际应用并为教师提供教学案例支持。1. 学生宿舍管理系统期末周最值得直接抄的SpringBootVue课设如果你正盯着这个标题找能直接跑的课设源码大概率是被期末大作业的时间表逼到头了。这套《基于SpringbootVue的学生宿舍管理系统》不是那种只有登录注册的纯Demo它把学生管理、宿舍分配、报修处理、入住统计做成了一条完整闭环后端用SpringBoot 2.7 MyBatis-Plus前端用Vue 3 Element Plus前后端分离联调最后还能打包成一个独立jar包交作业、写论文、答辩演示都能用。课程设计、期末大作业、软件工程实践这三类场景都适合它对想从JSP老项目往前后端分离跳的初学者来说也是一份完整的可抄作业。2. 技术栈拆解为什么这个组合最适合交课设2.1 前后端分离的选型逻辑演示效果好论文材料也够写老式课设用JSP Servlet Tomcat写起来痛苦演示时页面还丑。换成SpringBoot Vue之后后端只出接口前端只画页面两边可以并行开发答辩时能讲“我设计了RESTful接口、JWT鉴权、Vue路由守卫”素材一下就多了。SpringBoot的自动配置和内嵌Tomcat意味着你不用装独立Tomcat双击jar包就能跑这是我推荐新手用它做课设最核心的理由。Vue侧的核心优势是组件化和生态。一个宿舍分配弹窗、一张报修表格、一个入住率统计卡片Element Plus里都有现成组件半天能搭完三个页面。相比Server JSP页面里那种混写Java脚本的做法Vue的v-model双向绑定和axios异步请求更贴近真实项目。学校里《软件工程》课程设计的“前后端分离架构”评分点这个组合完全覆盖。2.2 版本选型SpringBoot 2.7而不是3.xVue 3而不是2版本选择直接决定你能不能一周内跑通。不少同学一上来就用SpringBoot 3.2结果发现网上教程全是javax.servlet自己项目里却是jakarta.servletIDE一片飘红这就是典型的“版本太高把课设干翻车”。组件推荐版本理由JDK8 或 11SpringBoot 2.7官方支持安装快SpringBoot2.7.18网上教程最全javax包名兼容老代码MyBatis-Plus3.5.3单表CRUD零SQLBaseMapper直接吃MySQL8.0mysql-connector-java替换为mysql-connector-jNode16/18Vite 5对高版本Node也兼容但16最稳Vue3.4 Vite 5组合优于Vue2webpack启动秒开Element Plus2.7Vue3官方配套UI库表格表单组件全SpringBoot 3.x本身没问题但它强制JDK 17和jakarta.*包名课设场景下排查问题的代价太大。Vue侧同理Vue2的Element UI已经进入维护期新项目直接用Vue 3 Vitenpm run dev起来那一下的体验差距是决定性的。2.3 项目结构后端分层和前端目录一次看明白拿到一份源码先看结构结构是否清晰比代码是否花哨更重要。这套系统的后端采用经典四层结构src/main/java/com/example/dormitory/ ├── config/ # 配置类拦截器、MyBatis-Plus分页配置、跨域配置 ├── controller/ # 接口层接收前端请求不写业务逻辑 ├── service/ # 业务层接口 serviceImpl实现 ├── mapper/ # MyBatis-Plus的Mapper接口继承BaseMapper ├── entity/ # 数据库实体类对应每张表 ├── dto/ # 前端传参对象比如LoginDTO、AssignDTO ├── vo/ # 返回给前端的结果对象比如LoginVO、DormitoryVO └── utils/ # 工具类JWT生成解析、验证码、统一返回结果前端目录src/ ├── api/ # axios接口封装Login.js、Dormitory.js ├── router/ # vue-router路由表与路由守卫 ├── views/ # 页面组件Login.vue、Dashboard.vue、Dormitory.vue ├── components/ # 复用组件表格、弹窗、侧边栏 └── main.js # 入口挂载Element Plus和路由这样的分层在答辩时有话讲controller只做参数校验和返回统一结果service管业务规则mapper管SQL数据流向是单向的。演示时老师问“如果我要加一个宿舍楼怎么改”你只要回答“加一张building表建对应entity和mapperservice里写一个listBuildings()controller开一个GET /api/building/list接口前端在菜单里加一项”整套流程就能自圆其说。3. 环境准备与初始化从空环境到前后端都亮起来3.1 后端搭建SpringBoot工程的依赖清单与配置陷阱用IDEA新建Spring Initializr项目这是最标准的入口。如果你是照着源码手敲注意创建时别选太高版本的依赖JDK选8或11构建工具选Maven依赖只勾Spring Web即可剩下的写进pom里。parent groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-parent/artifactId version2.7.18/version relativePath/ /parent dependencies !-- Web起步依赖内嵌Tomcat提供Spring MVC -- dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-web/artifactId /dependency !-- MyBatis-Plus注意SpringBoot 2.x用这个artifactId -- dependency groupIdcom.baomidou/groupId artifactIdmybatis-plus-boot-starter/artifactId version3.5.3/version /dependency !-- MySQL驱动 -- dependency groupIdmysql/groupId artifactIdmysql-connector-java/artifactId version8.0.33/version /dependency !-- JWT工具库 -- dependency groupIdio.jsonwebtoken/groupId artifactIdjjwt/artifactId version0.11.5/version /dependency !-- Lombok减少getter/setter模板代码 -- dependency groupIdorg.projectlombok/groupId artifactIdlombok/artifactId optionaltrue/optional /dependency /dependencies这里有一个踩坑点mybatis-plus-boot-starter是给SpringBoot 2.x用的如果你用了SpringBoot 3.x必须换成mybatis-plus-spring-boot3-starter否则启动直接报bean找不到。JWT依赖用0.11.5低于0.9.1的老版本在JDK 8上会有Base64编码问题解析token时总报IllegalArgumentException。写完后配置application.yml这是整个系统能不能连上数据库的关键server: port: 8080 spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/dormitory?useUnicodetruecharacterEncodingutf8serverTimezoneAsia/Shanghai username: root password: 123456 mybatis-plus: configuration: map-underscore-to-camel-case: true # 数据库下划线自动转Java驼峰 log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 控制台打印SQL调试用 global-config: db-config: logic-delete-field: deleted # 全局逻辑删除字段数据库连接串里的characterEncodingutf8是中文不乱码的前提serverTimezone不写的话MySQL 8驱动会直接报时区错误。log-impl打印SQL能让你在排查问题时看到SQL和参数开发期强烈建议打开上线再关。3.2 前端环境Node、npm、Vite与Element Plus接入前端环境配置就是三件事装Node配npm镜像用Vite创建项目。Node安装包一路next就能完成安装后看版本node -v npm -vnpm默认源在国外创建一个空项目要等半天先换淘宝镜像npm config set registry https://registry.npmmirror.com然后创建Vue 3项目。选JS不选TS课设场景TS的接口类型定义能多写一倍代码时间来不及npm create vitelatest dormitory-web -- --template vue cd dormitory-web npm install npm install element-plus axios vue-router4 npm run devnpm create vite是当前最主流的方式--template vue是纯JS模板不带TS。装完后main.js里接入Element Plus注意全局引入虽然打出来的包大一点但课设最看重省心import { createApp } from vue import ElementPlus from element-plus import element-plus/dist/index.css import zhCn from element-plus/es/locale/lang/zh-cn import App from ./App.vue import router from ./router const app createApp(App) app.use(ElementPlus, { locale: zhCn }) app.use(router) app.mount(#app)Element Plus默认文案是英文不配置zhCn的话分页器会显示“Total xxx”而不是“共 xxx 条”答辩时很掉价。记住这个细节。Vite的代理配置是前后端联调的第一步在vite.config.js里加export default defineConfig({ plugins: [vue()], server: { port: 5173, proxy: { /api: { target: http://localhost:8080, changeOrigin: true } } } })这里/api开头的请求会被转发到8080。前端代码里请求路径全部写相对路径/api/auth/login联调时就不会有跨域问题。注意改完vite配置必须重启npm run dev热更新不会识别vite.config.js的改动这是很多人改了代理没反应的原因。3.3 打通最小闭环先做登录再做业务我的习惯是拿到骨架后先不做业务页面第一步先把“后端发一个Token前端存下来带着Token请求一个需要鉴权的接口”这条链路跑通。原因很简单如果登录链路有坑后面所有页面都调不通接口越早暴露越好。后端写一个最简单的AuthControllerRestController RequestMapping(/api/auth) public class AuthController { PostMapping(/login) public Result login(RequestBody LoginDTO loginDTO) { // 省略查库校验先用假数据验证链路 MapString, String data new HashMap(); data.put(token, test-token-123456); data.put(username, admin); return Result.success(data); } GetMapping(/check) public Result check(RequestHeader(Authorization) String token) { return Result.success(token有效); } }前端在App.vue的onMounted里调一次/api/auth/check能通就说明Vite代理、后端端口、axios路径全部正确。这个环节往往能排除掉一半的“为什么接口不通”问题。4. 后端核心实现JWT登录、宿舍分配与报修工单4.1 数据库设计五张表撑起整套业务数据库设计决定了答辩深度。这套系统拆成五张表关系不复杂但能讲清楚sys_user保存管理员和宿管账号student保存学生信息和所在宿舍dormitory保存宿舍楼、房间和容量repair是报修工单notice用于公告。核心建表SQL如下CREATE TABLE sys_user ( id int NOT NULL AUTO_INCREMENT, username varchar(50) NOT NULL COMMENT 登录账号, password varchar(100) NOT NULL COMMENT BCrypt加密后的密码, role varchar(20) DEFAULT admin COMMENT 角色admin/manager, create_time datetime DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4; CREATE TABLE dormitory ( id int NOT NULL AUTO_INCREMENT, building varchar(20) NOT NULL COMMENT 楼栋如1号楼, room_no varchar(20) NOT NULL COMMENT 房间号如301, capacity int NOT NULL COMMENT 房间容量4/6人间, used_bed int DEFAULT 0 COMMENT 已住人数, gender int NOT NULL COMMENT 0男 1女, PRIMARY KEY (id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4; CREATE TABLE student ( id int NOT NULL AUTO_INCREMENT, stu_no varchar(20) NOT NULL COMMENT 学号, name varchar(50) NOT NULL, gender int NOT NULL, dorm_id int DEFAULT NULL COMMENT 宿舍IDNULL表示未分配, bed_no int DEFAULT NULL COMMENT 床位号, check_in_time datetime DEFAULT NULL COMMENT 入住时间, PRIMARY KEY (id), UNIQUE KEY uk_stu_no (stu_no) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4; CREATE TABLE repair ( id int NOT NULL AUTO_INCREMENT, student_id int NOT NULL, content varchar(500) NOT NULL COMMENT 报修内容, status int DEFAULT 0 COMMENT 0待处理 1处理中 2已完成, create_time datetime DEFAULT CURRENT_TIMESTAMP, primary key (id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;这里有几个设计点值得注意dormitory.used_bed是一个冗余字段目的是列表页展示“3/4人”时不用count统计但冗余字段的维护要靠事务保证后面分配宿舍时就必须同时更新student和dormitory两张表用Transactional兜底。student.dorm_id和bed_no为空表示该生未分配宿舍这和“住满”是两个状态答辩时能说清楚就很加分。4.2 登录鉴权轻量JWT拦截器方案课设项目我强烈推荐JWT HandlerInterceptor而不是Spring Security。原因很直接Security过滤链配置复杂答辩时老师顺着“过滤器执行顺序”追问几层就能把人问崩。JWT方案代码量小原理也容易说清用户登录成功后后端签发一个带过期时间的Token前端每次请求把它放在请求头里后端拦截器验证Token的签名和过期时间。先写JWT工具类这两个方法全场都会用到Component public class JwtUtil { // 密钥课设用固定字符串实际项目要放到配置中心 private static final String SECRET_KEY dormitorySecretKey12345678901234567890; private static final long EXPIRE_TIME 12 * 60 * 60 * 1000; // 12小时 // 生成Tokensubject放用户id public String createToken(Integer userId, String username) { return Jwts.builder() .setSubject(String.valueOf(userId)) .claim(username, username) .setIssuedAt(new Date()) .setExpiration(new Date(System.currentTimeMillis() EXPIRE_TIME)) .signWith(SignatureAlgorithm.HS256, SECRET_KEY) .compact(); } // 解析Token抛异常说明Token无效或过期 public Claims parseToken(String token) { return Jwts.parser() .setSigningKey(SECRET_KEY) .parseClaimsJws(token) .getBody(); } }注意SECRET_KEY长度必须大于32字节HS256算法要求否则启动后一调登录就报WeakKeyException。过期时间设12小时课程设计演示场景下上午登录下午答辩不用重新登录这是实际体验出来的参数。拦截器负责从请求头取Token并校验只放行登录接口Component public class AuthInterceptor implements HandlerInterceptor { Autowired private JwtUtil jwtUtil; Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { // 放行预检请求 if (OPTIONS.equalsIgnoreCase(request.getMethod())) { return true; } String token request.getHeader(Authorization); if (token null || !token.startsWith(Bearer )) { response.setStatus(401); response.setContentType(application/json;charsetutf-8); response.getWriter().write({\code\:401,\msg\:\未登录\}); return false; } try { Claims claims jwtUtil.parseToken(token.replace(Bearer , )); // 把当前用户id放到request域后面业务里可以取 request.setAttribute(userId, claims.getSubject()); return true; } catch (Exception e) { response.setStatus(401); response.getWriter().write({\code\:401,\msg\:\Token无效或过期\}); return false; } } }再通过WebMvcConfigurer注册拦截器并排除登录和静态资源路径。前端axios请求拦截器里统一拼上Bearer前缀两边约定好格式这是联调时最容易对不齐的地方。4.3 宿舍分配业务性别校验、超员校验与并发处理宿舍分配是这套系统的核心业务逻辑也是答辩时老师最喜欢追问的点。一个有效分配要同时满足三条规则性别必须和宿舍楼匹配、房间未住满、同一个学生没被分配过两次。这三条任何一个不满足都要给前端明确提示。Service public class DormitoryServiceImpl extends ServiceImplDormitoryMapper, Dormitory { Transactional(rollbackFor Exception.class) public Result assignRoom(AssignDTO dto) { // 1. 查宿舍锁行防止并发时超额入住 Dormitory dorm this.baseMapper.selectDormitoryForUpdate(dto.getDormId()); if (dorm null) { return Result.fail(宿舍不存在); } // 2. 校验性别 Student student studentMapper.selectById(dto.getStudentId()); if (!dorm.getGender().equals(student.getGender())) { return Result.fail(性别与宿舍类型不匹配); } // 3. 校验容量 if (dorm.getUsedBed() dorm.getCapacity()) { return Result.fail(该宿舍已住满); } // 4. 分配床位默认空闲床位号 usedBed 1 studentMapper.assignDorm(dto.getStudentId(), dto.getDormId(), dorm.getUsedBed() 1); dormitoryMapper.increaseUsedBed(dto.getDormId()); return Result.success(分配成功); } }这里最关键也是课设源码里少见的点是第1步的selectDormitoryForUpdate。默认的BaseMapper查出来是普通select两个管理员同时给最后一个床位分配不同学生时两个请求都能通过容量校验结果床上住两个人。加了SELECT ... FOR UPDATE之后同一时刻只有一个事务能改这一行另一个串行执行时used_bed已经变化会走到“已住满”。这个细节如果能在答辩时主动讲出来属于明显的加分项。increaseUsedBed用的是MyBatis-Plus的UpdateWrapper进行原子自增和算术运算它会先查后改还是直接执行一条UPDATE也需要权衡。常见做法是直接写在mapper里用Update注解配一条SQLUPDATE dormitory SET used_bed used_bed 1 WHERE id #{id}保证这不是“读出值再写回”的竞态操作。5. 前端实现与联调路由、axios封装与打包进SpringBoot5.1 路由设计与路由守卫登录页、布局页、业务页前端一共需要三类页面登录页/login使用侧边栏布局的首页/layout/dashboard以及嵌套在布局里的宿舍管理、学生管理、报修管理页面。路由表这样写import { createRouter, createWebHashHistory } from vue-router const routes [ { path: /login, component: () import(../views/Login.vue) }, { path: /layout, component: () import(../layout/Index.vue), children: [ { path: dashboard, component: () import(../views/Dashboard.vue) }, { path: dormitory, component: () import(../views/Dormitory.vue) }, { path: student, component: () import(../views/Student.vue) }, { path: repair, component: () import(../views/Repair.vue) } ] }, { path: /, redirect: /layout/dashboard } ] const router createRouter({ history: createWebHashHistory(), routes })这里我直接用的createWebHashHistory而不是createWebHistory这个选择是有原因的hash模式地址会带个#不好看但打包进SpringBoot的静态目录后刷新任意子路径都能正确加载history模式虽然地址干净但刷新/layout/dashboard时后端没配路由回退就直接404。课设没必要为了美观去处理服务端回退配置hash模式省心。路由守卫拦截未登录访问router.beforeEach((to, from, next) { const token localStorage.getItem(dorm_token) if (to.path /login) { next() } else if (!token) { next(/login) } else { next() } })逻辑是去登录页直接放行去其他页面时本地没有Token就跳回登录页。Token的存在性并不能证明有效性所以登录后第一次请求返回401时响应拦截器里要清Token并强制跳登录页这就是“无状态Token的本地失效”处理方案需要在request.js里配合完成。业务页面之间的路由跳转可以带上参数。比如学生列表点“查看宿舍”跳转宿舍详情页用router.push({ path: /dormitory/detail, query: { dormId: row.id } })在详情页用route.query.dormId接收。这样比在store里存数据更简洁刷新页面参数也不会丢。5.2 axios封装请求拦截器、响应拦截器与跨域axios不能每个页面单独写一遍项目里统一封装一个request.js。这份封装决定了联调效率核心是两个拦截器import axios from axios import { ElMessage } from element-plus import router from ../router const request axios.create({ baseURL: /api, // 配合Vite代理 timeout: 10000 }) // 请求拦截器自动携带Token request.interceptors.request.use(config { const token localStorage.getItem(dorm_token) if (token) { config.headers.Authorization Bearer ${token} } return config }) // 响应拦截器统一处理错误 request.interceptors.response.use( response { return response.data }, error { if (error.response error.response.status 401) { localStorage.removeItem(dorm_token) router.push(/login) ElMessage.error(登录已过期请重新登录) } else { ElMessage.error(error.response?.data?.msg || 网络错误) } return Promise.reject(error) } ) export default requestbaseURL填/api而不是http://localhost:8080这很重要。填死地址会有跨域问题填绝对地址后端还得开CORS填相对路径配合Vite代理生产环境再让Nginx或SpringBoot转发代码里一次都不用改。请求拦截器统一加Bearer前缀后端拦截器统一去掉前缀两边格式一致。对应每个业务模块再单独建api文件比如src/api/dormitory.jsimport request from ../utils/request export function getDormitoryList(params) { return request.get(/dormitory/list, { params }) } export function assignRoom(data) { return request.post(/dormitory/assign, data) }页面里调用时只用关心Promise的结果和错误提示代不产生任何跨域代码。这里不写cors配置后端使用常见做法是开发期靠Vite代理打包后前后端同源全程都不需要后端开CORS这是最干净的方案。5.3 打包部署Vue构建产物放进SpringBoot的static目录开发期是前后端两个服务前端在5173后端在8080。交付的时候不能让人开两个窗口跑要打成一个jar包这一步叫“Vue打包放进SpringBoot中”实际操作就是把前端构建产物复制到后端的静态资源目录。npm run build构建完成后dist文件夹里出现index.html和assets目录。然后在IDEA里手动把dist下的文件复制到src/main/resources/static/再执行Maven打包mvn clean package -DskipTests java -jar dormitory-0.0.1.RELEASE.jar此时浏览器访问http://localhost:8080看到的就是Vue页面接口路径/api/...会由SpringBoot自身处理不再经过Vite代理。一个jar包带全部前端妥妥的课设演示方式。打包前记得Vue的接口请求务必是相对路径/api如果写死了http://localhost:8080/api打包后前端代码里的请求会绕过同源关系去访问8080SpringBoot的静态资源和接口仍然能通但排查起来很绕。交付给别人的时候一份完整的源码包至少应该包括这几部分检查一下自己的压缩包里有没有交付物内容后端源码完整SpringBoot工程含pom.xml可直接mvn package前端源码Vue工程目录npm install后能npm run dev数据库脚本建库SQL、初始化管理员账号、测试学生数据部署说明JDK/MySQL版本、账号密码、打包命令答辩PPT大纲技术架构图、功能清单、设计亮点源码里一定要放一份初始化数据SQL里面预置5个学生和3个宿舍。否则老师现场让你演示你从头录入数据要花十分钟整个答辩节奏就垮了。这是课设源码实用性上最容易翻车的地方。6. 避坑排查与验收技巧五条血泪经验加一份演示路径6.1 五条高频踩坑记录坑一SpringBoot版本太高导致javax包找不到现象启动类里import javax.servlet.*全部报错或项目里同时出现javax和jakarta两套包名。原因SpringBoot 3.x把Java EE API从javax.*迁移到jakarta.*网上大量教程和博客都是基于SpringBoot 2.x写的生搬硬套下来自然编译不过。解决最省心的方案是退回SpringBoot 2.7.x JDK 8/11所有老教程代码都可以直接用。如果非要用SpringBoot 3.x遇到javax改成jakarta即可但后续MyBatis-Plus、验证框架的兼容问题会接踵而来课设不划算。坑二MyBatis-Plus分页查询total一直为0翻页不出来现象selectPage返回的记录有数据但total字段永远是0页面上显示“共0条”。原因MyBatis-Plus的物理分页依赖PaginationInnerInterceptor只引入mybatis-plus-boot-starter不够还得有一个配置类显式注册到MybatisPlusInterceptor里。解决新建MybatisPlusConfig.java把分页拦截器注册进去。Configuration public class MybatisPlusConfig { Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor new MybatisPlusInterceptor(); interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); return interceptor; } }这个配置类是MyBatis-Plus课设最常见的遗漏报错时控制台根本不会提示属于典型的黑匣子问题。坑三数据库中文变成问号或者控制台SQL中文乱码现象前端写入宿舍楼名称“1号楼”存进数据库变成“1???獍”。原因application.yml连接串缺了characterEncodingutf8或者建表时字符集不是utf8mb4。解决建库时执行CREATE DATABASE dormitory DEFAULT CHARACTER SET utf8mb4;连接串里带上useUnicodetruecharacterEncodingutf8表字段类型统一用varchar并在建表语句里声明CHARSETutf8mb4。双击jar包运行时如果还是乱码在IDEA的VM options里加-Dfile.encodingUTF-8这是Windows上最容易忽略的环境级参数。坑四Vite代理改了没反应请求还是打到5173现象npm run dev启动后点击登录请求路径是http://localhost:5173/api/auth/login后端接口根本没收到请求一会儿就报404。原因改vite.config.js后必须重启dev server热更新不会重启代理。还有一种情况是浏览器缓存了旧的模块依赖接口路径里出现了http://localhost:8080字样。解决改完proxy配置后CtrlC强制停掉dev server再重新npm run dev开浏览器无痕模式排除缓存。这是联调阶段消耗时间最多的“玄学”问题实际上规则非常明确。坑五打包后刷新子页面404功能却都正常现象前端打包放进SpringBoot的static目录点击菜单跳转没问题一按F5刷新http://localhost:8080/layout/dormitory就白屏或404。原因前端路由用了history模式刷新时浏览器把带路径的请求发给SpringBoot后端没有对应的Mapping走默认的404。解决路由创建用createWebHashHistory地址变成http://localhost:8080/#/layout/dormitory刷新时#后面的内容不会被发给后端SpringBoot只认根路径。这就是我在5.1节坚持选hash模式的原因不要为了美观踩这个坑。6.2 验收演示路径六分钟讲完整个系统源码拿到手跑通不难难的是答辩怎么把故事讲圆。我一般按这个时间线给老师演示节奏紧凑且每个功能都在亮业务的完整性时间演示步骤讲师要表达的重点第1分钟输入admin账号登录进入Dashboard统计页展示JWT鉴权流程统计卡片展示宿舍总数、入住率、待处理报修第2分钟打开学生管理搜索学生姓名展示MyBatis-Plus条件构造器的使用前端表格分页第3分钟给未分配宿舍的学生分配宿舍讲解性别校验、容量校验、事务保证两张表一致第4分钟故意分配一个女生到男生宿舍楼演示拦截器和业务校验反馈说明“系统不是只做增删改查”第5分钟新建一条报修工单切换到处理状态展示状态流转强调后端时间字段由数据库当前时间生成第6分钟退出登录再访问页面被拦截回登录页展示路由守卫的作用收尾老师大概率会追问这几个点提前备好答案效果会好很多为什么用MyBatis-Plus不用JPA答单表CRUD只需继承BaseMapper且代码量远小于JPA映射Token过期了怎么办答前端响应拦截器捕获401后清Token跳登录页怎么解决并发分房答SELECT FOR UPDATE行锁保证同一宿舍分配串行化。选题想往上加亮点的话有两个改动成本非常低的扩展一是引入ECharts画一个宿舍入住率饼图二是用SpringBoot自带的Scheduled(cron 0 0 2 * * ?)写一个每天凌晨自动统计各楼栋空床位的定时任务。这两块都能单独写进论文的创新点章节代码量却都控制在50行以内。末尾提一个我自己的习惯拿到任何课设源码不要急着跑npm run install就完事第一件事永远是看application.yml里的数据库密码和create.sql里的初始化数据。先执行SQL脚本、再改自己本机的MySQL账号密码、然后启动后端、再启动前端这四步按顺序来跑通基线后再动代码。我帮人排查课设问题多了就会发现九成跑不起来都是卡在数据库账号密码和初始化数据上而不是代码本身。从那以后我每次交付源码都强制自己把“README里写清楚MySQL账号密码和SQL执行顺序”这一条列为必做项。希望帮到你这份宿舍管理系统的源码值得你下载后完整跑一遍再按上面的演示路径走一遍答辩就不虚了。本文还有配套的精品资源点击获取
返回列表