拓冰建站拓冰建站
首页 / 资讯中心 / 正文

基于SSM+Vue的驾校测评系统毕设全攻略:从选题到答辩

如果你点开这篇文章大概率是拿到了一个“基于SSMVue的驾校测评系统”的毕业设计题目或者你在犹豫要不要选这个方向。我先说结论这个题目在本科毕设里属于性价比很高的类型——业务规则清晰、角色划分明确、技术栈经典成熟既能展示后端分层设计能力又能体现前端交互功底而且数据天然适合做可视化统计论文素材一抓一大把。但前提是你真的把它当成一个“系统”来做而不是把CRUD堆完就交差。这篇文章我会从选题拆解一直讲到最后答辩包括数据库怎么设计、后端业务边界怎么划、前端页面怎么组织、论文每一章怎么写以及那些没人告诉你但一定会踩的坑。全程基于我实际带过的项目经验不是网上复制粘贴的模板。1. 选题思路与系统整体拆解1.1 为什么“驾校测评”是毕设的优质赛道驾校测评系统这个题目好做根本原因是它的业务模型足够“标准”。一个驾校里有三类人学员要预约练车、查看测评结果教练要处理预约、给学员打分评价管理员要管人管车管数据。这个三角色模型天然对应了权限体系设计而权限控制恰恰是毕设答辩时老师最爱问的点。另外驾校业务里“预约—确认—完成—评价—统计”这条链路上有状态流转、有时间冲突校验、有多表联查这些都是SSM框架的强项。你不需要发明复杂算法只需要把业务逻辑梳理清楚系统自然就显得“有深度”。还有一点很实际这个题目的数据可视化场景非常丰富。学员通过率、教练评分对比、各科目预约量、学员进度分布随便挑两个做成图表论文里的“系统实现”章节就会非常好看答辩演示也容易出效果。1.2 SSM Vue为什么这个组合是毕设标配SSMSpring SpringMVC MyBatis到今天仍然是教学体系里的主流框架虽然企业里更多用SpringBoot但毕设用SSM有几个实打实的好处第一SSM的分层结构更“显性”Controller、Service、Mapper三层分得清清楚楚老师一眼就能看出你懂分层架构第二SpringMVC的请求流转、MyBatis的SQL映射都是高频答辩问题用SSM做完了你能讲清楚的东西更多第三网上SSM相关的资料和踩坑记录极其丰富遇到问题基本都能搜到答案。前端选Vue同理。Vue的渐进式设计让页面开发效率很高而且Element UI组件库和SSM项目的配合非常成熟表格、表单、弹窗、日期选择器这些毕设高频组件都是开箱即用。这里有个小建议如果导师没有强制要求版本前端优先选Vue 2 Element UI不要盲目上Vue 3 Element Plus。不是说Vue 3不好而是Vue 2 Element UI在毕设这个场景下的资料最全、坑最少。等你有余力再在论文里写“使用Vue 2进行开发其响应式原理和组件化思想同样适用于Vue 3”这句话放到论文里也挑不出毛病。1.3 系统功能模块与角色边界在动工之前先把功能边界划清楚。我推荐的模块划分是这样的学员端注册登录、个人信息维护、教练列表查看、预约测评选教练、选时间、选车辆、查看自己的测评记录和成绩、查看驾校公告。教练端登录、查看分配给自己的预约列表、确认/拒绝预约、为学员录入测评结果分项打分评语、查看自己带过的学员列表和统计。管理端用户管理学员/教练账号的增删改查、教练信息审核、车辆信息管理、公告发布、数据统计看板通过率、预约量、教练评分对比。注意学员和教练不要共用一套“用户表角色字段”就完事了最好拆出学员扩展表和教练扩展表。虽然这样做会让SQL多几个关联但论文里的E-R图会丰富很多而且现实中教练有准教车型、教龄、评分等属性学员有当前科目、剩余学时等属性硬塞在用户表里字段会非常混乱。2. 数据库设计与核心业务规则2.1 核心表结构设计数据库是毕设的地基表设计得不好后面写Mapper的时候每一行都是痛苦。我设计的核心表如下供你直接参考。用户表存的是登录凭证和公共信息学员和教练的扩展信息分表存放预约表是核心中的核心它关联了学员、教练、车辆和时段测评记录表则进一步关联预约保证每一次测评都有据可查。表名职责关键字段user登录账号与公共信息id, username, password, role, real_name, phone, id_card, statusstudent_profile学员扩展信息id, user_id, driver_type(C1/C2), current_subject, total_hours, remaining_hourscoach_profile教练扩展信息id, user_id, coach_years, teach_subject, rating, introducecar车辆信息id, plate_no, car_type, status(空闲/使用中/维修)appointment预约记录id, student_id, coach_id, car_id, appoint_date, time_slot, status(待确认/已确认/已完成/已取消), create_timeassessment测评记录id, appointment_id, student_id, coach_id, subject, score_detail, total_score, comment, assess_timenotice公告id, title, content, create_time这里特别说明一下score_detail这个字段。驾校测评不是给你一个总分就完事而是要分项的——倒车入库、侧方停车、坡道起步、直线行驶等等。最简单的做法是建一个单独的“评分细项表”但毕设里我更推荐在assessment表里用一个JSON字符串存储分项得分比如[{item:倒车入库,score:90},{item:侧方停车,score:85}]。这样查询时不需要额外连表后端解析JSON就能拿到所有细项展示成表格或者雷达图都很方便。答辩时如果老师问“为什么这么设计”你可以说测评细项是动态可配置的用JSON存储可以避免频繁修改表结构。2.2 预约状态的流转与管理预约是整个系统的心脏也是最容易出业务漏洞的地方。我给预约定义了四个状态待确认、已确认、已完成、已取消流转规则如下学员提交预约后生成“待确认”记录同步锁住该教练在该时间段的预约名额。教练登录后看到待确认的预约可以确认或拒绝拒绝时必须填写原因这个字段很容易被遗漏但实务中非常必要。学员在教练确认前可以自行取消教练确认后学员不能再自行取消只能联系管理员处理。计时训练或测评完成后由教练将预约改为“已完成”并同步录入测评记录。只有“已确认”状态的预约才能执行“完成”操作只有“待确认”或“已确认”状态才允许被取消。这个状态机是论文里“业务逻辑设计”章节的好素材也是答辩时体现你思考深度的关键。很多同学的项目预约状态就一个字段随手改没有任何约束老师一问“如果学员取消预约同时教练确认了怎么办”就直接卡壳。2.3 冲突校验与数据一致性预约冲突一定要在数据库层面和业务层双重控制。数据库层面给appointment表加一个唯一索引ALTER TABLE appointment ADD UNIQUE KEY uk_coach_time (coach_id, appoint_date, time_slot, status);注意这里把status加进唯一索引不严谨因为已取消的记录会永久占坑。更合理的方案是在业务层做校验SQL查询该时段是否存在状态为“待确认”或“已确认”的记录同时数据库只对“有效状态”做部分唯一约束——MySQL不支持部分唯一索引所以实际项目中我的做法是用单独一张“时段占用表”来记录某个教练在某个时段是否已被占用预约表和占用表在同一事务里操作。这样既不会误伤历史取消记录又能保证并发下不超卖。如果你的毕设不要求处理高并发业务层校验就够了但事务一定要加。ServiceImpl方法上标注Transactional确保“插入预约记录”“更新时段占用表”“更新车辆状态”要么全部成功要么全部回滚。3. 后端SSM实现别只会搭架子要会写业务3.1 统一返回结果与异常处理很多学生的后端接口返回格式五花八门有的返回Map有的直接返回实体有的成功失败字段都不一样。前端对接的时候每个接口都要单独写解析逻辑极其折磨。我强烈建议第一步先封装一个统一返回体public class ResultT { private Integer code; private String message; private T data; public static T ResultT success(T data) { ResultT result new Result(); result.setCode(200); result.setMessage(操作成功); result.setData(data); return result; } public static T ResultT error(String message) { ResultT result new Result(); result.setCode(500); result.setMessage(message); return result; } }配合一个全局异常处理器用ControllerAdvice拦截业务异常和未知异常这样所有接口的返回格式都统一成{code, message, data}前端axios拦截器里只需要判断一次code就可以分发逻辑。这个封装在论文的“系统实现”里也是一个可写点。3.2 预约接口的核心实现逻辑预约接口是后端最核心的业务之一我贴一个简化版逻辑完整代码你可以在自己项目里扩展Override Transactional public ResultString createAppointment(AppointmentDTO dto) { // 1. 校验预约时间是否合法必须早于当天且在规定时段内 if (dto.getAppointDate().before(new Date())) { return Result.error(预约日期不能早于今天); } // 2. 校验教练在该时段是否已被占用 AppointmentExample example new AppointmentExample(); example.createCriteria() .andCoachIdEqualTo(dto.getCoachId()) .andAppointDateEqualTo(dto.getAppointDate()) .andTimeSlotEqualTo(dto.getTimeSlot()) .andStatusIn(Arrays.asList(待确认, 已确认)); ListAppointment exists appointmentMapper.selectByExample(example); if (exists.size() 0) { return Result.error(该教练在该时段已被预约请选择其他时间); } // 3. 校验车辆状态 Car car carMapper.selectByPrimaryKey(dto.getCarId()); if (car null || !空闲.equals(car.getStatus())) { return Result.error(所选车辆不可用); } // 4. 插入预约记录并更新车辆状态 Appointment appointment new Appointment(); appointment.setStudentId(CurrentUser.getId()); appointment.setCoachId(dto.getCoachId()); appointment.setCarId(dto.getCarId()); appointment.setAppointDate(dto.getAppointDate()); appointment.setTimeSlot(dto.getTimeSlot()); appointment.setStatus(待确认); appointment.setCreateTime(new Date()); appointmentMapper.insertSelective(appointment); car.setStatus(使用中); carMapper.updateByPrimaryKeySelective(car); return Result.success(预约提交成功等待教练确认); }这段代码里有几个细节值得你注意状态都用中文可读值而不是数字枚举看起来不专业但实际开发中如果只用数字你每写一个查询都要去翻枚举定义中文反而最多省了这一步。当然更规范的做法是用int 枚举类论文里可以写得更漂亮。另外第2步的“存在性校验”我用了selectByExample如果项目里用的是注解SQL或XML效果一样但务必要确保这条查询走到索引否则数据量一大就会慢。3.3 MyBatis多表关联查询实践预约列表需要展示学员姓名、教练姓名、车型、车牌号等信息单查appointment表肯定不够必须在Mapper里做联查。这里我推荐用resultMap关联映射resultMap idAppointmentVOMap typecom.example.vo.AppointmentVO id columnid propertyid/ result columnappoint_date propertyappointDate/ result columntime_slot propertytimeSlot/ result columnstatus propertystatus/ association propertystudent javaTypecom.example.entity.User id columnstudent_id propertyid/ result columnstudent_name propertyrealName/ /association association propertycoach javaTypecom.example.entity.User id columncoach_id propertyid/ result columncoach_name propertyrealName/ result columncoach_phone propertyphone/ /association association propertycar javaTypecom.example.entity.Car id columncar_id propertyid/ result columnplate_no propertyplateNo/ /association /resultMap对应的SQL就是join三张表用别名区分同名字段。要注意一点MyBatis的自动映射有坑当多张表有相同列名比如都有id、create_time时必须用列别名显式指定否则数据会被映射到错误的属性上。这个坑我当年踩了一个晚上才排查出来。3.4 Service层的事务边界事务边界是毕设代码里最容易被忽略的点。以“教练提交测评成绩”为例这个操作至少要同时做三件事插入一条测评记录、把对应的预约状态改为“已完成”、更新学员的学时进度如果成绩合格则推进当前科目。这三件事必须在一个事务里否则可能出现测评记录有了但预约还是“已确认”的数据错乱。Override Transactional public ResultString submitAssessment(AssessmentDTO dto) { // 校验预约状态必须是“已确认” Appointment appointment appointmentMapper.selectByPrimaryKey(dto.getAppointmentId()); if (appointment null || !已确认.equals(appointment.getStatus())) { return Result.error(当前预约状态不允许提交测评); } // 1. 插入测评记录 Assessment assessment new Assessment(); BeanUtils.copyProperties(dto, assessment); assessment.setAssessTime(new Date()); assessmentMapper.insertSelective(assessment); // 2. 更新预约状态 appointment.setStatus(已完成); appointmentMapper.updateByPrimaryKeySelective(appointment); // 3. 如果合格推进学员科目进度 if (dto.getTotalScore() 80) { studentProfileService.updateSubjectProgress(appointment.getStudentId()); } return Result.success(测评提交成功); }这里Transactional必须加在public且非私有方法上而且不能同类调用比如Controller直接调本类的另一个带事务注解的方法会失效。这一点是Spring事务的经典考察点答辩很可能被问到。3.5 登录鉴权与拦截器毕设的登录鉴权不一定要上Spring Security/JWT那一套重的框架用拦截器Session就能搞定而且容易讲清楚。登录成功后将用户对象放入Session写一个LoginInterceptorpublic class LoginInterceptor implements HandlerInterceptor { Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { HttpSession session request.getSession(); User user (User) session.getAttribute(user); if (user null) { response.setContentType(application/json;charsetUTF-8); response.getWriter().write({\code\:401,\message\:\未登录\}); return false; } return true; } }在SpringMVC配置里注册拦截器并配置放行路径登录、注册、静态资源放行其他接口全部拦截。再写一个继承Interceptor的权限拦截器根据用户角色判断能否访问管理员接口和教练接口。两个拦截器叠加就能实现完整的权限控制。这块内容在论文里写“系统安全性设计”段落时素材非常充足。4. 前端Vue实现从页面到交互4.1 路由设计与页面骨架前端项目我建议用Vue CLI创建路由用vue-router状态管理用Vuex或者Vue 3的Pinia如果你用Vue 3的话。页面结构按角色划分const routes [ { path: /login, component: Login }, { path: /, component: Layout, redirect: /home, children: [ { path: home, component: Home, meta: { title: 首页 } }, { path: student/assessment, component: StudentAssessment, meta: { role: STUDENT } }, { path: student/appointment, component: StudentAppointment, meta: { role: STUDENT } }, { path: student/profile, component: StudentProfile, meta: { role: STUDENT } }, { path: coach/appointments, component: CoachAppointments, meta: { role: COACH } }, { path: coach/assess, component: CoachAssess, meta: { role: COACH } }, { path: admin/dashboard, component: AdminDashboard, meta: { role: ADMIN } }, { path: admin/users, component: AdminUsers, meta: { role: ADMIN } } ] } ];注意路由守卫router.beforeEach里判断是否登录、角色是否有权限没权限就跳转登录页。这一步配合后端的拦截器实现前后端双重权限控制答辩时能明确说出“前端控制页面访问后端控制接口访问”这句话比只说“我用了拦截器”高一个层次。4.2 axios请求封装与拦截器前后端分离的项目里axios封装是标配。我通常的做法是import axios from axios; const service axios.create({ baseURL: /api, timeout: 10000 }); // 请求拦截器自动携带凭证 service.interceptors.request.use(config { // 从sessionStorage中取token或从cookie中取sessionId return config; }, error { return Promise.reject(error); }); // 响应拦截器统一处理返回码 service.interceptors.response.use(response { if (response.data.code 401) { router.push(/login); return Promise.reject(new Error(未登录)); } if (response.data.code ! 200) { Message.error(response.data.message); return Promise.reject(new Error(response.data.message)); } return response.data.data; }, error { Message.error(网络异常); return Promise.reject(error); }); export default service;这里有两个细节一个是baseURL设置为/api配合Vue CLI的devServer代理转发到后端端口这样可以完美避开跨域问题不需要在后端配CORS虽然我还是建议后端也配一下CORS作为兜底另一个是响应拦截器里直接return response.data.data这样调用方拿到的就是业务数据本身不用每个组件里都写res.data.data这样丑陋的链式取值。4.3 预约页面的核心交互逻辑学员预约页面是前端交互最复杂的页面要联动三个关键信息日期、时间段、教练和车辆。我的实现逻辑是学员先选择教练教练列表卡片展示头像、教龄、评分。选择“日期 时间段”后调后端接口查询“该教练此时段是否已被预约”如果已被预约组件直接禁用该时段按钮。车辆选择跟随教练走某个教练默认绑定一辆指定车辆学员不需要选车简化操作管理员在后台维护教练和车辆的绑定关系。日期选择器要禁用今天以前的日期时间段的选择用按钮组而不是下拉框交互更直观。按钮禁用逻辑这样写el-button v-forslot in timeSlots :keyslot.value :disabledoccupiedSlots.includes(slot.value) clickselectSlot(slot) {{ slot.label }} /el-button这个“已占用时段实时禁用”的功能前端展示效果非常好导师演示的时候也能直观感受到系统的业务完整性。4.4 数据可视化学员进度与教练评分对比管理端的数据看板是这个系统最吸睛的模块建议用ECharts实现。推荐至少放两个图表第一个是“各科目通过率柱状图”从测评记录表按科目分组统计总体及各科目通过率一目了然。第二个是“教练评分对比雷达图”把各教练在测评细项上的平均分画在一个雷达图里直接对比教练在倒车入库、侧方停车等不同教学点上的强弱。ECharts在Vue里的使用方式很简单装依赖后按需引入即可import * as echarts from echarts; mounted() { this.chart echarts.init(this.$refs.chartRef); this.loadData(); }, methods: { async loadData() { const data await getCoachRadarData(); this.chart.setOption({ radar: { indicator: data.indicators.map(i ({ name: i.name, max: 100 })) }, series: [{ type: radar, data: data.coaches }] }); } }注意ECharts在组件销毁时要手动dispose否则会内存泄漏。beforeDestroy钩子里加一行this.chart.dispose()这个小细节写进博文或论文都是一句话的事但很多学生想不到。4.5 Vue组件复用与代码组织写Vue代码最忌讳的就是每个页面复制粘贴一大段几乎相同的表格代码。学员端查看测评记录、教练端查看已完成的测评、管理端查看所有测评本质都是同一个“测评结果表格”只是数据接口和操作列不同。我的建议是抽一个AssessmentTable.vue公共组件通过props传入数据源和操作按钮配置三个页面分别调用。组件抽好后前端代码量大约能减少三分之一更重要的是论文里可以写“本项目通过组件化设计提高了代码复用率”比纯CRUD有亮点。5. 论文怎么写才不像凑字数5.1 论文结构模板与章节策略毕设论文有固定的套路你不需要创新结构但要避免“一看就是凑字数”。我推荐的章节结构和各章写作策略如下章节核心内容写作策略第1章 绪论背景、意义、国内外现状背景结合驾培行业政策意义分理论意义和实际意义国内外现状要引用文献不用多每段两三篇就够第2章 相关技术SSM框架、Vue、MySQL、ECharts切忌大段抄官网介绍要把每个技术写成“我在项目中怎么用它解决什么问题”第3章 需求分析可行性分析、角色分析、用例图、功能需求、非功能需求用例图用Visio或ProcessOn画这是最容易被老师翻看的图第4章 系统设计总体架构图、功能模块图、E-R图、数据库表结构、核心业务时序图尽量多画图每张图配一段说明文字图表不会查重第5章 系统实现各模块页面截图 核心代码 代码说明按“学员模块—教练模块—管理模块”的顺序写每个功能贴1-2段核心代码并解释第6章 系统测试测试环境、功能测试用例表、测试结果列一张测试用例表覆盖登录、预约、取消、测评、统计等核心功能第7章 总结与展望项目总结、不足与改进方向不足建议写“并发能力不足”“未实现移动端适配”等真实问题比空话有说服力5.2 核心章节的写作技巧与查重规避论文最容易查重爆表的是“相关技术”这一章。你去看那些模板写“Spring是一个轻量级容器框架IoC和AOP是它的核心思想”——这种话早就被翻烂了查重直接飙红。我的写法是“本项目选择Spring框架作为应用的核心容器。在项目启动时Spring负责创建和管理Controller、Service、Mapper等Bean实例在处理预约提交请求时Spring的声明式事务管理可以确保多表操作的数据一致性例如学员提交预约后新增预约记录与更新车辆状态必须同步成功或失败。”看到了吗同样是介绍Spring但每一句都结合了本项目既不是官网抄的又能展示你真正在用框架。需求分析章节不要只写“系统分为三个模块学员模块、教练模块、管理员模块”这种废话。每个功能点都要写清楚功能描述、参与者、前置条件、基本流程、异常流程。以“学员取消预约”为例参与者学员前置条件该预约状态为“待确认”或“已确认”基本流程学员点击取消 → 系统校验状态 → 将预约状态改为“已取消” → 释放对应车辆异常流程预约状态为“已完成”时无法取消提示“已完成测评无法取消”这样一个功能点写200字系统里至少有十几二十个功能点需求分析章节根本不用愁凑字数。5.3 论文配图与表格制作建议论文中所有架构图、流程图、E-R图不要直接截图别人的用ProcessOn或者draw.io自己画也不要在图上画得花里胡哨。统一风格最简单的方法全部用黑白或同一色系的方框箭头字体统一微软雅黑每个图下面写“图4-1 系统总体架构图”这样的编号说明。页面截图建议统一用Chrome无痕模式的窗口提前清理无关书签和插件截图时保证页面数据是真实模拟的——比如测评分数不要全是100分要有高有低才有说服力。这些细节老师不会明说但看到整齐的图表和真实的演示数据印象分会高不少。6. 答辩和演示的实战技巧6.1 演示脚本5分钟讲清核心亮点答辩演示不要从登录开始慢慢点老师没耐心看。我建议按“业务闭环技术亮点”设计演示路径开场30秒用管理员账号登录展示统计看板——通过率柱状图、教练评分雷达图让老师第一眼看到“系统有统计能力”。切到学员账号演示“查看教练列表 → 选择教练 → 选择时间 → 提交预约”强调此时的时段冲突校验。切回教练账号演示“查看待确认预约列表 → 确认预约 → 进行测评打分展示分项打分表单 → 提交测评”。切回学员账号刷新页面展示测评结果和评语强调“状态从待确认→已确认→已完成”的流转闭环。最后切到管理员展示用户的增删改查一句话带过把时间留给前面的业务闭环。整个演示控制在5分钟内提前录屏备份。每年都有学生当场演示时数据库没启动、端口被占用提前录好视频至少能保底。6.2 高频答辩问题与应答思路根据我多年在答辩现场的经验SSMVue这个组合被问到最多的问题就这些“为什么用SSM而不用SpringBoot”回答思路SpringBoot的自动配置确实简化了开发但SSM的XML配置让框架的运行机制更透明比如SpringMVC的DispatcherServlet、MyBatis的Mapper扫描都是在配置中显式声明的这对我理解三层架构更有帮助。如果老师追问“那你觉得SSM和SpringBoot各有什么优缺点”就围绕约定大于配置、微服务生态、学习曲线回答。“MyBatis和Hibernate有什么区别”回答思路MyBatis是半自动ORMSQL由自己写灵活可控适合复杂查询Hibernate是全自动ORM对象表映射由框架自动完成适合CRUD密集且表关系不复杂的场景。本项目涉及大量多表联查比如预约信息需要关联用户表、车辆表、测评表用MyBatis可以精确控制SQL性能所以选了MyBatis。“预约冲突你是怎么避免的”回答思路分两层。数据库层通过唯一索引避免同一教练同一时段重复插入业务层在插入前先查询是否存在“待确认”或“已确认”状态的预约且用Transactional保证查询和插入是一个原子操作。然后举出一个极端场景如果两个学员同时提交同一教练同一时段的预约数据库唯一索引会拦住后提交的那一个保证数据不会错乱。“前端页面是怎么和后端交互的”回答思路Vue通过axios发送HTTP请求到SpringMVC的Controller参数以JSON格式传递后端返回统一格式的Result对象前端axios响应拦截器统一处理业务码。再提一句开发环境下通过devServer代理解决跨域生产环境部署到同一容器下由Nginx统一转发。这些都是“送分题”关键是你自己要真的理解不要背答案。老师追问到第二层如果答不上来前面的印象分就全没了。7. 常见问题排查与避坑手册7.1 环境与部署常见问题快查现象原因解决方案后端/前端端口被占用上次运行没有完全关闭netstat -ano查PID后杀掉或用fuser -k 8080/tcp前端请求后端全是404接口路径或代理配置不对检查vue.config.js的proxy配置确认target指向后端端口和上下文路径Maven依赖下载失败网络源不稳定换成阿里云镜像源settings.xml里配置mirror节点连接数据库报Communications link failure数据库没启动或host不对确认MySQL服务已启动jdbc.url中的地址、端口、库名、时区参数是否正确MyBatis报BindingExceptionMapper接口和XML未绑定检查Mapper接口的全限定名、XML的namespace、applicationContext.xml里mapper扫描路径我见过最多的翻车现场是数据库时区问题serverTimezoneAsia/Shanghai没加导致日期存储的时间差8小时。这个参数一定要记得在JDBC连接串里写清楚前端显示的预约日期才不会错乱。7.2 前后端联调阶段的高频Debug记录跨域报错CORS即使前端配了proxy如果后端没有兜底配CORS部署时也会出问题。在SpringMVC配置类里加一个CorsFilterBean public CorsFilter corsFilter() { CorsConfiguration config new CorsConfiguration(); config.addAllowedOriginPattern(*); config.addAllowedMethod(*); config.addAllowedHeader(*); config.setAllowCredentials(true); UrlBasedCorsConfigurationSource source new UrlBasedCorsConfigurationSource(); source.registerCorsConfiguration(/**, config); return new CorsFilter(source); }注意addAllowedOrigin(*)和setAllowCredentials(true)同时使用会有冲突新版本Spring要求用addAllowedOriginPattern(*)代替。列表页表格数据渲染不出来多半是后端返回的字段名和前端定义的不一致。比如后端返回createTime前端写成了create_time显示出来的表格全是空列。遇到这种问题不要拼命调前端先用Postman或浏览器直接请求接口看返回的JSON结构是什么再决定在前端改字段名还是后端加JsonProperty注解。Element UI表格操作列点击无反应检查事件绑定操作列里是否有click.stop以及是否有未被发现的按钮类型默认提交行为。还有常见的一种情况el-table的row对象里根本没有对应字段导致点击时拿到的是undefined。7.3 毕设时间管理与心态建议最后聊点实在的。毕设最忌讳的就是前松后紧我建议你按这个节奏推进第一周定好数据库表和接口清单第二周把后端所有Mapper和实体类生成好第三周把后端的业务逻辑全部写完先不写前端第四到五周集中写前端页面和联调第六周写论文和准备演示数据最后一周做整体测试和答辩演练。如果你用的是IDEA社区版没有自带Tomcat集成直接在pom里引入tomcat插件用cargo-maven3-plugin或者tomcat7-maven-plugin运行Web项目不需要付费版。遇到不会写的地方先自己查半小时还解决不了再问同学或看博客。不要一上来就找代做代做的代码拿到手你根本讲不清楚答辩分分钟被老师问穿。自己写的项目哪怕有瑕疵至少每一行代码的逻辑你都心里有数。我在实际带项目的过程中发现学生最容易翻车的地方反而不是技术本身而是“需求没想清楚就开写”、”数据库表设计改了三次导致代码推倒重来“。所以如果你现在还没建库建表先别急着写代码拿起纸笔把角色、流程、状态、边界都画清楚后面会顺很多。这个系统做完之后你其实还留了不少可以继续扩展的方向比如增加在线模拟考试功能、接入地图服务展示训练路线、或者做成微信小程序版本。不管这次毕设最后评了几分这套从设计到落地的思路在你之后找实习或者入职做真正项目时都会反复用到。先把眼前这个驾校测评系统做扎实比什么都有用。
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门