做一个二手车交易系统听上去像是个老掉牙的练手项目但真把它拆开来看你会发现它几乎把一个商业项目该有的技术问题都覆盖了一遍。基于SpringBootVue的二手车交易管理系统源码配上MyBatis和MySQL这套组合不是什么花哨新框架但胜在稳、熟、好招人、好落地。这个项目做的是什么简单说就是给二手车交易场景做一套前后端分离的管理系统后台管车辆、管订单、管用户、管审核前端面向管理员做信息维护和交易流程跟踪。适合谁刚准备找工作的应届生、想转型Java全栈的开发、或者是接私活想快速交付的小团队拿来改改就能用。我基于这个标题从业务场景、数据库设计、后端接口、前端页面、部署调试五个层面把它完整拆一遍。这篇不是源码逐行注释而是讲清楚这个项目“为什么这么做”以及你拿到手之后怎么改、怎么避坑。1. 二手车交易系统的业务逻辑拆解很多人一上来就建表写接口结果做着做着发现流程根本对不上。二手车交易系统的核心不是“卖车”而是“撮合风控履约”。卖家挂车、买家看车、平台审核、线上预约、线下成交、费用结算、过户状态跟踪整个链路里每一环都有状态流转漏掉任何一环这个系统就只能算个展示网站离“交易系统”还差得远。1.1 角色权限矩阵先理清楚这套系统至少要有四类角色平台管理员、车源发布者可以是商家或个人、买家/访客、财务/审核人员。不同角色看到的菜单和操作权限完全不同这是管理系统的地基。管理员用户管理、车辆审核、订单仲裁、数据统计、系统配置车商/卖家车辆发布、车辆上下架、报价管理、预约看车处理、成交确认买家浏览车辆、收藏对比、提交预约、在线询价、查看成交记录财务订单费用核算、佣金提取记录、发票状态管理在设计表结构之前先把角色权限的矩阵画出来后面做Spring Security或者Shiro权限控制时直接按角色分配接口访问权就行。如果项目源码里没有权限模块那第一件事就是补上这个否则整个系统的业务闭环是不成立的。1.2 车辆生命周期状态机车辆是整个系统的核心对象它的状态不能只靠一个字段存最好用状态机来约束流转草稿 → 待审核 → 已上架 → 已预约 → 谈判中 → 已成交 ↓ ↓ 审核驳回 已下架每个状态变更都要记录操作日志尤其是“审核驳回”和“已成交”后台上要有明确的流转记录。表里建议加一个vehicle_status_history表存历史状态快照。这样买家提交投诉或者财务对账时数据有据可查。状态机这件事看着简单实际开发中如果只用一个查询条件来控制页面显示很容易出现“车已经卖了但首页还在展示”这种低级事故。1.3 交易与订单的核心流程一辆车从展示到成交中间要经过询价、预约看车、线下谈判、签订合同、过户等环节。系统里对应的表设计我建议分三张order_info主订单表记录买卖双方、车辆、成交价格、状态order_process流程实例表记录每一步处理结果和时间transaction_record资金流水表记录定金、尾款、佣金、退款这里有个关键点订单表要对“车辆快照”做冗余存储。因为车辆信息是会变的里程数、车况描述、价格都需要留存历史版本。直接关联车辆表会导致成交订单里看不到当时买的车是什么状态。实践里常用做法是在订单表里加vehicle_json或者vehicle_snapshot字段存下单时的车辆核心信息快照。2. 核心技术选型为什么是SpringBootVueMyBatisMySQL这个项目标题里的技术栈组合是很多中小型管理系统的标配。但标配归标配每一步选型都是有逻辑的不是为了拼凑简历关键词。2.1 SpringBoot解决什么问题SpringBoot在这套系统里承担的是“快速构建可独立运行的RESTful服务”。二手车交易管理系统的业务量级单机部署完全能扛住SpringBoot内嵌Tomcat打jar包直接跑运维成本极低。它最核心的价值在于自动配置能力和生态整合能力。我见过有人用Spring Cloud微服务去拆这个项目拆了十几个服务最后一台服务器跑得气喘吁吁。其实在项目初期单体应用反而是最好的架构。SpringBoot的模块化能力允许你把controller、service、mapper包结构分得足够清晰将来真有需要拆分的点时直接按业务域抽取即可。2.2 MyBatis优势在于SQL控粒度为什么选MyBatis而不是Spring Data JPA二手车交易的查询场景非常复杂组合条件多价格区间、里程范围、车龄、排放标准、变速箱类型、车源地区几套条件任意组合。MyBatis可以把动态SQL完全掌控在自己手里if标签组合条件清晰可调慢查询优化时直接拿SQL去explain。另外MyBatis的缓存机制也是这个项目里的加分项。一级缓存默认开启同一个SqlSession内相同查询不会重复查库二级缓存可以按namespace维度配置车辆列表这种读多写少的数据缓存收益非常明显。但要注意如果车辆状态频繁变更上下架、价格调整缓存一定要配置对应的刷新策略否则用户看到的价格和实际价格不一致容易引发客诉。2.3 MySQL是关系型数据最稳妥的选择这套系统的数据关系复杂车辆、用户、订单、报价、收藏、留言之间大量join查询MySQL在保证ACID事务的前提下性能和稳定性最均衡。尤其要注意的是选MySQL 5.7还是8.0这是个实际部署时绕不开的决策点。我之前在实操时用的MySQL 5.7.44兼容性最好网上能查到的安装教程也全是针对5.7的。8.0对排序规则和认证插件有调整如果是从旧项目直接迁库可能会踩坑。这几年新建项目我建议用8.0窗口函数、JSON增强都很实用但安装时要额外处理caching_sha2_password导致客户端连接失败的问题。源码里如果用jdbc连接MySQL 8.0需要加?serverTimezoneAsia/ShanghaiuseSSLfalseallowPublicKeyRetrievaltrue。2.4 Vue前端为什么比JSP/Thymeleaf更合适后端返回JSON前端通过Axios调用接口渲染页面前后端完全解耦。Vue的响应式数据绑定让二手车列表的筛选条件联动非常顺畅——选品牌后车型下拉自动刷新、选价格区间后列表即时过滤这些交互用jQuery写会很啰嗦但Vue的双向绑定和计算属性天然合适。这套源码如果用Vue2建议尽量往Vue3迁移。Vue3的组合式APIComposition API对复杂业务逻辑的复用性提升明显比如把“车辆搜索”逻辑抽成一个useVehicleSearch()函数多个页面复用代码整洁度会好很多。3. 数据库设计的核心细节与表结构参考二手车交易系统的数据库设计是整个项目的灵魂。字段设计好不好直接决定后面做报表统计、多条件筛选时痛苦不痛苦。3.1 核心表结构清单我提供一张实际项目中验证过的建表思路可以对照源码看它的表设计是否完整表名核心字段设计要点sys_userid, username, password, role_type, phone, status密码存BCrypt密文role_type存枚举数字vehicle_infoid, title, brand_id, series_id, price, mileage, register_year, emission_standard, status品牌和车系分开缓存表价格用decimal(10,2)必加city_code和on_sale_timevehicle_imageid, vehicle_id, url, sort_order车辆多张图首图用sort_order最小记录vehicle_audit_logid, vehicle_id, operator_id, action, remark, create_time审核动作日志车牌号和车架号脱敏处理order_infoid, order_no, vehicle_id, buyer_id, seller_id, deal_price, status, contract_urlorder_no唯一索引用日期随机数生成user_favoriteid, user_id, vehicle_id, create_time唯一索引(user_id, vehicle_id)防止重复收藏appointmentid, vehicle_id, buyer_id, expect_time, status预约看车状态待确认/已确认/已完成/已取消3.2 字段类型和索引的细节价格字段千万别用float或double会有精度问题。D瓜、里程、佣金都要用decimal。状态字段建议用tinyint存数字预设枚举对应关系比如车辆状态0草稿、1待审核、2已上架、3已下架、4已成交。索引设计是三板斧单条件查询字段建普通索引组合筛选字段建联合索引排序字段建索引。实际踩过坑的地方是status和listed_time要建联合索引因为后台默认列表就是按状态和上下架时间组合查的。不要什么字段都加索引索引过多会拖慢插入速度。3.3 MySQL排序与锁的实践经验列表页最常见的问题就是排序混乱。分页查询时只用order by create_time可能会翻页重复正确做法是order by create_time desc, id desc双字段保证排序唯一性。这是很多入门级源码容易忽略的地方。后台审核人员在审核车辆、生成订单时会遇到并发操作同一辆车的问题。这里必须用MySQL行锁来保证一致性比如审核时执行SELECT * FROM vehicle_info WHERE id #{vehicleId} AND status 1 FOR UPDATE;在REPEATABLE READ隔离级别下这条语句会锁住该行直到事务提交防止审核通过的同时又被下架操作覆盖。注意FOR UPDATE的前提是查询条件里的字段要走索引否则锁的就不是一行而是全表。所以状态条件是常查询字段一定要加索引。4. 后端实现接口设计、权限控制与MyBatis实战后端这块是源码的核心价值所在。拿到代码后不要急着跑起来先把包结构看懂理解每个模块的分工。4.1 包结构与分层规范标准的工程分层是这样的com.example.vehicle ├── config // 配置类跨域、拦截器、MyBatis分页插件 ├── controller // 接口入口只做参数接收和返回封装 ├── service // 业务逻辑事务控制在这里 ├── mapper // MyBatis接口层对应XML文件 ├── entity // 数据库实体类 ├── dto // 前端交互数据对象避免直接暴露entity ├── vo // 视图对象聚合多表结果 └── utils // JWT工具、日期工具、图片上传工具很多源码的问题在于Controller里塞了太多业务逻辑service形同虚设。实际开发时事务必须放在service层查询接口禁止在Controller里直接调用mapper。这个习惯越早建立越好后面项目复杂度上来你就知道好处了。4.2 统一返回结构与异常处理二手车系统前后端联调时最痛苦的就是每个接口返回格式不统一。后端接口返回体必须统一成{ code: 200, message: success, data: {} }对应的Java类public class ResultT { private Integer code; private String message; private T data; }全局异常处理用RestControllerAdvice统一拦截业务异常和系统异常不要把异常堆栈直接抛给前端。这个点虽然基础但直接决定前端联调的效率。4.3 MyBatis动态SQL与分页车辆列表筛选的动态SQL是整个项目里最核心的Mapper之一。XML里典型写法select idpageQuery resultTypecom.example.vehicle.vo.VehiclePageVO select v.id, v.title, v.price, v.mileage, v.register_year, b.brand_name, s.series_name, v.status from vehicle_info v left join brand b on v.brand_id b.id left join series s on v.series_id s.id where if testkeyword ! null and keyword ! and (v.title like concat(%, #{keyword}, %) or v.description like concat(%, #{keyword}, %)) /if if testminPrice ! null and v.price gt; #{minPrice} /if if testmaxPrice ! null and v.price lt; #{maxPrice} /if if teststatus ! null and v.status #{status} /if /where order by v.on_sale_time desc, v.id desc /select分页用MyBatis的分页插件PageHelper一行代码搞定PageHelper.startPage(pageNum, pageSize); ListVehiclePageVO list vehicleMapper.pageQuery(query); PageInfoVehiclePageVO pageInfo new PageInfo(list);这里有个小坑PageHelper的startPage必须紧跟在mapper查询方法前一行中间一旦插入别的查询语句分页参数就会错位。刚上手时这个坑坑了不少人。4.4 SpringBoot自定义自动配置与框架版本有些同学拿到源码后启动报错常见原因就是SpringBoot版本问题。特别提醒这套源码如果是2023年之前的很可能用的SpringBoot 2.x如果你直接用最新2025年的SpringBoot 3.x环境去跑很多配置项已经变了。SpringBoot 2.x用javax.*包3.x用jakarta.*SpringBoot 2.x的配置拦截器在WebMvcConfigurer里3.x依然是它但包路径变了MyBatis官方starter适配SpringBoot 3需要单独检查版本我的建议是不要盲目上最新版本这类学习型源码里SpringBoot 2.7.x依然是最稳的组合。如果非要用SpringBoot 3那src下包名、依赖版本都要大调成本不低。项目里如果涉及自定义自动配置框架本身的自动配置原理要懂——SpringFactoriesLoader加载META-INF/spring.factories文件中的配置类这个机制在工作中排查奇怪问题时很有用。5. 前端实现Vue页面构建与交互细节前端管理系统的开发重心在于列表页、表单页、状态流转操作以及部分需要实时反馈的交互效果。5.1 Vue环境配置与项目初始化这套源码前端如果是Vue2 Element UI建议先把Node环境核对好。Node 16以上能跑Vue2项目Vue3 Vite则建议Node 18。环境配置是第一道坎很多同学卡在这一步。如果源码是Vue3项目用Vite初始化的我建议的命令行流程npm create vitelatest vehicle-web -- --template vue-ts cd vehicle-web npm install npm run dev如果遇到failed to load tsconfig vue/tsconfig/tsconfig.web.json: tsconfig not found这个报错基本就是vue/tsconfig依赖没装好或者版本不匹配执行npm install -D vue/tsconfiglatest重装即可。5.2 路由设计与权限守卫前端路由是整个后台页面的导航骨架。推荐用动态路由方式根据用户角色从后端拿到菜单权限再注册路由。Vue Router的导航守卫是管理登录态和角色跳转的关键router.beforeEach((to, from, next) { const token localStorage.getItem(token); if (!token to.path ! /login) { next(/login); } else { next(); } });最容易被初学者忽略的是这个场景用户已经登录但角色是普通买家他直接通过URL访问/admin/order这时必须在守卫里做meta角色判断否则越权漏洞就出现了。接口层也要做权限校验前端守卫只是体验优化安全还是靠后端。5.3 列表页的搜索联动与插槽使用车辆列表页是前端工作量最大的地方。搜索区要有品牌下拉、车系下拉、价格区间、里程筛选、车辆状态Tab切换。品牌和车系是关联的选中品牌后车系自动刷新这一步用Vue的watch监听品牌值变化再请求车系接口即可。挂载表格中的操作列时Vue的插槽slot非常关键。随便举一个场景车辆列表最后一列是操作按钮每行的按钮根据当前状态动态渲染el-table-column label操作 width240 template #default{ row } el-button v-ifrow.status 1 typesuccess clickhandleAudit(row)审核通过/el-button el-button v-ifrow.status 2 typewarning clickhandleOffline(row)下架/el-button el-button v-ifrow.status 2 typeprimary clickhandleOrder(row)生成订单/el-button /template /el-table-column插槽这个概念搞不懂前端写操作列会非常痛苦。还有车系筛选级联时可能会用到组件插槽比如下拉选项自定义展示车型图片这些都是源码里值得啃的实际用法。5.4 Axios封装与图片、视频的上传预览前端调用后端接口必须统一封装Axios实例核心是拦截器里自动携带token并统一处理后端返回codeapi.interceptors.request.use(config { config.headers[Authorization] Bearer localStorage.getItem(token); return config; }); api.interceptors.response.use(res { if (res.data.code ! 200) { ElMessage.error(res.data.message); return Promise.reject(res.data); } return res.data.data; });车辆图片上传用Element Plus的el-upload组件配合后端文件上传接口即可预览需要处理回显URL和上传响应格式匹配的问题。如果是2025年加载趋势车辆详情页常有视频看车的需求最省事的方案是后端上传后转出m3u8格式前端用视频播放器播m3u8流。Vue里播放m3u8格式常见做法是引入hls.js不需要额外装依赖import Hls from hls.js; function playVideo(videoElement, url) { if (Hls.isSupported()) { const hls new Hls(); hls.loadSource(url); hls.attachMedia(videoElement); } }这块是加分项主要是应对二手车看车场景里的视频化展示需求。6. 部署上线与源码交接的实操经验源码跑通之后才是真正考验部署能力的阶段代码能不能部署到服务器上运行是判断“这套源码你算不算拿到手”的关键标准。6.1 MySQL安装、数据库初始化和时区设置MySQL安装这块我没有踩过特别大的坑。Windows环境直接下载MySQL 8.0的zip包解压管理员权限命令行执行初始化和启动服务或者用MySQL Installer一键安装都能跑起来。关键步骤是安装后给root设置密码并创建项目专用户mysql -uroot -p CREATE DATABASE vehicle_db DEFAULT CHARACTER SET utf8mb4; CREATE USER vehicle% IDENTIFIED BY your_password; GRANT ALL PRIVILEGES ON vehicle_db.* TO vehicle%;这里有一个特别容易踩的坑导入外部SQL文件时如果文件里有DROP TABLE IF EXISTS你手里这份源码如果你直接执行也没问题。但要注意SQL文件里的字符集是不是utf8mb4否则中文会乱码。连接串里一定加上字符集和时间时区参数。MySQL 5.7和8.0安装后默认内存占用差距比较大如果在云服务器上部署1G内存的机器跑MySQL 8.0会比较紧张可以调innodb_buffer_pool_size降低内存占用。6.2 后端打包部署与前端资源发布后端打包标准操作mvn clean package -DskipTests java -jar vehicle-server.jar --spring.profiles.activeprodSpringBoot的application-prod.yml配置项里数据库连接、文件上传路径、图片访问域名都要改成服务器实际环境。常见坑是文件上传路径没配置导致前端上传的车辆图片在生产环境直接404。前端发布则是执行npm run build生成的dist目录用Nginx托管即可。前后端分离后最大的部署坑是跨域开发环境用Vite代理解决生产环境要用Nginx反向代理统一入口server { listen 80; server_name vehicle.example.com; location / { root /usr/share/nginx/html/vehicle-web; index index.html; try_files $uri $uri/ /index.html; } location /api/ { proxy_pass http://127.0.0.1:8080/api/; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } }6.3 把源码发给别人时的标准操作热词里有个“vue项目源码怎么发给别人”处理方式其实就两种。对技术人来说直接把项目压缩包发过去里面必须带README.md写清楚启动步骤、数据库导入脚本、默认账号密码、JDK和MySQL版本要求。或者如果你用的是GitREADME里写清楚clone后要做的事。对非技术的业务方光发源码没用要把dist打包好的前端配上jar包一起用Docker容器方式交付对方一行命令docker-compose up -d就能跑起来。这才是交付出去的完整形态。我之前试过直接把源码扔给业务方对方看一堆目录根本不知道怎么启动最后还是我远程过去部署的。所以交付内容里一定要附带一份环境要求清单注明JDK 8/11/17哪个版本、Maven版本、Node版本、MySQL 5.7还是8.0这些信息比代码本身更容易卡住复活流程。6.4 Docker部署一套SpringBootVue的实践路径如果是在宝塔面板之类的服务器环境做Docker部署流程也不复杂。前端和后端各打一个镜像再用Docker Compose编排成一个内部网络前端通过Nginx转发请求给后端。Dockerfile后端大概是这样FROM openjdk:11-jre-slim WORKDIR /app COPY target/vehicle-server.jar app.jar EXPOSE 8080 ENTRYPOINT [java, -jar, app.jar]Dockerfile前端FROM node:18-alpine as build-stage WORKDIR /app COPY package*.json ./ RUN npm install COPY . . RUN npm run build FROM nginx:alpine COPY --frombuild-stage /app/dist /usr/share/nginx/html COPY nginx.conf /etc/nginx/conf.d/default.conf核心点是前端镜像多阶段构建先构建再打Nginx镜像。部署的时候记得把MySQL数据目录挂载到宿主机否则容器一删数据全没。7. 常见问题排查实录与避坑技巧源码跑起来的过程中大部分时间都花在解决环境和框架兼容问题上。我把实际遇到过的问题按出现频率排个序照着查能省很多事。7.1 接口报401/403排查接口返回401的时候95%的情况是前端没带token或者后端JWT解析密钥不一致再或者是token过期了。排查步骤很简单打开浏览器开发者工具看Network请求头里有没有Authorization字段没有就是前端拦截器问题有但还401那就是后端JWT工具类里设置的secret和拦截器里用的不一致。这种问题我建议别急debug先打印一段token手动解析。JWT过期这个问题尤其恶心调试时时间稍长就过期一定要把工具类里的过期时间临时调成24小时再联调。7.2 MyBatis缓存引发的数据不一致二级缓存一旦开启车辆上下架后列表还是旧数据这就是缓存没刷新的典型场景。我在做后台审核功能时踩过审核通过一辆车前台列表应立即能看到但因为二级缓存配置在namespace上审核接口执行的是update语句缓存默认只刷当前Mapper的操作。解决方案是保证所有涉及车辆状态的变更都在VehicleMapper里执行这样更新操作会自动刷新该命名空间缓存。如果业务代码里绕过Mapper直接改库缓存就失效了。真要小心这种隐蔽数据不一致宁可禁用二级缓存也别在数据一致性要求高的业务上硬上缓存。7.3 MySQL锁等待超时怎么办高并发下多个事务同时更新同一辆车的状态就容易报Lock wait timeout exceeded。首先要确认死锁的两条SQL及其事务边界常见的解法是更新操作集中在同一事务内顺序固定先查后更减少事务时间不要在事务里做远程调用或复杂计算检查是否缺少索引导致锁全表实际业务中我习惯在代码里对“车辆状态更新”这种热点操作做层同步控制比如分布式锁或Redis锁不纯粹依赖数据库锁。但做这种操作前一定确认你的场景是否真的需要不然又是过度设计。7.4 SpringBoot版本太高引发的启动失败热词里有“springboot版本太高”确实这套基于SpringBoot的源码新手最容易遇到的启动失败就是版本冲突。排查逻辑是看启动类前面的spring-boot-starter-parent版本号2.x到3.x之间javax到jakarta的包名变更会让老源码直接编译失败MySQL驱动版本不匹配会报Unknown database information_schema或者其他乱码错误。别盲目升级看源码的依赖锁定版本或者直接降级到一个稳定版本。7.5 前端联调接口跨域报错本地开发时前端地址是http://localhost:5173后端是http://localhost:8080浏览器直接请求存在跨域问题。后端加一个跨域配置类Configuration public class CorsConfig implements WebMvcConfigurer { Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping(/api/**) .allowedOrigins(http://localhost:5173) .allowedMethods(GET, POST, PUT, DELETE, OPTIONS) .allowedHeaders(*); } }开发环境也可以直接用Vite的proxy解决但注意生产环境Nginx反代同样要处理/api/前缀跳转。这俩只要选一个稳定策略就行别前后端混着来交叉使用容易出双重跨域问题。8. 这套源码后续还能怎么扩展源码的价值在于你能让它跑起来然后在上面做业务迭代。二手车交易系统的扩展方向比你想得到的要多得多。8.1 引入数据同步与实时分析交易系统的日常运营数据比如用户访问行为、车辆浏览量、价格变动趋势这些数据如果只存在MySQL里统计复杂查询会很吃力也不利于后续分析。可以在SpringBoot里集成定时任务把交易数据同步到一些列式存储再配合任务调度框架做周期性统计报表。真要到了做用户偏好分析、价格预测的阶段再把实时计算框架引入比如SpringBoot整合Flink做点击流的实时聚合这是大型二手车平台的标准演进路线。用SpringBoot整合Flink的思路其实不难SpringBoot负责提供配置管理和数据采集入口Flink作为实时计算引擎消费消息中间件里的行为数据计算结果再回写到MySQL或同步到ES里提供全文搜索。这些扩展说起来是架构升级但起点都是在现有SpringBoot项目里逐步加模块实现的。8.2 增加搜索模块与数据同步二手车最核心的需求是找车搜索。MySQL的like %keyword%在数据量小的时候没问题但车源上千条后就会卡顿。部署一套ES索引MySQL里车辆数据变更时通过消息中间件异步同步到ES搜索接口走ES查询这是最经典的技术演进路线。初期不需要自己维护ES集群厂商托管的云ES够用。8.3 引入智能推荐与价格评估如果你想把项目拿到二手车真实业务场景里用车辆估值是一个很有卖点的模块。可以基于历史成交数据训练一个简单估价模型接口传入里程数、车龄、品牌型号、维保记录返回估值区间。实现起来没有想象中那么难从历史成交量大的品牌车型里抽关键特征再做个回归预估效果就能初步体现。9. 写在最后的一点经验这套源码看完、跑通、改过之后你会得到一个很直接的经验积累完整技术栈的运转流程是怎样的。SpringBootVueMyBatisMySQL这套组合在真实行业的覆盖率很高熟练这套技术栈后找工作或者接项目基本盘是很稳的。你拿到源码之后我建议做的第一件事不是跑起来而是先看数据库设计再把业务状态流转理清楚。状态流转理清楚了前后端代码看着就有目的性了。跑通之后自己动手改两个小需求比如给车源列表新增一个“只看新能源”的筛选项后端加一个参数前端加一个按钮把链路完整走一遍这个项目才算真正长在你身上了。另外一个实际经验是源码版本管理一定要用Git哪怕是你自己一个人开发也要用。每次改代码前先commit一下改挂了还能回滚。我自己曾经在给二手车系统加在线签约功能时把原本能正常跑的状态字段改错了忘记commit愣是花了一个晚上才把之前的逻辑还原回来。从那以后任何改动前都会习惯性先提交一版。这个习惯我会推荐给每一个做这套项目的人真的能救你无数次。最后再分享一个小技巧拿到任何一套SpringBootVue源码第一步先去读README编号、第二个去数据库导入脚本、第三个去application.yml/application-prod.yml看端口和数据库配置。三样东西看完这套项目在你心里的地图就已经展开了。