SpringBoot+Vue 做汽车租赁管理系统,这个组合在毕设里算是一套“标准答案”了。项目本身不复杂,但前后端该有的东西都有:用户登录、权限区分、车辆管理、订单流转、租金计算、统计图表,一个完整的业务闭环。如果你是本科毕业设计或者课程设计选了这么个题目,只要把下面这些逻辑理清楚,代码写得干净一点,答辩的时候能解释清楚“为什么这么设计”,拿个不错的成绩问题不大。
这篇文章我不打算只贴一个“源码下载地址”然后就完事,而是把我当年做这个项目时踩过的坑、想明白的道理、以及这个系统背后真正值得你花时间的核心逻辑,都摊开来讲。不管你拿到的是哪一版源码,只要你理解了这套业务和设计思路,换成别的技术栈(比如把前端换成 React,或者把 MySQL 换成 PostgreSQL),你照样能做得出来。
1. 项目概述:这到底是个什么样的系统
1.1 核心功能与业务场景
汽车租赁管理系统解决的是一个很简单但很繁琐的问题:一个租车公司,手里有几十台车,怎样才能搞清楚每台车现在在哪、被谁租着、租金该收多少、什么时候该保养了。
往细了说,系统至少要管住这几件事:
- 车辆信息管理:车的基本资料(品牌、型号、车牌、颜色、座位数)、车辆状态(可用、已租、维修、保养)、照片、每日租金定价。
- 客户信息管理:租车的人是谁,身份证号、电话、驾驶证信息,租车历史记录。
- 订单流程:从客户下单、选车、提交订单,到管理员审核、确认取车,再到实际还车、结算租金,最后归档。这个流程是系统的核心主线。
- 租金计算:租金不是简单的“日租价乘以天数”,否则这套系统就没什么技术含量了。真实场景里通常会涉及:租期不足一天的怎么算、超时还车怎么加收费用、押金怎么核算退款、优惠折扣怎么叠加。
- 统计报表:每个月租出去了多少车、营收是多少、哪款车最受欢迎、哪个客户是回头客。毕设里做几个 ECharts 图表展示出来,视觉上就直接加印象分。
这个系统在业务上和你手机里那些共享单车 App 有本质区别:共享单车是全自动的计费,而汽车租赁因为涉及证件审核、押金、车况确认、事故责任归属,线下的“人”参与度非常高。所以这个系统的核心并不是“自动化”,而是把线下流程里的每一个环节都数字化、可追溯。这一点想明白了,你在设计表和状态机的时候就不会画错方向。
1.2 为什么这套选题适合毕设和课设
很多人选毕设题目有个误区,要么选了一个“看起来很简单但全是什么管理系统增删改查”的题,答辩的时候没什么可讲的;要么选了一个“太硬核”的题,比如做一个分布式高并发秒杀系统,结果自己根本写不完,代码全是拼接的,连自己都看不懂,答辩一问就露馅。
汽车租赁管理系统属于典型的“业务复杂度适中、技术覆盖面广”的选题。它不是一个空壳的增删改查,它有明确的核心流程(订单状态流转),有需要认真思考的设计点(租金计算规则、权限控制),也有可以拔高的技术点(统计分析、Redis 缓存、文件上传、Excel 导出)。难度你可以自己调节:只是六张表互相增删改查也能跑,但如果你愿意,把一个订单状态机设计得很严谨,把数据权限做得很细致,这也能成为你在答辩时最有说服力的亮点。
另外,这个系统天然带有多角色。管理员、普通用户(前台租车)、门店操作员,不同的角色看到不同的页面、操作不同的功能。这就逼着你必须去考虑权限问题——不是你假装做一个判断就能糊弄过去的。这个设计点在任何答辩评委那里都吃得开。
2. 技术选型背后的事:SpringBoot + Vue + MySQL 为什么是黄金三角
2.1 后端为什么选 SpringBoot
SpringBoot 在今天已经是 Java Web 开发的事实标准了,不用争论。它对刚接触企业级开发的在校生来说,最大的意义是“帮你把繁琐的配置收走”。
如果你用过老式的 Spring MVC 项目,你会记得那种痛苦:XML 配置写了一堆,web.xml、spring-mvc.xml、数据源配置、扫描包配置,光是把项目跑起来就累得半死,而这还没有写一行业务代码。SpringBoot 用自动配置把这些全都解决了,你只需要在application.yml里写好数据库连接、端口号,然后就能专注于写 Controller、Service、Mapper。
这个项目我建议你选择 SpringBoot 2.7.x 版本,而不是 3.x。原因是社区里大量的教程、开源代码都是基于 2.x 的,而且 2.x 和之后要整合的很多中间件兼容性更好。SpringBoot 3.x 强制要求 JDK 17,且底层使用 Jakarta EE 命名空间,很多旧工具类直接不兼容,对于只想顺利毕业的学生来说,没必要在这种地方给自己挖坑。
启动类写得非常简洁:
@SpringBootApplication @MapperScan("com.rental.system.mapper") public class CarRentalApplication { public static void main(String[] args) { SpringApplication.run(CarRentalApplication.class, args); } }三行代码,一个可启动的 Web 服务,这在十年前是不敢想象的。
2.2 前端为什么选 Vue
Vue 在国内中小型项目里的普及率非常高,学习曲线比 React 缓得多,特别适合“从零开始且需要快速出效果”的前端项目。
Vue 的核心价值在于“响应式数据绑定”和“组件化开发”。比如车列表页面,你只需要维护一个carList数组,在 Vue 里把它v-for循环渲染到页面上,当你从后端拿到数据更新carList时,页面自动刷新。这在原生 JavaScript 里需要手动操作 DOM,写一大堆 appendChild,而且一旦业务复杂,代码就失控了。
这个项目的前端,我建议直接用 Vue CLI 创建(或者 Vite),配合以下几个关键库:
- Vue Router:管理页面路由。比如
/car/list是列表页,/order/detail/:id是订单详情页。还有动态路由的概念,根据用户角色动态生成菜单。 - Axios:发送 HTTP 请求到后端接口,统一拦截处理 token 和错误信息。
- Element UI(或 Element Plus):组件库。表格、表单、日期选择器、弹窗,这些都直接用现成的,千万别自己手写样式,你会浪费大量时间。
2.3 MySQL 为什么合适
MySQL 在关系型数据库里的地位不用多说。对这个项目来说,MySQL 8.0 是首选。数据表之间的关系(用户与订单、订单与车辆、车辆与品牌)非常清晰,用外键关联和索引就能拿到理想的查询性能。
有人问我:为什么不选 Oracle?因为没必要,而且毕设环境里 Oracle 的安装就够折磨人了。为什么不选 MongoDB?因为你这个业务根本不需要文档型数据库的灵活性,车辆、订单有明确的结构和约束,关系型数据库是天然合适的。
2.4 为什么坚持前后端分离
这个项目的架构是前后端完全分离的:Vue 开发环境跑在 8080 端口,SpringBoot 跑在 8081 端口,两者通过 RESTful API 通信,期间用 JSON 传递数据。
这样做最大的好处是结构清晰、职责单一。后端的 Controller 只负责处理请求返回 JSON,前端只用关心渲染。两个人在分工协作时(比如你和你的组员),一个人管前端一个人管后端,互不干扰,只需要提前约定好接口文档。
另一个实际的好处是,你可以用其他工具直接调试后端的接口,比如 Swagger、Postman、Apifox。这一点在联调阶段能救你的命。
3. 项目目录结构:一开始先定规矩,后面才不会乱
3.1 后端目录结构
一个清晰的项目结构,在答辩时能让你少费很多口舌。我建议按“经典分层”来组织:
com.rental.system ├── config // 配置类(Cors、Swagger、Jwt等) ├── controller // 控制器,接收请求 ├── service // 业务逻辑层(接口 + 实现) ├── mapper // 数据访问层(MyBatis 的 Mapper 接口) ├── entity // 实体类 ├── vo // 视图对象,给前端返回的具体结构 ├── dto // 数据传输对象,接收前端的参数 ├── common // 统一返回结果、异常处理、常量 ├── utils // 工具类 └── CarRentalApplication.java这个结构的核心原则只有一个:Controller 里不要写业务逻辑。Controller 拿到前端参数以后,直接转给 Service 处理,Service 内部把事情做完,返回一个结果,Controller 再包装成统一的 JSON 格式交给前端。这个习惯你从学生阶段养成了,以后到公司里没人会说你写的代码“像个学生”。
3.2 前端目录结构
Vue 项目结构也很有讲究:
src ├── api // 接口封装(按模块拆分) ├── assets // 静态资源 ├── components // 公共组件(上传组件、表格组件) ├── router // 路由配置 ├── store // Vuex 状态管理 ├── views // 页面组件(视图) ├── utils // 工具类,axios 封装等 ├── App.vue └── main.js这里我想特别说一下api目录。很多学生习惯在页面里直接写this.$http.post('/api/login'),看起来方便,但一旦接口地址变了,或者后端结构变了,你就需要去每一个页面里改,极其痛苦。正确做法是:每个模块的接口统一封装在api目录下的一个 JS 文件里,页面里只调用方法。比如:
// api/order.js import request from '@/utils/request' export function getOrderList(params) { return request({ url: '/order/list', method: 'get', params }) } export function completeOrder(orderId) { return request({ url: `/order/complete/${orderId}`, method: 'put' }) }想维护的时候就只改这个文件,别的地方都不用动。
4. 核心功能模块拆解与实现重点
这是全文最核心的部分。代码写得好不好看是一回事,功能模块想得清不清楚是另一回事。模块想清楚了,代码只是时间问题。
4.1 用户认证与权限控制(最具含金量)
汽车租赁系统有三类用户:管理员、门店员工、普通租客。不同角色能访问的接口和页面必须区分开。这个系统里我建议用JWT + RBAC的组合方案。
JWT(JSON Web Token)解决的是“你是谁”的问题。登录成功后,后端生成一个 token 令牌,前端后续请求都带上这个 token,后端验证通过后才返回数据。它和传统 Session 方案相比,天然适合前后端分离,服务端不需要保存会话状态。
大概流程是:
- 用户登录,后端校验用户名密码,验证通过后生成一个 token 返回。
- 前端在 utils 封装好的 axios 拦截器里,从 localStorage 取出 token,放进请求头
Authorization: Bearer <token>。 - 后端定义一个拦截器(HandlerInterceptor),对所有请求(除了登录等白名单)进行 token 解析验证。
- 解析出的用户信息放进 ThreadLocal,后续业务代码里可以直接获取当前登录用户。
token 的生成可以用 jjwt 库,核心代码大概是:
public String createToken(Long userId, String username, String role) { return Jwts.builder() .setSubject(username) .claim("userId", userId) .claim("role", role) .setExpiration(new Date(System.currentTimeMillis() + 1000 * 60 * 60 * 2)) .signWith(SignatureAlgorithm.HS256, secretKey) .compact(); }注意我给这个 token 设置了两小时过期时间,时间太短用户用一会儿就掉线很恼火,太长又不安全。两小时算是一个实操经验值,你可以根据需求调整。
RBAC(基于角色的访问控制)解决的是“你能干什么”的问题。最简单的方案是:数据库里建三张表user、role、user_role,用户关联角色,每个角色对应一组菜单权限。但考虑到这是毕设,你可以简化成在用户表里直接加一个role字段,用字符串区分ADMIN、EMPLOYEE、CUSTOMER。
前端拿到用户角色后,动态生成菜单;后端在拦截器里对敏感接口(比如管理员才能调用的接口)做角色校验。千万不要只做前端控制,因为接口如果被直接调用,前端那层控制就是形同虚设。前后端都要做权限控制,这是我一直强调的安全底线。
4.2 车辆信息管理
车辆表是整个系统的“货物基础”,没有车这个系统一切功能都没有载体。
车辆实体起码要包含这些字段:车牌号、车辆品牌(建议用独立字典表,方便做筛选)、车型(轿车/SUV/商务车等)、颜色、座位数、变速箱类型(自动挡/手动挡)、日租金、押金、车辆照片(一个 URL 字段,配合文件上传功能)、当前状态(可用/已租/维修/保养)、公里数、年检到期日。
车辆照片的上传这里有两个选择。一是把图片上传到服务器本地目录,数据库只保存相对路径;二是使用 MinIO 搭建一个简易对象存储服务,把图片传上去返回一个 URL。推荐后者,因为你在简历里多写一句“使用了 MinIO 进行文件存储”,含金量立刻就不一样了。MinIO 的搭建不需要运维知识,下载下来配置一下就能跑。
4.3 订单流程管理(这个系统的心脏)
订单是业务的核心,它具有明确的“状态机”。状态机这个词听起来高级,实际意思就是“一个订单在不同时刻只能处于某个确定状态,而且状态之间的流转是有方向的、需要条件的”。
我建议你设计四个核心状态:
- 待取车(PENDING):客户提交订单,管理员审核通过后生成租车单。此时车被锁定,别人不能租。
- 租用中(RENTING):客户到门店取车,管理员确认发车。订单关联车辆状态改为“已租”。
- 待归还(DUE):到了预计还车时间还没还。系统应该自动提醒,这就是一个定时任务可以发挥的地方。
- 已完成(COMPLETED):客户归还车辆,管理员验车确认,结算租金,订单关闭。
订单状态变化的每一次操作都要记录到order_log表(谁在什么时间把订单从什么状态改成了什么状态)。这个日志表在毕设阶段可能看起来“无关紧要”,但答辩的时候一提到“操作留痕、审计追踪”,这就是亮点。到时候你就能有理有据地告诉评委,这个系统不是玩具,它考虑了真实业务中的纠纷场景。
4.4 租金计算与结算规则
租金计算是纯业务问题,但也是最能体现你是否“入行”的地方。真实租车公司有一个公式,不能瞎设计:
总租金 = 日租单价 × 租用天数 + 超时费用 + 其他费用(如保险选装) - 优惠折扣 押金 = 单独计算,还车后无问题则退还“租用天数”不是简单算两个日期之间差多少天,因为还车时间是按小时算的。真实场景中会用到“租车时长超出整日,但不足一天”的计费规则。你可以在后端设计一个计算工具类,专门处理时间差和费用计算。这个工具类的入参是下单时间、取车时间、计划还车时间、实际还车时间、日租金单价。返回值是详细的费用明细。
这里有一个很重要的点:不要让前端计算租金。前端只负责展示,一切金额计算必须由后端完成。原因很简单:前端传过来的金额是可以被篡改的。如果你让前端传一个“总价 500 元”过来,懂点 HTTP 简单到不行的人完全可以把请求拦截下来改成 5 元。正确的姿势是,前端只传“租用车辆的 ID、开始时间、结束时间”,后端根据库里的单价算出总价。
4.5 统计报表与数据可视化
报表是答辩环节最能展示成果的模块。建议你用 ECharts 做三个图表:
- 近 6 个月营收趋势(折线图):按月汇总完成的订单总金额。
- 车型出租占比(饼图):统计不同车型的出租次数占比。
- 车辆出租排行(柱状图):出租次数最多的 Top10 车辆。
后端的统计 SQL 会复杂一点,但这就是 SQL 的学习机会。给你一个例子,统计每月营收:
SELECT DATE_FORMAT(create_time, '%Y-%m') AS month, SUM(total_amount) AS revenue FROM `order` WHERE status = 'COMPLETED' GROUP BY DATE_FORMAT(create_time, '%Y-%m') ORDER BY month编译好以后,后端组装成图表数据结构返回前端,前端直接用 ECharts 渲染。这一个模块可以充分展示你的 SQL 聚合能力和数据可视化能力。
5. 数据库设计:表结构搭得好,业务就跑不偏
5.1 数据表整体规划
我建议整体设计 9 张核心表。附一张完整清单,你可以对照着设计:
| 表名 | 作用 | 关键字段 |
|---|---|---|
| user | 用户表 | id、username、password(加密)、real_name、phone、role、status |
| car | 车辆表 | id、plate_number、brand、model、car_type、color、seats、daily_rate、deposit、photo、status |
| car_brand | 品牌字典表 | id、brand_name(车站品牌尽量用字典维护,不要写死在代码里) |
| order | 订单表 | id、order_no、user_id、car_id、start_date、end_date、actual_return_date、daily_rate、total_amount、deposit、status |
| order_log | 订单日志表 | id、order_id、operator_id、action、from_status、to_status、remark、create_time |
| insurance | 保险选项表 | id、name、price(租车时可以加选保险,这个表让项目更真实) |
| customer_feedback | 客户反馈表 | id、order_id、user_id、rating、content、create_time |
| notice | 公告表 | id、title、content、create_user、create_time |
不要过度建表,也不要欠设计。比如车辆品牌,有的学生直接把它写成车表里的一个字符串字段,看起来没问题,但当你需要统计“哪个品牌最受欢迎”的时候,你会发现自己没法按品牌聚合。这种因为设计偷懒带来的后端烦恼,我真的见得太多了。
5.2 核心表设计时要注意的几个坑
密码安全,这是老生常谈了。密码绝对不能明文存。用哈希加盐,或者直接用 Spring Security 自带的好消息:BCryptPasswordEncoder。
@Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); }存密码的时候是把密码先通过 encoder 加密再入库存,登录校验时也是把用户传的明文密码跟数据库的 hash 比对,而不是直接查出来对比。对这门课程的作业来说,“登录功能”你做出来了不代表严谨,密码加密这种细节评委很容易问到,你答上来就是加分项。
金额字段类型:千万别用 float 或者 double。浮点数在计算机里通常不是精确的,0.1 + 0.2 的结果可能是不等于 0.3 的。存储金额一律用DECIMAL(10, 2)。你在 Java 里用BigDecimal进行操作,避免精度陷阱。这个知识点太常问了。
时间字段:建议业务时间用DATETIME,如果要考虑时区问题,可以统一使用TIMESTAMP。但更实用的建议是:后端默认使用北京时间存入,前端展示时格式化输出,这样体验最统一。
逻辑删除:不要物理删除数据。用户注册了账号想注销,车辆信息录错了要删掉,正常的做法不是 DELETE,而是在表里加一个deleted字段(0 表示存在,1 表示删除),查询时统一在 SQL 加WHERE deleted = 0。这个习惯在真实企业项目里几乎是标配,论文里能写,答辩里能讲。
6. 实操:把项目从零跑起来
6.1 环境准备
不管你是从开源平台下载的源码,还是自己逐步开发,你需要准备的环境基本是这几样:
- JDK 8 或 11(SpringBoot 2.x,推荐 JDK 8 就够)
- Maven 3.6+
- Node.js 14+ 和 npm(Vue 2 项目建议 node 16,我用 node 16 跑 Element UI 从未出问题;Vue 3 + Vite 建议 node 18+)
- MySQL 8.0
- IDEA(或者 Eclipse,但 IDEA 免费社区版真的够用)
- Navicat 或 DataGrip 作为数据库管理工具
MySQL 的安装有几个坑值得提醒:Windows 上装 MySQL 8.0 时,初始化的默认字符集是 utf8mb4(这个没问题),但是安装完成以后要记得确认 root 用户的鉴权方式。如果你用很老的客户端连接,会出现 “Client does not support authentication protocol requested by server” 这种报错。解决方案是修改 root 用户的加密方式:
ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY '你的密码'; FLUSH PRIVILEGES;如果你是拿现成的源码,这一步卡住的人非常多,报错群里十个有八个是这个原因。
6.2 后端启动步骤
- 用 IDEA 打开后端目录,等待 Maven 自动下载依赖。这一步建议耐心等待,如果下载慢,可以配置阿里的镜像源。
- 本地创建数据库
car_rental,字符集选择utf8mb4。 - 找到源码目录里的
car_rental.sql文件,用 Navicat 打开执行,导入表结构和初始数据。 - 修改
application.yml里的数据库连接信息,主要是url、username、password。 - 运行启动类,看到 “Started CarRentalApplication” 日志,说明 SpringBoot 启动成功。
application.yml里的配置大概长这样:
server: port: 8081 spring: datasource: url: jdbc:mysql://localhost:3306/car_rental?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai username: root password: 你自己的密码 driver-class-name: com.mysql.cj.jdbc.Driver mybatis: mapper-locations: classpath:mapper/*.xml configuration: map-underscore-to-camel-case: truemap-underscore-to-camel-case: true这个配置很有用,它能让数据库的字段(比如plate_number)自动映射成实体的驼峰属性(plateNumber),避免写一堆 resultMap 别名。
6.3 前端启动步骤
- 用 WebStorm 或者 VS Code 打开前端目录。
- 终端执行
npm install安装依赖。 - 如果项目里的
package.json使用的依赖版本比较老,npm 安装过程可能会有警告,先忽略。 - 执行
npm run serve启动开发服务器。
默认地址是http://localhost:8080,打开以后登录页面连不上后端,大概率是跨域问题。解决方式有两种:后端配置 Cors 过滤器(处理 CORS 跨域),或者前端配置开发代理。
前端vue.config.js代理方案更方便:
module.exports = { devServer: { proxy: { '/api': { target: 'http://localhost:8081', changeOrigin: true } } } }这样前端发的/api/login替你把请求转发给后端的8081端口。记住,target是你后端实际端口,且不要填错,这个错误根本查不出来,因为浏览器控制台报的是 “404”。
7. 常见问题与排查技巧
做这个项目会遇到的问题我大概归类成四类:启动类、数据库连接类、接口联调类、前端报错类。我直接给你速查表。
7.1 启动类问题
SpringBoot 启动报错Unknown character set encoding: 'utf8',检查application.yml是否把characterEncoding拼错了;报错Consider defining a bean of type 'xxxMapper',检查启动类是否漏了@MapperScan,或者确认 Mapper 接口有没有加@Mapper注解。
如果启动时端口被占用(Tomcat 默认 8080 被占用),两个解决方案:关掉占用端口的进程(推荐先看任务管理器),或者在配置文件里把server.port改成别的端口。前端和后端的端口别搞成同一个,否则你会看见极具迷惑性的错误。
7.2 数据库连接类问题
最常见的我刚刚讲过:MySQL 8 以上版本需要明确使用com.mysql.cj.jdbc.Driver,老版本的驱动类名(com.mysql.jdbc.Driver)在 8.0 里已经不推荐使用了。
另一个高频报错是Public Key Retrieval is not allowed。这个问题发生在 MySQL 8.0 使用 SSL 安全连接时,最简单粗暴的解决方式是:在数据库连接 URL 后面加两个参数:
?useSSL=false&allowPublicKeyRetrieval=true这个报错出现的原因我说一下,MySQL 8.0 默认使用 caching_sha2_password 认证,客户端连接时要么走 SSL,要么用 RSA 公钥加密传输密码。JDBC 默认不允许获取公钥,所以直接把allowPublicKeyRetrieval=true加上就解决。顺带把 SSL 关掉,本地开发完全不需要。
7.3 接口联调类问题
前端请求后端的接口报 401,说明 JWT 校验失败。按这几步检查:
- 是否在登录之后正确保存了 token?在
localStorage.setItem('token', res.data.token)。 - 是否在 axios 请求拦截器里带了
Authorization头? - 后端的拦截器是否放行了“免登录”接口,比如登录接口本身?
前端请求接口报 500,优先去 IDEA 的控制台看完整异常堆栈。大多数 500 都是后端 NPE(空指针)或 SQL 写错了,控制台会直接告诉你哪一行代码出的问题。新手最容易犯的错是只看浏览器里的报错,不去看后端的日志,绕了很远的路。
7.4 前端打包与部署问题
毕设经常会有一个要求:“把项目部署出来,给老师现场演示”。如果老师要求能在服务器上跑,你需要把 Vue 打包(npm run build)成静态文件,然后放到后端里托管。
这里有个操作诀窍:把打包出的dist目录里的文件,复制到 SpringBoot 的src/main/resources/static目录下。这样你在启动后端的时候,访问http://localhost:8081就能打开前端页面,前后端一体运行,给老师演示的时候非常方便。
但这个方案有一个坑:前端打包时设置的 API 地址必须是相对路径(比如/api)而不能是http://localhost:8081,否则你打包复制过去以后,前端页面还是会去请求 8080(已不存在)的地址。
8. 学习路线:怎么把这个项目吃透,而不是背会
这一步本来想写代码层面的指导,但我想跟你们分享一些更实际的学习思路。
很多学弟学妹拿到源码第一件事是想改系统名称、改作者,然后准备直接拿去交。我不建议这样。数据库可以抄,代码可以抄,但是答辩那十五分钟你要靠自己对项目的理解活下来。老师极其容易问的一个问题就是:“你这个订单模块是怎么设计的,能不能讲讲?”你支支吾吾,那你作为第一作者的含金量就打了折扣。
我建议你拿到一套源码以后,先跑通,再读懂,最后自己重写一遍核心模块。具体你可以这样做:
- 先把项目跑起来,体验一遍功能,把一个完整的业务流程走通:注册用户 -> 查看车辆 -> 下单 -> 管理员审核 -> 还车结算。
- 打开数据库,对着表结构,把每张表之间的关系画出来,搞清楚“用户怎么关联到订单的”、“订单怎么关联到车的”。
- 从前端入手,追踪一次完整的请求链路:用户在页面点击了按钮,请求发到了哪个 API 方法,Vue Router 把用户带到了哪个页面,axios 把请求发到了哪个后端 URL,Controller 是哪个方法,Service 里调了什么逻辑,Mapper 查了哪些表,最后怎么把数据传给前端渲染。把这个链路走一遍,你基本就理解了这个项目的 80%。
- 最后,找一张简单的表(比如车辆表),自己从数据库设计开始,到后端接口,到前端页面,完整地实现一遍。做过一遍的人才真正有底。
一点个人体会:我做这个项目的时候,被 JWT 拦截器折腾了两天,后来发现只是 return 了 true 但是忘了在 interceptor 里放行前置路由。那也是我第一次意识到,为什么认识代码和代码报错时“两眼一抹黑”之间的差距那么大。做毕设真正的意义不是学会某个框架,而是第一次独立地面对一个不完整的、模糊的、带着无数报错的需求,然后把它拆开,慢慢捋顺,最后做出来一个自己能完整讲清楚的东西。
工具和框架只是手段,业务模型和排查思维才是你在这个项目里真正能学到的东西。祝你把项目跑通,答辩顺利。