ARTICLE DETAIL

资讯详情

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

SpringBoot3+Vue3租车管理系统毕设实践:从技术选型到部署答辩全复盘

SpringBoot3+Vue3租车管理系统毕设实践:从技术选型到部署答辩全复盘 简介这是一套面向计算机专业本科生的2025届毕业设计级全栈项目资源聚焦租车业务场景解决车辆租赁服务中用户预订、订单管理、车辆调度与后台监管等核心需求适用于课程设计、毕设开题与SpringBootVue工程实践学习。资源共6个文件含3个ZIP分别封装前后端源码与返修材料、1个MP4系统操作录屏、1个SQL数据库脚本及1个DOCX需求文档总大小98.04MB结构清晰、模块完整便于快速部署与代码研读。已有108人学习下载配套B站双视频教程系统演示启动部署覆盖从环境配置、数据库导入到前后端联调的全流程需求文档详述功能边界与用例流程SQL脚本适配MySQL8源码基于SpringBoot3与Vue.js3 Composition API开发具备现代Web应用典型分层架构与RESTful接口规范可直接用于答辩演示或二次开发。 2025年做毕业设计我选了“租车车辆管理系统”这个题技术栈直接定成Java SpringBoot3 Vue.js3。说实话这套组合在计算机专业毕设里已经是“标准答案”级别了但真要从零把用户、车辆、订单、权限这一整套流程跑通需要处理的问题远比想象中多。这篇文章是我整个项目的复盘包括技术选型原因、后端核心模块怎么设计、前端Vue3工程怎么搭、部署阶段踩过的坑以及最后答辩时最加分的几个点。如果你正在做同类型的系统或者想在简历上写一个“能讲清楚”的项目这篇内容可以直接拿来参考。1. 项目整体设计与技术选型思路1.1 为什么选择SpringBoot3 Vue3这套组合先说选型。2022年以后SpringBoot3正式发布最直观的变化就是强制要求JDK17以上并且把原来基于Java EE的javax.*包全部换成了jakarta.*。很多同学在初始化项目时还习惯找“javax.servlet”的代码结果一跑就编译报错这就是没有提前了解SpringBoot3带来的兼容性变动。我用SpringBoot3的原因很简单它是当前最新的稳定主线学校课程和招聘面试都在向这个版本靠拢与其用旧版本做毕设不如直接学新东西。Vue3这边也一样。Vue3的组合式API比Vue2的选项式API更适合做中后台系统配合Vite开发服务器冷启动速度比Webpack时代的Vue CLI快很多。租车管理系统页面数量不多但状态管理、路由守卫、接口拦截这些需求是标配Vue3 Pinia Vue Router这套组合足够覆盖而且社区资料已经非常完整遇到问题很容易搜到解决方案。我当时也考虑过用若依或Ruoyi-Vue这种脚手架。如果单从“快速出成果”的角度看用脚手架确实省事但毕设答辩老师最常问的就是“这个权限拦截是你自己写的吗”“这段逻辑能不能讲清楚”。如果直接用脚手架改改原理一问三不知风险很高。所以我选择从零搭建核心代码都自己控制这也是后面能顺利通过答辩的重要原因。提示如果你对SpringBoot3的底层还不熟建议先花半天时间把“自动配置”“starter依赖”“条件注解”这几个概念过一遍后面做任何模块都会顺手很多。1.2 需求拆解租车系统到底在管什么很多同学拿到题目的第一反应是“不就是车辆增删改查吗”但实际梳理下来租车系统至少包含三个角色、两个端、一条完整业务链。用户端核心流程是注册登录 → 浏览车辆 → 选择车辆和租期 → 提交订单 → 模拟支付 → 到店取车 → 使用中 → 还车 → 结算费用。管理员端核心功能是车辆信息管理、车辆状态维护、订单审核与调度、用户管理、经营数据统计。除了这两个端系统还需要一个权限模型普通用户只能操作自己的订单管理员可以操作所有订单和车辆信息。所以我把业务模块拆成了十个左右用户认证、车辆管理、品牌管理、订单管理、支付模拟、还车结算、统计报表、操作日志、权限管理、公告管理。每个模块都不算复杂但合在一起就构成了一个完整闭环。做毕设的时候最忌讳只做“单表增删改查”因为那样体现不出系统性思维答辩也很难有亮点。数据流方面我画过一条主线用户下单时系统先判断车辆状态是否“可租”然后创建订单同时把车辆状态改成“已预订”模拟支付成功后状态变成“待取车”取车时改成“租用中”还车后进入“待结算”结算完成整个订单归档。车辆状态和订单状态是联动的这一块是系统的核心逻辑也是面试官最容易深挖的地方。2. 后端核心模块实现要点2.1 项目结构和数据库设计先把地基打牢后端我用的是标准的Controller-Service-Mapper三层结构包名按功能划分controller、service、mapper、entity、dto、vo、config、common、exception、util。实体类全部放在entity里前端传参用dto接收返回给前端的统一用vo封装这样每个类职责清晰不会出现一张表打天下的局面。数据库我设计了六张核心表用户表、车辆表、品牌表、订单表、操作日志表、公告表。车辆表包含车牌号、车辆名称、品牌ID、车型、座位数、排量、日租金、押金、车辆图片、状态、总行驶里程、创建时间等字段。订单表包含订单编号、用户ID、车辆ID、预计取车时间、预计还车时间、实际取车时间、实际还车时间、租车天数、订单金额、押金、状态、创建时间等字段。这里有几个设计上容易忽略的点订单编号不要用自增ID业务上最好生成一个可读的唯一单号比如yyyyMMddHHmmss 用户ID后四位 随机数方便后续排查问题。金额字段用DECIMAL(10, 2)不要用double否则结算时会出现精度误差。状态字段建议用tinyint或varchar不要用int裸存。我习惯用varchar存枚举名比如AVAILABLE、RENTED代码里可读性更强排查问题时一眼就能看懂。车辆表和订单表建立外键关系。虽然项目里不强制用物理外键但逻辑上要保证订单关联的车辆存在我通过vehicleId做逻辑关联并在Mapper查询时做left join把车辆信息带出来。技术选型上我用了MyBatis-Plus理由是它内置了分页插件和通用BaseMapper简单查询不用写SQL复杂统计再自己写XML。SpringBoot3要使用mybatis-plus-spring-boot3-starter这个依赖不能用旧版的mybatis-plus-boot-starter这是个很容易踩的坑。2.2 用户认证与权限管理Spring Security JWT怎么落地用户登录认证是几乎所有管理系统都绕不开的模块。我在项目里用的是Spring Security JWT的方案。为什么用JWT而不用Session因为前后端完全分离后端服务将来可能水平扩展Session存内存里会有黏性问题JWT是无状态的服务器不保存登录状态只要客户端拿着token后端验签通过就认为是合法请求。这正好是面试里常说的“无状态认证”。实现思路是用户注册时用BCryptPasswordEncoder对密码做哈希处理数据库里绝不存明文。登录接口校验用户名和密码成功后生成JWT把用户ID、用户名、角色封装进token里返回给前端。token有效期我设置的是24小时毕设阶段够用。Spring Security配置类里关掉CSRF放行登录、注册、车辆列表、车辆详情等公开接口其余接口都需要认证。写一个JwtAuthenticationFilter继承OncePerRequestFilter从请求头Authorization里取token解析成功就把用户信息放进SecurityContextHolder后续接口就能直接通过AuthenticationPrincipal获取当前登录用户。角色权限控制用PreAuthorize(hasRole(ADMIN))注解管理员接口只有管理员能访问普通用户访问会返回403。这个模块花了我最多时间因为Spring Security的过滤器链机制对新手不太友好。一开始我把自定义过滤器放到了正确位置结果导致登录接口也被拦截返回401。后来查了官方文档才发现要把过滤器加在UsernamePasswordAuthenticationFilter之前并且要用http.addFilterBefore()而不是http.addFilter()这两者的效果完全不同。注意JWT的密钥不要硬编码在代码里应该写在application.yml里环境切换时用Value读取。毕设虽然不要求安全等级多高但这个习惯在真实项目中很重要。2.3 车辆状态与订单状态流转并发防超租的实现细节租车系统最大的业务难点是“同一辆车不能被两个人同时租走”。如果只是简单的查询车辆 → 创建订单 → 修改车辆状态在高并发场景下会出现两个用户同时查到“可租”然后都下单成功的情况。我采用的方案是数据库乐观锁。在车辆表里加一个version字段下单时不直接update状态而是执行条件更新UPDATE rent_vehicle SET status BOOKED, version version 1 WHERE id #{vehicleId} AND status AVAILABLE AND version #{oldVersion}如果影响行数为0说明车辆已经被别人抢先预订直接抛出业务异常提示“手慢了车辆已被预订”。同时订单状态的设计也严格区分PENDING待支付、PAID已支付、PICKED_UP已取车、RETURNED已还车、FINISHED已完成、CANCELLED已取消。每个状态之间都有明确的流转条件比如订单只能从PENDING取消支付成功后从PENDING进入PAID取车时从PAID进入PICKED_UP还车后从PICKED_UP进入RETURNED管理端确认结算后才变成FINISHED。这样设计的好处是代码逻辑清晰无论前端怎么调后端都会做状态校验非法请求直接被拦。还车结算部分我按“日租金×天数超时费”计算。租车天数按实际还车时间-实际取车时间算不满一天按一天计超时超过两小时额外收取半天租金。这些规则都是业务常识答辩时能讲出来会很加分。我还额外加了“押金管理”的逻辑下单时冻结押金还车结算时如果无违章或损坏押金原路退回毕设里直接做成“模拟退回”扣除订单金额后返回剩余押金。这个点虽然简单但让整个系统更接近真实场景。3. 前端Vue3工程化实践3.1 用Vite初始化项目与目录划分前端我用Vite创建项目命令是npm create vitelatest rent-car-frontend -- --template vue。如果你不熟悉TypeScript直接用JavaScript模板就行毕设讲清楚业务比堆类型重要。项目创建后我又加了几个必备依赖npm install element-plus element-plus/icons-vue npm install pinia npm install vue-router4 npm install axios npm install echarts目录结构我做了清晰划分src/ ├── api/ # 接口请求封装 ├── assets/ # 静态资源 ├── components/ # 公共组件 ├── router/ # 路由配置 ├── stores/ # Pinia状态管理 ├── views/ # 页面 ├── utils/ # axios实例、格式化工具 ├── App.vue └── main.jsapi目录下按业务模块拆文件比如user.js、vehicle.js、order.js每个文件导出对应的请求方法。这样页面里不需要直接写axios.get统一走封装好的接口后续修改接口地址或统一处理逻辑都方便。3.2 接口封装与登录态管理Axios实例封装是前端工程化的关键一环。我创建了一个utils/request.js配置baseURL: /api并在请求拦截器里自动携带tokenrequest.interceptors.request.use(config { const user JSON.parse(localStorage.getItem(userInfo) || {}) if (user.token) { config.headers.Authorization Bearer ${user.token} } return config })响应拦截器里统一处理后端返回的结构比如后端约定{ code: 200, data: ..., message: ... }如果code不是200就弹出错误提示如果是401就清空本地用户信息跳到登录页。这样一来业务代码里不需要重复写错误处理逻辑干净很多。登录态管理我用Pinia。定义了一个userStore保存用户信息、token、角色和登录/登出方法配合localStorage做持久化。路由守卫里判断如果没有token且访问的是需要登录的页面跳转到登录页并带上redirect参数登录成功后自动回到之前想访问的页面。这个交互细节虽然不起眼但在答辩演示时非常效果。3.3 核心页面实现车辆列表、下单流程、管理后台车辆列表页是整个系统门面我用了Element Plus的卡片布局每张卡片显示车辆图片、名称、日租金、品牌、座位数底部是“立即租车”按钮。搜索区域支持按品牌、按日租金区间、按车型筛选这部分用了一个el-form绑定一个query对象点击搜索时重新请求列表接口。下单流程比较复杂。用户点击“立即租车”后进入一个表单页需要选择预计取车时间、预计还车时间系统自动计算租车天数和总费用。这里有个坑el-date-picker的值默认是数组格式如果用value-format设置成YYYY-MM-DD HH:mm:ss提交给后端时会省去很多格式转换的麻烦。我一开始没设置结果后端接收到的日期一直是null折腾了半天才发现是前端传参格式问题。管理后台我实现了车辆管理、订单管理、用户管理和统计报表。车辆管理和订单管理都用el-table加el-pagination状态列用el-tag显示不同颜色比如“可租”绿色、“租用中”橙色、“维修中”红色。统计报表使用ECharts展示近七天订单量趋势和车辆利用率柱状图后台管理首页还放了几个统计卡片总车辆数、今日订单数、本月营收、待处理订单数。这些数据不是假的都是通过后端统计接口实时查出来的答辩时打开页面就能看到联动效果。4. 环境配置与常见问题排查4.1 Java环境变量和Maven配置别再栽在第一步很多同学代码写得没问题结果项目启动不了一看环境变量还没配好。SpringBoot3要求JDK17以上我电脑里装了JDK17和JDK8两个版本所以环境变量尤其重要。Windows系统配置要点是新建JAVA_HOME值是JDK安装目录比如C:\Program Files\Java\jdk-17。在Path变量里添加%JAVA_HOME%\bin。新建MAVEN_HOME值是Maven安装目录。Path里再添加%MAVEN_HOME%\bin。配置完成后新开一个命令行窗口执行java -version和mvn -v验证能看到17和Maven版本号就说明配置成功。这里有个老生常谈的问题明明配了JDK17控制台java -version还是显示1.8。原因是系统Path里可能存在Oracle JDK或第三方软件写入的C:\Program Files (x86)\Common Files\Oracle\Java\javapath它会把java指向老版本。解决办法是把这个路径变量删掉或者把%JAVA_HOME%\bin在Path里的顺序提到最前面。用IDEA开发时还要检查项目SDK和Maven运行环境。File → Project Structure → Project里选择17Settings → Build Tools → Maven → Runner里把JRE也改成17。否则即使IDEA本身没问题Maven打包时也有可能会使用默认的JDK8导致编译报错。4.2 数据库初始化与常见启动报错数据库我用的MySQL 8.0初始化时新建一个rent_car数据库编码选utf8mb4排序规则utf8mb4_general_ci然后执行项目的init.sql脚本创建表结构。SpringBoot配置文件中关键参数spring: datasource: url: jdbc:mysql://localhost:3306/rent_car?useUnicodetruecharacterEncodingutf8serverTimezoneAsia/ShanghaiuseSSLfalse username: root password: 123456 driver-class-name: com.mysql.cj.jdbc.Driver如果启动时报Access denied for user rootlocalhost先确认密码是否正确如果报Public Key Retrieval is not allowed需要在URL后面加allowPublicKeyRetrievaltrue。这两个是我见过最频繁的数据库连接报错。构建过程中很容易遇到java: outofmemoryerror: insufficient memory。这个报错本质是Idea或Maven进程使用的堆内存不足解决办法分两步在Help → Edit Custom VM Options里把IDEA自身的最大堆调大比如-Xmx2048m。在Maven的settings.xml或命令行中添加MAVEN_OPTS-Xmx1024m -Xms512m避免构建时内存不够。如果你的项目依赖中包含不规范的包也可能出现Maven构建时堆溢出。这时可以检查pom.xml是否引入了互相冲突的依赖或使用mvn clean package -DskipTests重新构建。4.3 前端Node环境与Vite代理配置前端开发环境需要用Node.js 16以上的版本。安装完Node后npm会自带不必重复配置。但国内网络环境下npm安装依赖经常卡住或下载超时我建议配置一下npm镜像源npm config set registry https://registry.npmmirror.com这个操作不能多解释懂的都懂目的就是让下载依赖的速度回到正常水平。配置后重新执行npm install基本一两分钟就能装完。开发阶段最常遇到的是跨域问题。前端跑在http://localhost:5173后端跑在http://localhost:8080直接发ajax请求会被浏览器拦截。解决方案是在vite.config.js里配置代理server: { port: 5173, proxy: { /api: { target: http://localhost:8080, changeOrigin: true, rewrite: path path.replace(/^\/api/, ) } } }这样前端请求/api/vehicle/listVite开发服务器会转发到http://localhost:8080/vehicle/list后端接口不需要额外处理CORS。这个方案在开发阶段最简单不需要引入拦截器或CorsFilter。生产部署时我把前端打包成静态文件用Nginx托管并配置了反向代理server { listen 80; server_name localhost; location / { root /home/rent-car/dist; index index.html; try_files $uri $uri/ /index.html; } location /api/ { proxy_pass http://127.0.0.1:8080; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } }这个配置解决了前端路由刷新后404的问题同时也把/api开头的请求转发给后端和开发环境的代理规则保持一致。5. 项目复盘与答辩经验5.1 功能测试和边界情况整理项目写完只是第一步能够经得起测试和推敲才是加分项。我在答辩前花了整整两天时间把整个系统的关键流程走了一遍专门测那些“容易被忽略的边界情况”。第一是重复下单。我在两个浏览器里同时登录不同账号同时点击同一辆“可租”车辆的租车按钮看是否只会有一个订单创建成功。因为加了乐观锁第二个请求会收到“手慢了车辆已被预订”的提示数据库里也不会出现两条有效订单。第二是权限越权。用普通用户账号去访问/admin/vehicle/list接口预期返回403页面也会被路由守卫拦截。为了测试接口层的权限我直接修改前端请求地址把普通用户的token带上观察后端是否拦截。这个测试如果没做答辩时被老师当场试一下就会很尴尬。第三是订单状态非法流转。比如已经取消的订单再调支付接口应该报错已经还车的订单再调取车接口应该报错。我在后端每个状态变更入口都做了校验测试这些边界情况主要为了确认报错信息返回得是否友好而不是让前端白屏。5.2 毕设代码之外最值得记录的几张“底牌”答辩时老师不一定会一行一行看代码但有亮点要主动展示。我准备了几张“底牌”乐观锁防超租设计体现数据库并发意识。Spring Security JWT的无状态认证体现前后端分离架构的选型理由。全局异常处理与统一返回体体现友好错误响应。ECharts动态统计体现数据可视化和SQL聚合能力。订单状态机设计体现业务建模能力。这些点不需要很深奥但每个都要能讲清楚“为什么这么设计”。比如乐观锁我会从“两个人同时租同一辆车”的场景展开讲清楚乐观锁和悲观锁的区别然后说明我为什么选了乐观锁——因为车辆预订冲突概率不算特别高用版本号控制比锁表更轻量。5.3 后续还能怎么扩展如果想把项目做得更完整或者放在简历上更有竞争力有几个方向值得延伸接入真实支付支付宝沙箱或微信支付把模拟支付替换成真实回调同时研究支付回调的幂等处理。引入Redis缓存热门车辆列表、用户验证码降低数据库压力。把分页查询改成Elasticsearch全文搜索支持按车型、品牌、价格区间做复杂筛选。增加消息通知模块在订单状态变化时给用户发送短信或邮件这里可以聊到消息队列。增加车牌识别和车辆定位能力虽然毕设阶段用不上但思路可以体现对行业趋势的关注。我在实际项目里已经预留了部分扩展接口比如订单状态变更的地方我封装了一个OrderStatusManager后面如果加通知或任务调度直接从这里扩展就行。这比把状态逻辑到处写要干净得多也方便后续维护。最后再分享一个做毕设的小技巧把所有关键设计决定和一个“为什么”记到项目README里。我每次调试完一个坑都会在文档里补充一句当时的报错和解决方案。答辩前翻一遍很多细节都记得很清楚回答老师提问的时候明显更有底气。这个习惯后来用在工作里帮我省了太多时间。本文还有配套的精品资源点击获取
返回列表