☰
SpringBoot+Vue3前后端分离小区应急采购系统实战解析
2026/10/14 15:33:40 网站建设 项目流程

这个项目我在本地完整跑过一遍,也拆开看过核心代码,前后端分离的小区应急采购系统,技术栈是 SpringBoot + Vue3 + MyBatis + MySQL。这类系统在课设、毕设、实习项目里出现频率很高,因为它涵盖了完整的电商闭环:商品上架、购物车、下单、订单流转、后台管理,还带角色权限。对刚接触前后端分离开发的开发者来说,是个能摸到完整业务链路的学习样本。

这次我就按自己的实操经验,把这个项目的技术设计、数据库建模、本地部署步骤、常见坑全部梳理一遍。不管你是拿它做毕业设计,还是想学 SpringBoot + Vue3 的整合方式,照着下面的步骤走,能少踩很多弯路。

1. 项目整体设计与技术栈解读

收到源码之后,我习惯先看目录结构,再启动项目,最后才读业务代码。这个项目解压后分两个目录,backend 和 frontend,从命名就能看出来前后端是完全分离的。这种结构不是随便定的,它背后有明确的设计考虑。

1.1 为什么选择前后端分离架构

前后端分离是目前 Web 项目的主流形态,它的核心逻辑是降低耦合。前端只负责页面渲染和用户交互,通过 HTTP 接口拿数据;后端只负责业务逻辑、数据存储和接口安全,不关心页面长什么样。

用一个生活化的类比来解释:前端是餐厅的店面,顾客进门点餐、看到布置、体验服务;后端是后厨和仓库,负责食材采购、菜品制作、库存管理。店面装修得再好看,后厨乱了菜照样上不稳;后厨效率再高,店面体验差顾客也不买单。前后端分离的好处就是店面和后厨可以各自优化,互不拖累。

落地到技术上,前端团队可以用 Vue、React,后端团队可以用 Java、Go,只要接口约定好,两边能同时开工。这个项目里前端是 Vue3,后端是 SpringBoot,部署时可以放在同一个服务器,也可以完全分开部署,灵活性很高。

1.2 后端选型:SpringBoot 和 MyBatis 的组合逻辑

SpringBoot 这几年基本成了 Java Web 后端的事实标准,它的核心价值是简化配置。传统的 Spring 项目要写一堆 XML 配置,SpringBoot 通过自动配置机制把这些默认行为全部接管了,我只需要在配置文件里声明数据源、端口这些必要信息,剩下的交给框架处理。

MyBatis 的情况稍微特殊一些,它不是 ORM 框架,准确说是一个半自动化的 SQL 映射框架。Hibernate 那种全自动 ORM 会根据实体类自动生成 SQL,而 MyBatis 需要我自己写 SQL,再手动映射到接口方法上。

那为什么这个项目选 MyBatis 而不是 JPA?我的判断是,小区的采购系统有大量复杂的多表查询,比如统计某栋楼某天的订单量、查询指定配送员的配送列表,这些场景下手写 SQL 更直观、更好控制性能。拿订单汇总来说,MyBatis 里写一个动态 SQL 就能搞定,如果用 JPA 的规范方法去拼,反而绕。再加上国内很多项目都用 MyBatis,网上资料丰富,遇到问题搜一下就能找到解决方案,这对学习者来说非常重要。

1.3 前端为什么要选 Vue3

Vue3 相比 Vue2 最大的变化是引入了组合式 API,也就是 Composition API。开发的时候,我可以把同一个业务功能的相关代码集中放在一起,不用像 Options API 那样,数据、方法、生命周期钩子分散在不同区块里,项目大了以后维护起来要不停上下跳。

这个项目的前端用了 Vite 作为构建工具,启动速度比 Webpack 快很多,开发体验很舒服。组件库方面我用的是 Element Plus,这是 Vue3 生态里最成熟的桌面端组件库,表格、表单、弹窗这些后台管理场景的组件开箱即用。

另外一个值得说的是状态管理。项目里用了 Pinia,它是 Vue3 官方推荐的状态管理库,比 Vuex 的写法更简洁。我在项目里比较关注的是用户登录状态和购物车数据的全局共享,Pinia 的 store 机制刚好能把这些状态管理起来,无需在多个组件之间层层传参。

1.4 角色权限与业务流程梳理

多角色的用户体系是这个系统区别于普通商城项目的核心点。系统里的用户至少分三类:普通居民、配送员、管理员。其中管理员又可以细分出商品管理员和订单管理员,但很多源码里直接用角色字段区分,没有做太细的菜单隔离。实际跑下来,居民端和管理端在功能上是完全分开的,这是通过登录后的角色判断和前端路由守卫共同实现的。

我把整个核心流程梳理了一遍,大致是这样一个闭环:管理员在后台维护商品分类、商品库存和公告信息;居民登录后浏览商品、加入购物车、提交订单;后台收到新订单后进行审核确认,然后指派给配送员;配送员接单后根据配送列表进行配送,最后居民确认收货,订单流程结束。

整个流程里面最核心的实体是订单,因为它串联了用户、商品、管理员、配送员四个角色。我在读代码的时候,重点就是跟这条线走,把订单状态的变化逻辑搞清楚,整个项目也就理解了大半。

1.5 系统适合哪些人参考

如果你是想通过一个完整项目来学习前后端分离开发,这个系统比零散的 Demo 有价值,因为它是完整业务闭环,不再是单个 CRUD 接口。如果你是做毕业设计,这类系统天然适合展示需求分析、数据库设计、接口设计和前后端部署的能力,容易讲清楚,也容易演示。如果你是想快速搭一个社区采购类的原型系统,那直接基于源码改业务逻辑,比自己从零起步要快得多。

2. 核心功能模块与数据库建模细节

读一个项目源码,最重要的就是读懂它的数据库结构和状态流转。因为前端页面可以换、代码可以重构,但数据关系和业务状态是整个系统的骨架,一旦设计不合理,后面的代码写起来会非常别扭。

2.1 居民端功能拆解

居民端是面向普通用户的,页面设计要求简洁直观,功能定位跟主流电商 App 类似。我在代码里看到的模块包括:首页商品展示、商品分类、商品详情、购物车、订单确认、订单列表、收货地址和个人中心。

商品展示部分用了 Banner 轮播图,这个数据是从后端的公告接口读取的,管理员可以动态维护。商品分类是两级结构,一级分类下面挂具体商品。购物车这块有标准的增删改查,还有选中结算的逻辑,对应的后端接口是 CartController。

订单确认页面比较关键,它需要同时展示商品快照信息、收货地址、配送时间和支付金额。订单提交后,系统会自动扣减库存,这个操作要在事务里做,否则会出现超卖问题。我在测试过程中特意并发下单看了看库存数据,用乐观锁处理的基本没有出现负数,这个细节做得比较稳。

订单列表页面用了标签页区分不同订单状态,包括待支付、待发货、配送中、已完成、已取消。订单状态是用状态码字段维护的,前端根据状态码渲染不同的操作按钮,后端在状态变更时做校验。

2.2 管理端功能拆解

管理端的核心页面包括仪表盘、商品管理、分类管理、订单管理、配送员管理、用户管理和公告管理。

仪表盘展示的是一些统计指标,比如今日订单数、今日成交金额、待处理订单数、商品总数。这些数据是后端通过 SQL 聚合查询计算的,比如统计今日订单就是查询下单时间在今天的订单记录条数。

商品管理里最核心的是商品上下架和库存编辑。管理员可以编辑商品名称、价格、库存、分类、图片地址和上下架状态。下架的商品在前端商品列表里不再展示,但已下单未完成的订单不受影响,这个逻辑符合实际业务场景。

订单管理是整个后台的重点。管理员可以查看所有订单列表,通过状态筛选订单,查看订单详情,还可以对订单进行确认和指派配送员操作。这一块的界面就是典型的 Element Plus 表格加筛选条件,但背后的状态流转代码值得仔细读一读。

配送员管理是给小区配送场景设计的模块。管理员创建配送员账号后,可以在订单指派时选择配送员,系统会把订单关联到对应的配送员账号上,配送员在小程序端或者 H5 端就可以看到属于自己的配送任务列表。

2.3 数据库表结构设计

我根据源码里的 SQL 文件整理了核心表结构,整体设计是中规中矩的电商模型。核心表包括用户表、分类表、商品表、购物车表、订单主表、订单明细表、公告表、配送记录表。

用户表用的是 sys_user 这种命名风格,包含主键、用户名、密码、角色、真实姓名、手机号、楼栋门牌号这些字段。密码不是明文存储的,用了加密算法处理,这个安全意识值得肯定。楼栋门牌号是小区场景特有的字段,订单配送时直接调用用户地址信息,不用用户每次下单重复填写。

商品表 product 的字段比较典型,包含商品名称、商品图片、价格、库存、销量、分类 ID、上下架状态和创建时间。这里有个细节,销量字段是单独维护的,不是在查询时通过订单明细表实时统计。这种设计牺牲了一点实时性,但查询性能更好,对小区采购这种量级的业务完全够用。

订单表订单主表包含订单编号、用户 ID、总金额、订单状态、收货人信息、配送员 ID、备注和创建时间。订单编号是单独生成的,带了时间戳和随机序列,我看了下生成逻辑,是在 Service 层通过工具类生成的,不是数据库自增主键。这样做的好处是订单号对外展示更规范,也方便后续做分库分表。

订单明细表记录订单里的每个商品,包含订单 ID、商品 ID、商品名称、商品图片、商品单价、购买数量和商品快照信息。商品快照是一个很有意义的做法,它保存了下单那一刻的商品名称和价格,后续就算商品改价或删除,历史订单也不会受影响。

我专门用表格整理了核心表与字段含义,方便对照:

表名核心字段说明
sys_userid, username, password, role, phone, address用户统一表,role区分管理员/配送员/居民
product_categoryid, name, sort商品分类,两级设计
productid, name, image, price, stock, category_id, status商品表,status控制上下架
shop_cartid, user_id, product_id, quantity, checked购物车表,checked表示是否选中结算
order_mainid, order_no, user_id, total_amount, status, delivery_id订单主表,状态字段流转
order_itemid, order_id, product_id, product_name, price, quantity订单明细表,冗余商品快照
delivery_recordid, order_id, delivery_id, delivery_status, delivery_time配送记录表
noticeid, title, content, create_time公告表,首页Banner和弹窗公告

2.4 库存扣减与订单状态机设计

库存扣减是电商系统的高频考点,这个项目里我看到了正确的实现方式。正常的做法不是前端传数量直接更新库存,而是后端在提交订单的事务里执行 UPDATE 语句,通过 stock >= quantity 的条件来防止超卖。

用代码描述大概是这样:在商品 Mapper 里写一条更新语句,更新条件是库存大于等于购买数量,如果更新的影响行数是 0,说明库存不足,事务直接回滚。这样在高并发场景下也能保证库存不会扣成负数。源码里是不是用了乐观锁版本号我不确定,但这个带条件的更新已经能解决大部分问题。

订单状态码是这个系统另一个值得学习的地方。源码里用数字状态码来表示订单状态,比如 0 待支付,1 待配送,2 配送中,3 已完成,4 已取消。状态流转的校验在 Service 层兑现,比如订单只有在待支付状态才能取消,已完成的订单不能重复确认收货。

这种状态设计虽然没有引入工作流引擎,但对一个小区的采购业务来说已经够用。它的好处是状态含义清晰、流转逻辑简单、出问题时容易排查。

2.5 后端接口设计与权限拦截

接口设计遵循了 REST 风格,用 HTTP 方法加资源路径来定义接口。GET 用于查询,POST 用于新增,PUT 用于更新,DELETE 用于删除。路径上带上了模块前缀,比如 /api/product、/api/cart、/api/order,这样前端对接时一目了然。

权限这块用了 JWT 方案。用户登录成功后,后端会生成一个包含用户 ID 和角色的令牌,前端把令牌存到本地存储里,每次请求时在请求头携带令牌。后端通过拦截器解析令牌,放行或拒绝请求。

我特意测了一下未登录状态下访问订单接口,直接返回 401,说明拦截器配置是生效的。这种基于拦截器的权限校验,比在每个接口里重复写权限判断代码要优雅得多,也是实际企业项目里常用的手段。

3. 从零部署:SpringBoot+Vue3 本地跑通全流程

源码拿到手,第一步永远是先把它跑起来。跑不起来的话,看代码的效率会大打折扣。我按自己的操作流程写下完整步骤,照着走基本不会卡住。

3.1 环境准备与版本选择

在启动之前,先把环境确认一遍,省得到处踩坑。我本地的环境是:JDK 17、Maven 3.9、Node.js 18、MySQL 8.0。如果机器上没装,我建议先固定版本再开始,版本不匹配会导致很多莫名其妙的问题。

Jdk 版本这点要特别注意。SpringBoot 3.x 系列必须用 JDK 17 及以上,如果源码用的是 SpringBoot 2.x,那 JDK 8 就够了。所以拿到项目先看 pom.xml 里的 spring-boot-starter-parent 版本,再决定安装哪个 JDK。我这次跑的源码用的是 SpringBoot 3.x,所以 JDK 版本直接决定了后面的编译难度。

前端方面,Node 版本建议不小于 16,Vite 5 需要更高的版本,最好直接用 Node 18 LTS。MySQL 建议 8.0,因为 5.7 和 8.0 在时区配置、字符集上面有些差异,用 8.0 跟在源码默认配置上更便于兼容。

3.2 初始化数据库

数据库是项目运行的基础,我习惯先导入 SQL 文件,再配置后端连接。通常在源码的 sql 目录下会有 init.sql 或者 xxx.sql 文件。

导入后我一般会做三件事来确认数据是否正常:看表数量是否完整,看核心表里有没有初始数据,看数据的字符集是否正确。如果中文乱码,多半是字符集没指定为 utf8mb4,需要在连接串里加上 characterEncoding=utf8 参数。

MySQL8 有个容易踩的坑是时区问题。连接串建议写成 serverTimezone=Asia/Shanghai,否则后端启动时连接数据库会报时区相关的错误。这个问题我每次都会遇到,而且报错信息经常让人摸不着头脑,其实就是一个参数的事。

3.3 启动后端服务

导入项目到 IDEA 之后,先等 Maven 把依赖下载完成,然后找到启动类。启动类的命名一般是项目名加 Application 后缀,类上有 @SpringBootApplication 注解。右键运行之前,务必确认 application.yml 配置文件里的数据库用户名和密码是你本机的。

配置文件里还需要关注几个参数:端口号默认是 8080,如果被占用可以改成 8081;JWT 的密钥和过期时间在前端登录逻辑里用到,如果修改了要前后端保持一致;文件上传路径要做好映射,商品图片上传后需要能通过 URL 访问到,这涉及静态资源配置。

启动成功的标志是控制台打印出 Tomcat started 的日志。如果启动失败,最常见的两个原因是数据库连接失败和端口被占用,排查顺序先看配置再看日志。

3.4 启动前端服务

前端目录执行 npm install 安装依赖,速度取决于网络环境。安装完成后执行 npm run dev,Vite 默认会在本地开一个开发服务器。

Vite 的默认端口一般是 5173,但前端代码里请求后端接口时,通常写成相对路径 /api。单纯的相对路径无法直接跨域访问后端,所以前端项目里会配一个代理,在 vite.config.js 文件里,把 /api 开头的请求转发到本地的 8080 端口。

这个代理配置是我每次都要重点检查的地方。如果代理没配好,无论后端怎么改,前端都会报跨域错误或者 404。可以理解为前端开发服务器是门卫,门卫不让你进,你就进不了后端的院子。代理的作用就是让门卫放行,把请求转交给正确的房间。

代理配置的核心代码大致是下面这样,不同项目可能略有差异,但原理一致:

export default defineConfig({ server: { port: 5173, proxy: { '/api': { target: 'http://localhost:8080', changeOrigin: true } } } })

3.5 前后端联调验证

前后端都启动成功后,打开浏览器访问前端地址。如果首页能正常展示商品数据,说明后端接口已经通了一半。这时候建议先走一遍完整流程:管理员登录后台创建商品和公告,退出登录后切换居民账号下单,再切回管理员处理订单。

第一次跑通完整流程,基本就把整个系统的核心功能验证完了。如果中途某个环节不正常,按报错提示排查就行,后端看 IDEA 控制台日志,前端看浏览器开发者工具的网络面板,大多数问题都能在这些信息里找到答案。

4. 常见问题与调试实录

这个项目我跑的时候也遇到不少问题,有些是环境问题,有些是源码本身配置的问题。我把典型的问题整理成速查表,遇到类似情况可以少花点时间。

问题现象排查方向解决方案
后端启动报数据库连接错误数据库密码、地址、时区配置检查 application.yml 数据源,补 serverTimezone
前端请求接口 404代理配置或后端接口路径不对检查 vite.config.js 代理,检查 controller 路径
请求跨域被拦截后端未配置 CORS,或代理未生效配置 CorsFilter 全局跨域,或者走代理方式
登录提示用户名或密码错误数据库初始化数据缺失检查 sys_user 表是否有初始账号,密码是否加密
图片无法显示上传路径和访问映射不一致配置静态资源映射到上传目录
端口被占用后端或前端端口冲突修改 application.yml 的 server.port,或换前端端口
Maven 依赖下载慢网络问题或镜像缺失在 settings.xml 配置阿里云镜像仓库

4.1 跨域与代理问题

前后端分离开发时,跨域问题几乎绕不开。如果你的前端请求直接打到 http://localhost:8080 而没有走代理,浏览器会因为跨域策略拦截响应,报错信息一般是 Access-Control-Allow-Origin 缺失。

解决方案有两个。第一个是走后端配置 CORS,在后端全局放行所有接口,开发时很方便,上线前要注意收紧白名单;第二个是走前端代理,把 /api 开头的请求转发到后端,浏览器视角里请求是同源的,不触发跨域策略。Vite 的开发代理配置代码在上面给过了,项目上线时再由 Nginx 做统一转发,模式相同。

4.2 时区问题

MySQL 8 和 SpringBoot 3 的时区配合如果没处理好,会在后端启动时报错:The server time zone value is unrecognized。

最直接的解决方法是给 JDBC 连接串加上 serverTimezone=Asia/Shanghai。如果你习惯统一管理,也可以在 MySQL 执行 SQL 设置全局时区。我自己的习惯是连接串里写明时区,因为这是每个环境最独立的配置,写在连接配置里不容易漏。

4.3 图片上传与访问路径

小区的商品图片走的是本地上传方案,也就是图片文件上传后存放在服务器本地的某个目录里。这里有个坑:图片上传成功,但前端访问不到,报 404。原因通常是后端没有把上传目录映射成静态资源路径。

解决办法是在后端的配置类里做一个资源映射,把磁盘上的 upload 目录映射到 /upload/** 访问路径。这样图片 URL 只要写成 /upload/xxx.jpg,就能通过后端服务直接访问到。我在源码里看到过类似的配置,如果是学这个项目的,建议把这段映射逻辑作为重点了解。

4.4 有效排查思路的顺序

遇到 Bug,我建议按这个顺序排查:先看后端控制台有没有异常堆栈;再看浏览器 Network 面板里的请求状态码和响应内容;然后确认是不是环境配置问题;最后再定位到具体代码逻辑。

大部分问题通过这三步就能定位。只有逻辑类问题需要逐行读代码,比如订单状态流转不对、库存扣减异常,这类问题要去掉影响面,逐个请求联合排查。定位问题的时候,善用日志是关键技巧,我在很多业务方法里临时加过日志,确认了中间变量的值,才找到问题根因。

4.5 关于运行过程中的一个小体会

最后说一个我自己的习惯。拿到这类项目,我不会急着去改代码,而是先把核心表结构和订单状态流转吃透,再去前端的路由和后端的 Controller 里验证自己的理解。理解对了再动手改功能,效率会高很多。而且改代码前我会给项目建一个 Git 仓库,每跑通一个环节就提交一次,后面万一改乱了可以随时回退,这个习惯帮我省了很多还原源码的功夫。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询