恒美微站 Logo 恒美微站
  • 首页
  • 关于我们
  • 建站服务
  • 主题模板
  • 案例展示
  • 资讯中心
  • 联系我们

SpringBoot+Vue租车管理系统开发实战:从设计到部署踩坑记录

  • 首页
  • 资讯中心
  • /
  • SpringBoot+Vue租车管理系统开发实战:从设计到部署踩坑记录

相关资讯

专科生毕业论文AI工具推荐:8个网站按写作流程分工解析 2026/10/5 13:36:08
HBase底层原理与读写机制详解:从WAL到Compaction 2026/10/5 13:31:08
AgentsMesh 实战案例集:多Pod委托编排、E2E自动化测试与服务器部署 2026/10/5 13:31:08

最新资讯

测试左移落地实践:从需求评审到CI质量门禁
插件系统四层契约:声明、能力、交付与加载
代码重构美学:从能跑到能看懂,重构如何成为一门手艺
居民负荷分层调度:双层鲸鱼算法与分时电价优化实战
VS2010 MFC围棋游戏工程解析:从GDI绘制到AI剪枝
UVa 13116 传送迷宫最短路:分组懒广播与Dijkstra优化

今日推荐

第26课:OpenClaw|日志审计与问题诊断:把日志链路改到 TaoToken 的排查清单
YOLOv5 OBB旋转框训练实战:从DOTA数据准备到调参避坑全流程
Zeron 终端、Worktree 与 Diff 面板:像 IDE 一样查看并驱动你的代码变更

本周热门

MR25H40CDF + PIC18F65K40:工业记录仪高可靠存储实战
基于STM32的数控恒压恒流电源设计:从硬件到PID调参全解析
LT9211 MIPI重定时器原理与双路扇出实战指南

本月精选

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证
2026 大模型集体涨价:用 Python 做企业 Token 成本测算与选型避坑(附配置)

SpringBoot+Vue租车管理系统开发实战:从设计到部署踩坑记录

发布时间:2026/10/5 13:36:08
SpringBoot+Vue租车管理系统开发实战:从设计到部署踩坑记录 开头做毕业设计或者公司内网小项目时“租车服务管理系统”是特别容易撞车的题目但也是最适合当时练手的场景。一套完整的租车系统要覆盖用户登录注册、车辆信息浏览、在线下单、订单审批、费用计算、车辆状态流转这些环节正好能把SpringBoot的后端功底和Vue的前端交互能力都串起来。本文要聊的是我在实际落地这个项目时的完整思路和踩坑记录从SpringBoot项目结构、MySQL表设计到Vue路由、动态菜单、打包部署尽可能把每一步的取舍和操作细节说清楚。适合准备做SpringBootVue相关毕设的同学也适合想自己搭一套完整前后端分离项目的入门开发者参考。我建议你带着“如果我要把这个系统改成重新跑一遍”的心态来读而不是光看功能清单。租车系统的核心难点不在于概念新而在于业务状态机、金额计算和前后端权限联动这类细节写起来极其啰嗦。下面按我从设计到落地的实际顺序展开。1. 需求梳理与功能模块划分1.1 租车业务到底在管什么很多人拿到这类题目第一反应是搞几张表、写几个增删改查页面就交差但租车业务比表面看起来要复杂一些。核心角色至少有三个普通用户租车人、管理员门店/平台运营、系统后台负责审核与统计。业务流程大体是这样用户注册登录后浏览在租车辆选择取还车时间后提交订单管理员在后台审核订单、确认车辆可用并完成取车交接用户归还后系统根据租用天数和单价计算费用同时更新车辆状态。这里面最容易被忽视的是“车辆状态”这个概念。它不是简单的“在库/租出”二选一而是包含了可租、已预订、已取车、维修中、已下架等多个状态而且状态之间不能随便跳。比如一辆车被下一条订单预约了哪怕还没有正式取车也应该从用户端隐藏或不可选否则就会出现超卖。我在设计表结构时把状态字段独立出来并且所有状态变更都走统一的服务方法就是为了避免到处直接改字段。1.2 功能模块清单整理之后功能模块大致如下用户端注册、登录、个人信息维护、车辆浏览与条件筛选、下单、我的订单列表、取消订单、还车申请。管理员端用户管理、车辆信息管理上下架、维修标记、订单审核、订单列表查询与统计、租金结算、基础数据管理品牌、门店。公共模块登录鉴权、统一异常处理、文件上传车辆图片、操作日志。这些模块如果合并到一张架构图里看本质就是“用户—订单—车辆”三个核心实体加上权限控制。后面的数据库设计和接口设计都围绕这三条主线走不要贪多。很多同学喜欢一开始就加“优惠券”“保险”“违章押金”结果数据关系越搞越乱最后答辩时自己都讲不清。我的建议是先把主线做扎实扩展功能放到最后的扩展点里提一嘴即可后期有时间再补。2. 技术选型与数据库设计2.1 SpringBoot后端技术栈选择后端我使用的是SpringBoot 2.7.x版本。之所以不用最新的SpringBoot 3.x一方面是新版本要求JDK 17基线很多学校的服务器和电脑还停在JDK 8另一方面是SpringBoot 2.7仍然在主流维护期内相关的集成资料、网上踩坑记录都比较全更适合毕业设计或中小型项目。如果你用的是IDEA 2026这类新开发环境创建SpringBoot项目时直接在Spring Initializr里选Java 8和SpringBoot 2.7.18即可没必要迷信最新版本。持久层我选了MyBatis-Plus而非原生MyBatis或JPA。原因很简单租车系统的单表查询很多MyBatis-Plus提供的内置方法能省掉大量重复的XML和Mapper代码。比如分页查询车辆列表只要引入PaginationInnerInterceptor写一个LambdaQueryWrapper就能搞定不用手写Count查询和Limit拼装。如果后面需要复杂统计比如“某个月门店收入”再单独写XML里的SQL就行完全够用。权限认证方面我选了JWTJSON Web Token方案。前后端分离项目的Session处理比较别扭JWT无状态、跨域友好配合SpringBoot拦截器就能完成登录校验。要注意的是JWT的密钥要放在配置文件里而不是写死在代码中过期时间我设置的是两个小时用户每次操作时前端可以在响应401后主动跳转登录页。2.2 前端Vue技术栈选择前端我用的是Vue 2 Element UI这个组合虽然不如Vue 3 Element Plus新但胜在稳定且资料多。如果是从零开始学我建议你直接学Vue 3 Element Plus毕竟官方生态已经全面转向Vue 3。但我这里要强调一点很多同学在Vue安装及环境配置这一步就卡住了常见问题包括npm版本过老、node-sass安装失败、vue-router版本不匹配等。Vue 3项目建议直接使用Vite构建node版本在16以上就行用npm create vitelatest快速初始化不要再用vue-cli那套老古董。路由管理我使用Vue Router。考虑到租车系统的菜单权限是动态的管理员和普通用户看到的侧边栏不一样我这里实现了动态路由。具体思路是前端只定义静态路由登录、首页、404用户登录后根据返回的角色标识和菜单权限列表通过router.addRoute()动态注册业务路由。这个比把所有路由都写在静态文件里再靠v-if控制要好维护得多页面刷新后也能从store或localStorage中恢复权限数据。组件通信方面涉及少量跨组件状态时我没上Vuex直接用了一个简单的store模式一个js文件导出reactive对象。只有当用户信息、车辆列表筛选条件、订单状态等被多个页面同时使用时才考虑Pinia或Vuex。过度设计在中小型项目里反而是负担。2.3 数据库表结构设计数据库我采用的MySQL 8.0字符集统一utf8mb4。核心表我拆成了五张用户表、车辆表、品牌表、订单表、操作日志表。不要把所有字段塞进一张表也不要因为追求范式把车辆和品牌拆成完全无关的两张表适度冗余更实用。用户表大概长这样核心字段为id、username、passwordBCrypt加密、phone、role0普通用户、1管理员、status0禁用、1正常。车辆表字段比较多有id、brand_id、model_name、plate_number、daily_rate、status0可租、1已预订、2已租出、3维修中、cover_image、location、description。订单表是核心中的核心字段包括id、order_no、user_id、car_id、start_date、end_date、total_days、total_amount、status0待审核、1已确认/待取车、2使用中、3已完成、4已取消、create_time等。表关系上订单表的user_id关联用户表idcar_id关联车辆表id品牌表的id被车辆表brand_id引用。这些外键逻辑在业务上必须保证但我实际建表时没有加物理外键约束而是在服务层校验。原因有两点一是物理外键在高并发插入或更新时有一定性能影响二是MyBatis-Plus在逻辑删除和分页时对带外键的表有时会有额外限制。如果你担心数据一致性可以通过事务和业务代码来保证。我额外加了几个索引订单表的user_id和status联合索引、车辆表的status索引、订单表的order_no唯一索引。这些索引是实际测试时发现的性能瓶颈比如后台“待审核订单”列表页面如果订单积累多了没有索引时查询会全表扫描后面数据一多页面响应就会明显变慢。3. 后端SpringBoot核心实现3.1 项目结构与统一响应后端代码我按照“Controller—Service—Mapper—Entity”四层结构组织Controller只做参数接收和响应包装Service里放业务逻辑Mapper负责数据库交互。下面是我常用的包结构controller存放接口入口如UserController、CarController、OrderControllerservice业务逻辑接口和实现类如OrderService、OrderServiceImplmapperMyBatis-Plus的Mapper接口entity数据库实体类common统一响应类、异常处理、工具类config配置类如WebMvcConfig、CorsConfig、InterceptorConfig统一响应类是前后端联调的基础。我定义了一个Result 类包含code、message、data三个字段。code为200表示成功400表示业务错误401表示未登录或token过期500表示服务异常。前端axios拦截器里直接判断response.data.code如果是401就清除本地用户信息并跳转登录页。3.2 登录认证与拦截器登录接口的逻辑不复杂先按用户名查用户再用BCryptPasswordEncoder校验密码最后生成JWT返回给前端。JWT的生成代码大致如下String token Jwts.builder() .setSubject(user.getId().toString()) .claim(username, user.getUsername()) .claim(role, user.getRole()) .setExpiration(new Date(System.currentTimeMillis() 7200000)) .signWith(SignatureAlgorithm.HS256, secretKey) .compact();拦截器的核心作用是从请求头Authorization中取出token并校验如果校验失败就抛出RuntimeException然后由全局异常处理器统一捕获。放行的URL列表包括login、register、车辆查询列表等无需登录的接口其余接口全部要过Token校验。这里有个小坑如果前端请求时没有把token加到header里后端拦截器会拦截所有请求导致404或401所以前端封装axios时一定要在请求拦截器里统一加上Authorization字段。3.3 车辆与订单核心业务逻辑车辆管理的核心接口是分页查询、新增车辆、上下架和状态变更。分页查询我使用了MyBatis-Plus的分页插件关键配置如下PaginationInnerInterceptor paginationInterceptor new PaginationInnerInterceptor(DbType.MYSQL); paginationInterceptor.setMaxLimit(50L);新增车辆时车牌号要做唯一性校验图片上传用MultipartFile接收然后存储到本地指定目录数据库里保存访问路径。这里要说一下开发阶段图片通常存到项目static/upload目录下但部署到服务器后如果用了打包成Jar的方式再访问static目录就会麻烦不少因为jar内部的资源路径不是常规文件路径。更建议把图片存到服务器某个固定目录比如/home/app/upload然后配置一个虚拟路径映射让前端可以通过/upload/**访问。订单业务是最容易出错的地方。用户提交订单时第一步要检查车辆当前是否可租这里不仅要看status是否为0还要检查该车辆在用户选择的日期区间内有没有时间冲突的订单。我加了一个“日期区间重叠查询”方法查询所有未取消的订单条件为取车时间小于等于用户还车时间且还车时间大于等于用户取车时间如果查出来有记录就拒绝下单。这个方法看起来很笨但准确性很高避免了只有状态判断导致的车被重复预订问题。车辆状态变化我用了一个简单的状态机方法所有状态迁移统一在OrderService里完成用户下单成功后车辆状态从0变为1已预订管理员审核通过后车辆状态从1变为2已取车/使用中用户还车后车辆状态从2变为0可租同时更新最后还车时间如果订单取消或审核不通过车辆状态恢复为0这样做的好处是状态迁移路径清晰不会出现“车辆还是已预订状态但订单已经取消了”的脏数据问题。状态修改后要同步更新车辆表这一步必须在同一个事务中完成否则一旦中途报错就会出现订单和车辆状态不一致。3.4 费用计算与订单状态流转租金计算是租车系统里最需要仔细处理的点。我的计算规则是总金额等于车辆每日租金乘以租用天数租用天数按自然日计算取车也算一天。比如用户取车是7月1日还车是7月3日实际计费天数就是3天。这里要注意Date类型的比较如果直接用timestamp相减再除以一天的毫秒数会因为时区问题出现一天的误差。我的做法是对LocalDateTime类型的日期先转成LocalDate然后通过ChronoUnit.DAYS.between计算天数差规避时区影响。订单状态流转我设计了五档状态0待审核、1已确认/待取车、2使用中、3已完成、4已取消。前端页面根据状态显示不同操作按钮比如“待审核”状态下用户可以取消订单“已确认”状态下用户不能直接取消必须联系管理员。管理员在“使用中”状态确认还车后订单直接跳到“已完成”同时费用在这里最终确定。如果中间有超时还车我在还车接口里做了一次额外费用计算超出部分的单价按1.5倍计算这个逻辑也可以在后期扩展成催缴功能。4. 前端Vue核心实现4.1 项目初始化与环境配置Vue项目初始化后一定要先处理两件事安装依赖和配置代理。npm install比较慢时建议设置国内镜像源但我不建议全局覆盖registry而是用.npmrc文件单独配置。代理配置放在了vue.config.js里开发环境中前端请求统一走 /api 前缀然后代理到后端地址这样可以避开CORS跨域问题devServer: { proxy: { /api: { target: http://localhost:8080, changeOrigin: true, pathRewrite: { ^/api: } } } }这个代理配置还能帮你调试时免去在后端写CorsConfig的麻烦。不过需要注意的是部署到生产环境后代理就不生效了要么用Nginx做反向代理要么前端直接把baseURL改为后端能够跨域访问的完整地址。两种方案我调研后最终选择了Nginx统一代理静态资源和后端接口省心很多。4.2 路由设计与权限控制路由设计上我采用静态路由加动态路由的结合。静态路由只包含login、register、home、404其他业务页全部走动态注册。用户登录后后端返回一个roles字段和一个菜单树结构前端根据菜单树生成对应的路由对象再调用router.addRoute()添加。动态路由的实现难度不高但有个坑页面刷新后动态路由就没了因为Vue实例会重新加载localStorage里的菜单树如果没有同步恢复会导致刷新后页面空白。我的解决方法是在main.js入口或App.vue创建前先读取localStorage中保存的menuData如果能读到就恢复路由再挂载应用。这个过程虽然有点“土”但实测下来很稳。Vue Router还涉及导航守卫。我写了全局前置守卫逻辑是如果目标路由是业务页面且未登录跳转登录页如果已登录且访问登录页则跳转首页。这里要注意在next()前把每个页面的标题处理好不然浏览器标签页永远不会变。4.3 核心页面与组件拆分用户端首页我拆成了顶部导航栏、车辆列表、筛选栏、分页四个组件。车辆列表用el-card展示每张卡片包含车辆图片、车型、日租金、状态标签点击“立即预订”后跳转到车辆详情页。详情页除了展示信息还需要一个日期选择器用于取还车时间选择并实时计算租金。这里有一个交互小细节日期选择器要禁用过去的日期且选择还车日期时自动判断是否早于取车日期这些逻辑全部做成计算属性避免在模板里堆复杂判断。管理员端我使用了经典的侧边栏布局左侧菜单从动态权限列表生成右侧内容区域放路由出口。组件复用方面我写了通用的分页组件和状态标签组件。比如状态标签组件根据传入的状态值自动决定显示什么背景色和文字用户端订单状态与管理员端共用这个小组件帮我省了不少重复代码。4.4 状态管理与接口封装状态管理虽然没上Vuex但我把用户信息、token、车辆筛选条件放在了一个全局store里。简单场景直接使用Vue提供的reactive对象加export就可以类似下面这样import { reactive } from vue export const store reactive({ userInfo: null, token: localStorage.getItem(token) || })接口封装是前端高效开发的关键。我把所有axios请求按业务模块拆分文件比如user.js、car.js、order.js每个文件里的方法都返回Promise。后面页面只需要import对应方法不需要关心URL和header。axios拦截器里统一处理loading状态和错误弹窗这是我强烈建议的否则每个请求都要写一遍错误提示代码会非常冗余。5. 联调部署与常见坑5.1 前后端联调的雷区联调阶段我遇到的第一个问题是日期格式不一致。后端返回LocalDateTime默认是类似“2025-06-15T10:30:00”的格式而前端Element UI的日期选择器需要的是“2025-06-15”。如果直接绑定会显示NAN。我在后端统一加了Jackson配置将LocalDateTime序列化格式改为“yyyy-MM-dd HH:mm:ss”同时前端也定义了一个dateFormat过滤器双保险处理。第二个问题是跨域。开发阶段通过devServer代理能绕过去但生产环境一旦前后端分开部署必须在后端配置CorsConfig。配置时记住allowedOrigin不要用“*”因为带Cookie的请求不允许使用通配符建议把前端域名写进去。如果使用了JWT无状态认证跨域配置相对宽松一点但还是要小心预检请求OPTIONS拦截器要对OPTIONS请求直接放行。第三个大坑是时间字段在前端格式化后又出现偏移。这个问题困扰了我一整天原因是Jackson默认序列化时会把LocalDateTime按UTC时区输出而前端取到后按本地时区解析导致时间差了8小时。解决方案是配置统一的时间格式化以及时区为GMT8前后端都按北京时间来处理。5.2 打包部署与SpringBoot集成部署方式我尝试过两种一种是前后端完全分离部署前端打包后的dist目录由Nginx托管后端打jar包跑在Java进程上。另一种是把前端打包后放进SpringBoot的static目录里让SpringBoot统一提供页面和接口。第二种方案特别适合学生毕设部署或者内网项目因为只需要一个Java进程不用单独安装Nginx。实现方式很简单先执行npm run build然后把dist目录下的所有文件复制到SpringBoot项目的src/main/resources/static目录下重新打包jar即可。要注意的是dist目录下的index.html引用的JS、CSS路径需要用相对路径否则在SpringBoot里访问会因路径前缀导致404。同时Vue Router要使用hash模式而不是history模式因为history模式在SpringBoot后端没有配置View controller时刷新页面会直接404。实际配置中我加了一个简单的WebMvcConfig把前端无法匹配的路由转发到index.html配置如下registry.addViewController(/{path:[^\\.]*}).setViewName(forward:/index.html);这个配置可以避免刷新后白屏的问题。不过要注意如果接口路径也匹配到这个规则会被错误转发到index.html所以SpringBoot的Controller优先级更高实际测试中接口会被正常处理因为这个ViewController匹配的是视图控制器层面的路径和RestController的接口映射不冲突。5.3 常见问题速查表这里把我实际开发中遇到的高频问题和解决方案整理成一张速查表方便大家抄作业。问题现象原因解决办法前端请求接口返回404代理没生效或路径错误检查vue.config.js中的pathRewrite和target请求路径是否带 /api 前缀提交订单后车辆状态不变事务没生效或状态更新逻辑写错检查ServiceImpl上是否加了Transactional打印SQL日志定位更新语句用户订单列表为空查询条件拼错通常是多表join时字段名不对用MyBatis-Plus的LambdaQueryWrapper拼条件注意是实体字段名而非列名刷新页面后路由404Vue Router用了history模式改为hash模式或在后端配置forward到index.html图片上传后访问不到虚拟路径映射未配置在WebMvcConfig中添加addResourceHandlers映射本地目录密码明文存储安全问题改用BCryptPasswordEncoder登录时校验加密结果日期参数绑定失败JSON格式与后端LocalDateTime格式不匹配后端配置Jackson的LocalDateTime序列化格式前端统一提交字符串跨域请求被拦截后端未配置CORS添加CorsConfigallowedOrigin写前端实际地址5.4 一点额外的经验如果你准备把这类系统当毕设交建议在答辩时重点讲两个点一是订单日期冲突检测的逻辑二是动态路由权限控制。这两块是很多类似项目里“设计得比较浅”的地方你只要把代码讲清楚老师一般都会认可。另外日志打印一定不要省尤其是订单操作、状态变更这类关键流程至少要打印出参数和结果这样后期排错会容易很多。我在实际开发中还发现车辆列表的缓存问题很隐蔽。用户端下完订单后回到列表页车辆状态可能还是旧数据。这个问题的根源是车辆列表接口做了简单的Redis缓存但订单状态变化后没有主动清理缓存。我的做法是当订单状态变化时直接调用缓存删除方法清空对应车辆详情和列表缓存。这一块代码量不大但能避免很多因为缓存宕出导致的状态不一致。6. 后续可以做的扩展整个系统跑通之后有几个方向很值得扩展。租车公司往往需要统计报表功能可以在后端基于订单表做聚合查询比如按门店、按月统计订单量和收入前端用ECharts画柱状图和折线图。还有消息通知功能订单审核通过后给用户发短信或邮件这里可以使用SpringBoot整合WebSocket实现站内信或者对接第三方短信服务。另一个必要的扩展是限流和操作日志审计。虽然毕设项目不需要很高的并发但接口限流能体现你对生产环境的理解。我之前用拦截器加了一个简单的接口访问计数按IP每分钟限制请求次数超过就返回提示。管理员的删改操作写入操作日志表查询时按时间倒序展示这样哪怕系统被误操作了也有追溯依据。最后文件存储方面如果你的项目要处理大量车辆图片本地目录存储不是长久之计。可以把图片转到对象存储服务或者MinIO这类私有化部署方案里前端通过临时URL访问。这个改动不涉及核心业务表结构主要是文件上传和访问路径的适配在系统稳定后可以随时替换。我个人在实际操作中的体会是租车系统这类“业务感很强”的小项目真正拉开差距的往往不是某个炫酷的功能而是订单状态是否闭环、金额计算是否严谨、刷新页面是否白屏这些细节。把这些细节一个一个磨平你不仅能把项目按时交付还会积累很多在书本上很难学到的工程经验。

关于恒美微站

恒美微站专注于为个体商户、工作室提供极简自助建站服务,让每个人都能轻松拥有专业网站。

快速链接

  • 关于我们
  • 建站服务
  • 主题模板
  • 案例展示
  • 资讯中心

服务项目

  • 可视化建站
  • 拖拽编辑
  • 主题定制
  • SEO 优化
  • 网站托管

联系方式

  • 📍 地址:北京市朝阳区建国路 88 号
  • 📞 电话:400-888-8888
  • ✉️ 邮箱:info@hmyw.cn
  • 🕐 时间:周一至周日 9:00-18:00

© 2024 恒美微站 hmyw.cn 版权所有 | 京 ICP 备 12345678 号