
简介这是一套面向Java全栈初学者与课程设计学生的汽车租赁系统实战源码基于SpringBoot后端与Vue.js前端构建完整覆盖用户管理、车辆调度、订单处理等核心业务场景适合作为毕业设计、大作业或SpringBootVue技术栈入门实践项目。资源共150个文件包含57个Java业务逻辑与控制器类、26个JPG与25个PNG格式的界面截图及图标资源、19个XML配置文件含MyBatis映射、15个编译后的class文件以及application.yml、logback-spring.xml等关键配置整体压缩包仅1.18MB轻量易部署。已有146人学习下载代码经导师指导并获98分高分评价所有模块均通过严格调试可直接运行验证功能逻辑。读者可获得结构清晰的前后端分离工程、Shiro权限控制实现含MyRealm、ShiroConfig等、Druid连接池配置、AOP日志切面、以及涵盖Controller/Service/DAO/Entity/Tests的完整分层代码体系。1. 为什么一个「汽车租赁系统」要死磕 SpringBoot Vue 的前后端分离落地你手头刚接了个毕设或外包需求做个汽车租赁系统支持用户选车、下单、支付、还车、评价管理员能管车辆、订单、司机、会员。老板/导师说“用 SpringBoot 和 Vue 做”但没告诉你——真正卡住90%人的不是功能逻辑而是前后端联调时的跨域404、Vue路由刷新白屏、SpringBoot静态资源404、JWT token在axios里漏传、Vue打包后路径错乱导致CSS/JS 404……这些不是bug是架构缝合失败的创口。这个标题里的.zip很关键它不是空泛的“技术栈介绍”而是一个可解压、可运行、可二次开发的最小可行工程包。它代表一种工业级落地范式——后端用 SpringBoot 做 RESTful API含 MyBatis-Plus 操作 MySQL、Redis 缓存订单状态、MinIO 存车辆图片前端用 Vue 3 Pinia Vue Router 实现单页应用SPA二者通过 Nginx 反向代理解耦部署。不是“理论上能跑”而是你unzip后改两行配置就能mvn clean packagenpm run build本地跑通登录、选车、下单全流程。适合三类人✅应届生毕设答辩前一周还在改接口返回格式这个结构能让你把精力聚焦在业务逻辑比如租车超期计费规则、车辆可用性校验而不是被No Access-Control-Allow-Origin header报错拖垮✅转岗前端Vue 路由怎么配才能让/car/detail/123正确加载Pinia 怎么持久化用户登录态这里给你真实项目里的router/index.ts和stores/user.ts✅中小公司后端不想再维护 JSP 或 Thymeleaf 模板SpringBoot 打成 jar 包丢到服务器Vue 打包成静态文件扔进 Nginx运维成本直降70%——本篇就拆解这个压缩包里每个文件的真实作用和必调参数。别被“租赁系统”四个字骗了——它本质是一套可复用的 SaaS 基础骨架用户中心、权限控制RBAC、文件上传MinIO、定时任务Quartz 清理过期订单、日志审计AOP。你替换成“设备租赁”“图书借阅”“会议室预约”改3个实体类5个SQL语句就能复用。现在我们从解压开始一砖一瓦重建这个系统。2. 解压即运行SpringBoot 后端启动的 4 个硬核检查点拿到基于SpringBootVue的汽车租赁系统.zip先别急着npm install。90% 的“跑不起来”问题根子在后端启动阶段就被埋下了。我习惯按以下顺序逐项验证比盲目查日志快3倍2.1 检查 JDK 版本与 SpringBoot 兼容性血泪经验别信 pom.xml 里写的 version打开pom.xml找到parent标签下的spring-boot-starter-parent版本号。常见组合如下注意SpringBoot 3.x 要求 JDK 17而多数老项目仍是 2.7.xparent groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-parent/artifactId version2.7.18/version !-- 这是当前最稳定的 LTS 版本 -- relativePath/ /parent提示如果你本地 JDK 是 8 或 11强行运行 SpringBoot 3.x 会直接报java.lang.IllegalStateException: Unable to load the config class。用java -version确认后要么升级 JDK要么降级 SpringBoot 版本修改version并删掉target/目录重编译。2.2 数据库连接配置application.yml 里这 3 行决定能否连上 MySQL进入src/main/resources/application.yml重点看spring.datasource配置段。不要只改url必须同步校验 driver-class-name 和 username/passwordspring: datasource: url: jdbc:mysql://localhost:3306/car_rental?useUnicodetruecharacterEncodingUTF-8serverTimezoneAsia/Shanghai username: root password: 123456 driver-class-name: com.mysql.cj.jdbc.Driver # 注意MySQL 8 必须用 cj 版本驱动✅url中serverTimezoneAsia/Shanghai是刚需否则时间字段插入时区错乱订单创建时间变成 1970✅driver-class-name必须匹配 MySQL 版本MySQL 5.7 用com.mysql.jdbc.Driver8.0 必须用com.mysql.cj.jdbc.Driver✅username/password别照抄root/123456—— 本地 MySQL 如果改过密码这里必须同步更新否则启动时抛Access denied for user。2.3 MyBatis-Plus 自动建表启动前手动执行 SQL 初始化数据库SpringBoot 默认不会自动建库建表除非你开了spring.sql.init.modealways但生产环境严禁这么干。这个压缩包通常附带sql/car_rental.sql文件内容类似CREATE DATABASE IF NOT EXISTS car_rental CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; USE car_rental; CREATE TABLE car_info ( id bigint NOT NULL AUTO_INCREMENT, brand varchar(50) NOT NULL COMMENT 品牌, model varchar(100) NOT NULL COMMENT 车型, license_plate varchar(20) NOT NULL COMMENT 车牌号, status tinyint NOT NULL DEFAULT 1 COMMENT 状态1-可用0-维修中, PRIMARY KEY (id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;操作步骤在 MySQL 客户端如 Navicat 或命令行新建数据库car_rental执行car_rental.sql全部语句启动 SpringBoot 时观察控制台日志若看到Mapped Statements列出CarInfoMapper.selectList等方法说明 MyBatis-Plus 已成功扫描到 Mapper 接口。2.4 Redis 与 MinIO 配置两个“可选但强烈建议启用”的服务虽然系统能无 Redis/MinIO 启动但车辆图片上传、订单缓存、登录态校验会直接失效。检查application.yml中这两段# Redis 配置用于存储 JWT token 和热点数据 spring: redis: host: localhost port: 6379 password: database: 0 # MinIO 配置用于存储车辆图片、合同PDF minio: endpoint: http://localhost:9000 access-key: minioadmin secret-key: minioadmin bucket: car-images✅ 启动 MinIO下载 MinIO Server 后执行minio server ./data浏览器访问http://localhost:9000用minioadmin/minioadmin登录手动创建car-imagesBucket✅ Redis若未安装用 Docker 一行启动docker run -d --name redis -p 6379:6379 -d redis:7-alpine✅关键验证启动 SpringBoot 后访问http://localhost:8080/api/v1/car/list若返回 JSON 数据且含carImages字段如imageUrl: http://localhost:9000/car-images/abc123.jpg说明 MinIO 集成成功。3. Vue 前端启动从npm install到首页渲染的 5 个致命细节后端跑通只是第一步。Vue 项目常因环境差异导致npm run serve卡在Compiling...或白屏。我们按真实调试路径拆解3.1 Node.js 版本锁定Vue 3 要求 ≥16.13.0但别用最新版执行node -v确认版本 ≥16.13.0。强烈建议用 nvm 管理多版本避免全局污染# macOS/Linux curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash source ~/.bashrc nvm install 16.20.2 nvm use 16.20.2为什么不用 18.x 或 20.xVue CLI 4.x本项目大概率使用对 Node 18 支持不稳定npm install时可能报ERR_OSSL_PEM_ROUTINE而 Node 16.20.2 是长期支持LTS中最稳的版本兼容所有 Vue 3 生态。3.2vue.config.js解决跨域、静态资源路径、打包输出的三大开关这是 Vue 项目里唯一必须修改的配置文件。打开根目录下的vue.config.js重点关注const path require(path) module.exports { // 1. 开发环境跨域代理解决 /api/* 请求被浏览器拦截 devServer: { proxy: { /api: { target: http://localhost:8080, // SpringBoot 后端地址 changeOrigin: true, pathRewrite: { ^/api: // 把请求路径中的 /api 去掉转发给后端 } } } }, // 2. 静态资源路径解决打包后 CSS/JS 404 publicPath: process.env.NODE_ENV production ? ./ : /, // 3. 输出目录确保与 Nginx 配置一致 outputDir: dist }✅devServer.proxyVue 开发服务器localhost:8081收到/api/v1/car/list请求自动转发到http://localhost:8080/v1/car/list避免在代码里写死http://localhost:8080✅publicPath: ./Vue CLI 3 默认publicPath为/但打包后放到 Nginx 的子目录如http://example.com/rental/时CSS/JS 会请求http://example.com/css/app.xxx.css而非http://example.com/rental/css/app.xxx.css加./强制相对路径✅outputDir: dist和 SpringBoot 的resources/static目录对应见第4章。3.3 Axios 请求拦截器JWT token 自动注入的正确姿势打开src/utils/request.js这是整个前端调用后端 API 的统一入口。核心逻辑是import axios from axios // 创建 axios 实例 const request axios.create({ baseURL: /api, // 与 vue.config.js 中的 proxy 保持一致 timeout: 10000 }) // 请求拦截器自动添加 token request.interceptors.request.use(config { const token localStorage.getItem(token) if (token) { config.headers.Authorization Bearer ${token} // 注意 Bearer 后有空格 } return config }, error Promise.reject(error)) // 响应拦截器统一错误处理 request.interceptors.response.use(response response.data, error { if (error.response?.status 401) { localStorage.removeItem(token) router.push(/login) // 跳转登录页 } return Promise.reject(error) }) export default request避坑点config.headers.Authorization Bearer token中的空格不能少否则 SpringBoot 的JwtAuthenticationFilter会解析失败response.data是关键SpringBoot 返回的是{code: 200, data: {...}, msg: success}前端直接取response.data就能拿到业务数据无需response.data.data401处理必须清 token 并跳转否则用户刷新页面后仍处于“已登录”假象。3.4 Vue Router 路由守卫登录态校验与动态路由加载src/router/index.ts是 SPA 的导航中枢。重点看beforeEach全局守卫router.beforeEach((to, from, next) { const token localStorage.getItem(token) if (to.meta.requiresAuth !token) { next(/login) // 需要登录的页面且无 token跳转登录 } else if (to.path /login token) { next(/dashboard) // 已登录却访问登录页跳转首页 } else { next() // 放行 } })✅to.meta.requiresAuth在路由定义中显式声明例如{ path: /car/list, component: () import(/views/CarList.vue), meta: { requiresAuth: true } }✅动态路由加载车辆详情页/car/detail/:id使用props: true在组件内直接通过props.id获取参数而非this.$route.params.idVue 3 Composition API 写法✅路由懒加载所有component: () import(...)写法确保首屏加载速度Webpack 自动代码分割。3.5 Pinia 状态管理用户信息持久化与响应式更新src/stores/user.ts是登录态的核心import { defineStore } from pinia export const useUserStore defineStore(user, { state: () ({ token: localStorage.getItem(token) || , userInfo: JSON.parse(localStorage.getItem(userInfo) || {}) }), actions: { setToken(token: string) { this.token token localStorage.setItem(token, token) // 持久化到 localStorage }, setUserInfo(userInfo: any) { this.userInfo userInfo localStorage.setItem(userInfo, JSON.stringify(userInfo)) }, clear() { this.token this.userInfo {} localStorage.removeItem(token) localStorage.removeItem(userInfo) } } })为什么用 Pinia 不用 VuexVue 3 官方推荐 PiniaAPI 更简洁无 mutations/types/constants且天然支持 TypeScript。localStorage持久化是刚需——否则页面刷新后用户登出clear()方法在退出登录时必须调用否则 token 仍在本地残留。4. 前后端联调Nginx 反向代理 静态资源部署的黄金配置开发阶段用vue.config.js代理能跑通但上线必须用 Nginx 统一入口。否则会出现Vue 路由刷新 404、SpringBoot 静态资源无法访问、HTTPS 证书无法统一管理。以下是生产环境标准配置4.1 Nginx 配置文件一份搞定反向代理与静态资源托管编辑/etc/nginx/conf.d/car-rental.confLinux或C:\nginx\conf\car-rental.confWindowsupstream backend { server 127.0.0.1:8080; # SpringBoot 应用 } server { listen 80; server_name localhost; # 1. Vue 前端静态资源dist 目录 location / { root /var/www/car-rental/dist; # Linux 路径Windows 改为 C:/nginx/html/dist index index.html; try_files $uri $uri/ /index.html; # 关键解决 Vue Router 刷新 404 } # 2. 后端 API 接口代理/api/* 转发到 SpringBoot location /api/ { proxy_pass http://backend/; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } # 3. MinIO 文件直链/minio/* 直接访问 MinIO location /minio/ { proxy_pass http://localhost:9000/; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } }关键参数解释try_files $uri $uri/ /index.html当请求/car/detail/123时Nginx 先找dist/car/detail/123文件不存在→ 再找dist/car/detail/123/目录不存在→ 最后返回dist/index.html由 Vue Router 解析路由proxy_pass http://backend/末尾的/表示去除路径前缀/api/v1/car/list→http://127.0.0.1:8080/v1/car/listlocation /minio/车辆图片 URL 如http://your-domain.com/minio/car-images/abc.jpg直接穿透到 MinIO不经过 SpringBoot减轻后端压力。4.2 SpringBoot 静态资源路径resources/static与dist的映射关系SpringBoot 默认将src/main/resources/static目录作为静态资源根路径。但Vue 打包后的dist目录需复制到这里才能让 SpringBoot 直接托管备用方案不推荐用于生产# 构建 Vue 项目 cd frontend npm run build # 复制 dist 到 SpringBoot 的 static 目录仅开发测试用 cp -r dist/* ../backend/src/main/resources/static/注意此方式下访问http://localhost:8080/即显示 Vue 首页但存在严重缺陷Vue Router 刷新仍 404SpringBoot 的WebMvcConfigurer未配置addViewControllers无法利用 Nginx 的 gzip 压缩、HTTP/2、负载均衡等能力生产环境必须用 Nginx 分离部署SpringBoot 只暴露 API 端口8080不暴露静态资源。4.3 HTTPS 配置Lets Encrypt 免费证书一键部署生产环境必须启用 HTTPS。用 Certbot 自动获取证书# Ubuntu 安装 certbot sudo apt update sudo apt install certbot python3-certbot-nginx # 获取证书替换 your-domain.com sudo certbot --nginx -d your-domain.com # 自动续期Certbot 已配置 cron sudo certbot renew --dry-run更新 Nginx 配置启用 SSLserver { listen 443 ssl; server_name your-domain.com; ssl_certificate /etc/letsencrypt/live/your-domain.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/your-domain.com/privkey.pem; # 其余 location 配置同上... } # HTTP 强制跳转 HTTPS server { listen 80; server_name your-domain.com; return 301 https://$server_name$request_uri; }安全提醒SpringBoot 的application.yml中server.ssl.key-store等配置必须删除HTTPS 由 Nginx 终止后端只需 HTTP 通信降低 TLS 计算开销。5. 避坑指南SpringBoot Vue 联调的 5 个高频翻车现场注意以下问题均来自真实项目踩坑记录按发生频率排序。每条包含现象、原因、解决方案拒绝“重启试试”。5.1 现象Vue 页面空白控制台报Failed to resolve component: router-view原因Vue Router 版本与 Vue 3 不兼容。压缩包里package.json的vue-router: ^4.0.0是正确版本但若你执行npm install vue-router未指定版本可能装入^3.0.0Vue 2 专用。解决删除node_modules和package-lock.json执行npm install vue-router4检查src/router/index.ts是否使用createRouter而非new Router()。5.2 现象SpringBoot 启动报Caused by: java.lang.ClassNotFoundException: org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration原因SpringBoot 版本与 Spring Cloud 版本不匹配。例如spring-cloud-dependencies:Hoxton.SR12要求 SpringBoot 2.3.x而项目用 2.7.18。解决查pom.xml中spring-cloud.version标签访问 Spring Boot Spring Cloud 版本兼容表 将spring-cloud.version改为2021.0.8对应 SpringBoot 2.7.x执行mvn clean compile。5.3 现象车辆图片上传后MinIO 控制台能看到文件但前端 URL 返回http://localhost:9000/car-images/xxx.jpg无法访问原因MinIO 默认只允许localhost访问且未配置 CORS跨域资源共享。浏览器因同源策略阻止加载。解决启动 MinIO 时添加--console-address :9001参数开放控制台执行以下命令配置 CORS替换your-domain.com为你的域名mc admin config set myminio service web-corsallow-originhttps://your-domain.com,allow-methodsGET,PUT,POST,DELETE,allow-headers* mc admin config save myminio mc admin service restart myminio5.4 现象登录成功后localStorage有 token但后续请求 Header 无Authorization原因Axios 拦截器未生效。常见于main.ts中未正确引入request.js或request.interceptors.request.use被包裹在条件判断中。解决检查main.ts是否有import /utils/request在request.js的interceptors.request.use回调函数第一行加console.log(Request intercepted)打开浏览器开发者工具查看 Console 是否输出该日志若无输出说明拦截器未注册检查request.js是否被其他模块覆盖。5.5 现象Nginx 配置正确但访问http://your-domain.com/api/v1/car/list返回 502 Bad Gateway原因SpringBoot 未监听127.0.0.1:8080而是绑定了0.0.0.0:8080正常但更可能是防火墙阻止了 8080 端口。解决在服务器执行curl http://127.0.0.1:8080/api/v1/car/list确认 SpringBoot 自身可访问若返回数据则检查防火墙sudo ufw statusUbuntu或sudo firewall-cmd --list-portsCentOS开放端口sudo ufw allow 8080或sudo firewall-cmd --permanent --add-port8080/tcp重启防火墙sudo ufw reload或sudo firewall-cmd --reload。6. 进阶技巧用 Swagger Postman 快速验证 API再用 Jest 做前端单元测试光跑通不算结束。真正的工程化交付需要可验证、可回归、可协作的闭环。下面这两个技巧让我在团队交接时少解释3小时6.1 SpringBoot 集成 Swagger自动生成 API 文档并在线调试在pom.xml中添加依赖dependency groupIdio.springfox/groupId artifactIdspringfox-swagger2/artifactId version2.9.2/version /dependency dependency groupIdio.springfox/groupId artifactIdspringfox-swagger-ui/artifactId version2.9.2/version /dependency创建配置类SwaggerConfig.javaConfiguration EnableSwagger2 public class SwaggerConfig { Bean public Docket api() { return new Docket(DocumentationType.SWAGGER_2) .select() .apis(RequestHandlerSelectors.basePackage(com.example.carrental.controller)) .paths(PathSelectors.any()) .build() .apiInfo(apiInfo()); } private ApiInfo apiInfo() { return new ApiInfoBuilder() .title(汽车租赁系统 API 文档) .description(提供车辆、订单、用户相关接口) .version(1.0) .build(); } }启动后访问http://localhost:8080/swagger-ui.html所有 Controller 方法自动生成文档点击Try it out即可发送请求无需 Postman 手动填参数。特别适合给测试同学快速上手。6.2 Vue 组件单元测试用 Jest 验证 CarList.vue 的列表渲染逻辑在src/views/__tests__/CarList.spec.ts中写测试import { mount } from vue/test-utils import CarList from /views/CarList.vue import { createPinia } from pinia describe(CarList.vue, () { it(renders car list correctly, async () { const pinia createPinia() const wrapper mount(CarList, { global: { plugins: [pinia] } }) // 模拟 API 返回数据 const mockCars [ { id: 1, brand: Toyota, model: Camry, license_plate: 粤B12345 } ] wrapper.vm.cars mockCars // 直接赋值 data await wrapper.vm.$nextTick() expect(wrapper.findAll(.car-item).length).toBe(1) expect(wrapper.find(.car-brand).text()).toBe(Toyota) }) })运行测试npm run test:unit。这不是形式主义——当产品经理突然要求“车辆列表加个搜索框”你改完代码后npm test通过即证明原有逻辑未破坏。6.3 生产环境部署 checklist5 个必须确认的项检查项检查方法不通过后果SpringBoot 日志级别为 INFOapplication.yml中logging.level.root: INFODEBUG 级别日志刷爆磁盘Vue 打包开启 gzipvue.config.js中configureWebpack: { plugins: [new CompressionPlugin()] }首屏加载慢 2~3 秒Nginx 开启 gzip 压缩nginx.conf中gzip on; gzip_types text/plain application/json;CSS/JS 体积大 3 倍MinIO 持久化挂载docker run -v /data/minio:/data minio/minio server /data重启容器后图片丢失SpringBoot Actuator 健康检查访问http://localhost:8080/actuator/health返回{status:UP}运维无法监控服务状态最后说句实在话这个.zip项目的价值不在于它实现了多少功能而在于它把 SpringBoot Vue 的协作边界划得足够清晰——后端只管数据和业务规则前端只管交互和体验中间用 RESTful API 和 Nginx 当“翻译官”。你以后做任何系统只要把car_info表换成book_info把rent_order换成borrow_order改 3 个实体类、5 个 SQL、2 个 Vue 页面就能复用整套架构。这才是工程师该追求的复用不是 CtrlC/V。希望帮到你。本文还有配套的精品资源点击获取