news 2026/10/17 3:50:25

前后端分离家具商城实战:SpringBoot+Vue+MySQL全栈开发详解

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
前后端分离家具商城实战:SpringBoot+Vue+MySQL全栈开发详解

前后端分离的在线家具商城,听起来像是个学生项目或者练手作品,但真完整做下来,你会发现它几乎涵盖了Web开发日常要用到的所有核心技能:SpringBoot接口开发、Vue前端交互、MyBatis数据持久化、MySQL表设计,还有一个完整商城该有的用户、商品、购物车、订单、支付(或模拟支付)流程。这篇文章就是来拆这套系统的,从设计思路到核心代码,再一路讲到部署,把能踩的坑也一并列出来。

这套项目形态非常适合两类人:一是刚学完SpringBoot和Vue,想找一个完整全栈项目作为毕设或者简历亮点的开发者;二是已经在做后端或者前端,想补一下另一侧技术栈的全栈手感。照着这套路子走一遍,你至少能梳理清楚一个问题——一个前后端分离的电商系统,从零到上线,究竟要经历哪些环节。

1. 项目整体设计与技术选型思路

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

在做家具商城这类管理系统时,最早期的方案通常是模板引擎渲染,后端把数据塞进页面,前端只负责显示。这种模式在小项目里确实省事,但一旦页面交互变复杂,问题就很明显:前端想调整一个按钮位置,后端工程师要跟着改模板;接口返回的数据结构变动,前端页面就崩。前后端分离则把两者拆开,前端只通过接口拿数据,后端只管业务逻辑和数据库操作,各自独立开发、独立部署。

这套家具商城选择前后端分离还有一个很实际的考虑:商城类项目天然有PC端、管理端、甚至是未来移动端的需求。管理端和商城端虽然业务不同,但可以共用同一套后端接口,只要后端把权限控制做好就够了。如果后面前端想换成小程序,后端接口基本上不用动。

另一个好处是开发和调试的体验。开发阶段前端用Node服务跑Vue,后端用SpringBoot跑在8080端口,通过代理转发解决跨域问题,改前端页面不用重启后端,效率比传统模式高出不少。对这个项目的定位来说(毕设或练手),这种架构也更能体现“系统设计”的完整性和模块化思维。

1.2 技术栈选型的理由

SpringBoot作为后端基础框架,几乎是当前主流的选择。它最大的价值在于自动配置——很多原本需要手动显式配置的内容(数据源、事务、Web容器)都变成了约定,项目启动直接从main方法跑起来,不用再折腾繁琐的XML配置。家具商城这种规模的项目,SpringBoot的效率优势明显。

Vue选择的是Vue 2或Vue 3,两者在这个项目里差异不大。Vue的核心是组件化开发,把首页、商品列表、购物车、订单结算拆成一个个组件,数据通过props和事件或Vuex(如果是Vue 3可以用Pinia)在组件间流动。相比传统jQuery操作DOM的方式,Vue把数据和视图做了双向绑定,页面状态被修改后视图自动更新,省掉了大量手动拼接HTML的逻辑。

MyBatis作为持久层框架,主要是看中它可以直接编写SQL,对于复杂的多表查询(比如家具商品分类、订单明细、库存更新),SQL的可控性比全自动ORM更强。配合逆向工程生成实体类和Mapper接口,CRUD的样板代码量也能降到很低。

MySQL则不用多说,开源稳定、资料多、安装简单。缓存可以用Redis优化,但基础版这个项目不引入Redis也完全跑得通,对新手更友好。

1.3 项目模块划分

这套系统的整体结构可以分为两个端:用户端和管理端。

用户端功能包括:注册登录、浏览家具分类和商品、商品搜索、商品详情查看、加入购物车、购物车管理、订单提交、模拟支付、订单查询、个人信息管理。管理端功能包括:管理员登录、商品分类管理、商品管理(增删改查)、订单管理(发货、状态修改)、用户管理、数据统计看板。

从开发顺序上,一般是先做后端接口,再写前端页面,最后联调。后端的模块可以按权限分为两类:公开接口(注册登录、商品浏览)和鉴权接口(购物车、订单、个人信息),用拦截器统一校验登录状态。

2. 数据库设计与核心模块拆解

2.1 数据表设计

家具商城的核心业务流程不算复杂,但涉及的数据关系需要理清楚。整套系统的表我把它分成三组。

第一组是用户相关:用户表(user)。用户字段一般包括id、用户名、密码、昵称、手机号、邮箱、头像、角色(普通用户/管理员)、创建时间。密码不要明文存储,注册的时候用MD5加盐或BCrypt加密,登录时比对密文。

第二组是商品相关:分类表(category)和商品表(product)。分类表字段是id、名称、父级id、图标、排序。商品表字段包括id、分类id、名称、描述、主图、轮播图、价格、原价、库存、销量、状态(上架/下架)、创建时间。家具商品往往会有多个规格,比如颜色、尺寸、材质,如果要做得全一点,可以再加一个商品规格表,但基础版把规格信息直接拆到商品名称和描述里也能接受。

第三组是交易相关:购物车表(cart)、订单表(orders)、订单项表(order_item)。购物车表字段是id、用户id、商品id、数量、勾选状态。订单表是核心,字段包括id、订单编号、用户id、总金额、实付金额、收货人姓名、收货地址、联系电话、订单状态(待付款/已付款待发货/已发货/已完成/已取消)、创建时间、支付时间。订单项表记录订单中的每个商品快照,字段有id、订单id、商品id、商品快照名称、商品快照图片、商品快照价格、数量。

订单为什么要把商品信息做成快照而不是直接关联商品表?这是个细节,但很关键。商品的价格、名称随时可能被管理员修改,如果订单关联的是最新商品信息,用户下单后的订单记录就可能对不上,比如商家改了价格,用户历史订单里的金额就变了。快照的设计保证了订单交易的确定性。

2.2 数据库建模的注意事项

表设计阶段最容易犯的错就是字段类型和长度选得太随意。价格字段一定不要用float或double,电商场景下用decimal,精度至少decimal(10, 2),否则对账时会遇到浮点数精度问题。库存字段用int,检查库存时要避免出现负数,更新库存的SQL要在条件里加上stock >= 购买数量。

主键建议用自增id,虽然分库分表的时候不太友好,但这个规模的项目自增id最简单可靠。如果图省事用UUID做主键,整张表数据量大之后,B+树索引的随机写入性能会比较差,而且前端拿到id做路由的时候还需要处理字符串参数。

如果要预留扩展能力,可以用逻辑删除字段(deleted)替代物理删除,尤其是商品和订单表。用户下单后,订单数据是不能轻易物理删除的,保留删除标记既能规避这个问题,也方便后期做数据统计。

2.3 权限控制方案

权限用最传统的角色判断:用户表里加一个role字段,0表示普通用户,1表示管理员。后端接口统一使用Spring拦截器(HandlerInterceptor)进行登录校验,拦截器在进入Controller之前执行,从请求头中读取token,校验通过后把用户信息放入ThreadLocal或request attribute中,Controller里直接获取当前用户id。

对于管理员接口,可以在拦截器里额外判断用户角色,也可以单独在Controller层的注解上做控制。基础版项目用拦截器+角色字段就够了,不需要引入Shiro或Spring Security这种重量级框架,理由有两个:

一是学习成本。Spring Security虽然功能强大,但配置复杂,新手经常被它的过滤器链搞得晕头转向。二是项目需求简单,不需要细粒度权限(比如按钮权限、数据权限),一个角色字段足够。如果你后续想升级,再引入Spring Security/JWT也不迟,但起步阶段保持简单很容易。

3. 前后端接口对接与关键功能实现

3.1 后端代码结构

后端包结构我习惯这样组织:

  • config:存放配置类,比如跨域配置、拦截器注册、MyBatis配置
  • controller:接口层,负责接收请求和返回结果
  • service:业务逻辑层,接口+实现类
  • mapper:数据访问层(MyBatis的Mapper接口)
  • entity:数据库实体类
  • dto:前端传入的数据封装对象(比如注册信息、订单提交信息)
  • vo:返回给前端的数据封装对象(比如购物车列表VO、订单详情VO)
  • common:通用类,比如统一返回结果、异常处理、JWT工具类

这样分包的好处是依赖方向清晰:controller依赖service,service依赖mapper,数据模型统一从entity取,避免循环依赖的同时也方便团队协作。

统一返回结果类是接口设计里容易被忽略的环节。我习惯定义一个Result类,包含code、message、data三个字段,code为200表示成功,其他表示异常。所有接口都返回Result对象,前端拿到后根据code判断业务结果,再决定是展示数据还是弹出错误提示。这个类虽然简单,但统一之后,前端的请求封装会极其顺畅。

3.2 登录鉴权与用户身份传递

用户登录后需要一种机制让后端记住“我是谁”。最传统的是Session,但前后端分离项目里,前端域名和后端域名可能不同,Session配合Cookie的跨域处理比较麻烦,而且横向扩展时Session同步也是问题。所以建议直接用JWT(JSON Web Token)。

简单说,用户登录成功后,后端生成一个包含用户id和用户名的token字符串返回给前端。前端把它存在localStorage或Vuex/Pinia里,之后每次请求都在请求头里带上Authorization: token。后端拦截器解析这个Token,验证签名和有效期,解析出用户id放入请求上下文。

实现Token解析时有两个坑需要提前规避。一是在拦截器中解析Token失败的时候,要直接返回401状态码和对应的JSON,让前端能弹出“登录已过期”的提示,而不是继续执行Controller。二是Token密钥要独立写在配置文件中,不要硬编码在代码里,否则代码泄露后Token就可以被伪造。

3.3 商品列表与搜索

商品列表是用户端最重要的入口,需要支持按分类查看、关键字搜索、价格排序、分页显示。核心接口的设计一般是GET /api/product/list,参数包括:categoryId、keyword、page、size、sortField、sortOrder。

这里要注意分页插件还是手写SQL。MyBatis的分页可以用PageHelper,只要在查询前调用PageHelper.startPage(page, size),后面的查询就会自动拼上LIMIT。手写SQL则是用LIMIT #{offset}, #{size},前者方便但不完全透明,后者可控但需要自己算offset。为了学习效果,我建议基础版手写分页,这样能真正理解limit的作用,之后再用PageHelper也毫无障碍。

搜索功能不要一上来就上ElasticSearch,那是过度设计。MySQL的LIKE模糊搜索在这个数据量级完全够用。如果家具商品只有几千条,即使搜索条件加上两个LIKE,查询时间也基本在毫秒级。等数据量真正大了,再考虑全文索引或者搜索引擎也不迟。

3.4 购物车与订单流程

购物车表设计简单,但前端交互细节不少。接口方面要有:加入购物车、修改数量、删除、勾选、获取购物车列表。这里比较重要的是购物车列表返回数据结构,因为前端要展示图片和商品信息,所以连表查询是必须的。建议直接返回CartVO,字段包括购物车id、商品id、商品名称、商品图片、单价、数量、选中状态、商品库存(用于前端提示库存不足)。

购物车合并逻辑容易被忽略。用户没有登录时也可以往购物车加商品,但一旦登录,客户端的临时购物车数据应该能合并到服务端。这个功能如果要做,一般逻辑是:前端把本地购物车数据在登录成功后同步到后端,后端按用户id和商品id合并数量。

订单流程是整套系统的核心链路。提交订单的后端逻辑要用事务保护,大致步骤如下:

  1. 接收前端传来的订单信息(购物车商品列表、收货人、地址、电话)
  2. 根据购物车记录联查商品,确认商品存在且在售
  3. 计算总金额,对比前端传入金额(可选步骤,严谨的话要以后端计算为准)
  4. 检查库存是否充足
  5. 扣除商品库存
  6. 生成订单主表记录,状态设为待付款
  7. 生成订单项表记录,保存商品快照
  8. 清空对应购物车记录
  9. 提交事务,返回订单编号

这些步骤只要一步失败,前面的操作就必须回滚。比如库存扣了但订单生成失败,会导致库存无端减少,这就是必须加@Transactional的原因。在使用Spring事务时,注意一个问题:事务只对RuntimeException起作用,如果你在代码里catch了异常却没往外抛,事务是不会回滚的。

下单后模拟支付,状态从待付款改为待发货。这里可以做一个支付页,也可以直接一个“模拟支付”按钮。支付成功后的核心操作有两个:更新订单状态、累加商品销量。

3.5 管理端功能

管理端是典型的后台CRUD页面,开发者自己用起来比写用户端还顺手。商品管理需要实现:分页查询、新增商品、编辑商品、上架下架、删除(逻辑删除)。分类管理维护的是前端页面的分类导航栏。

订单管理则是后台核心,管理员需要按状态筛选订单,查看订单详情(用户信息、商品明细、总金额),并执行发货操作,发货后订单状态变为已发货,用户端就能看到物流状态。

管理端页面建议单独放在一个路由前缀下,比如/admin,与商城端分开。菜单栏放在左侧,内容区放在右侧,典型的后台管理布局。由于前后端分离,管理端接口必须做权限校验,或者说在拦截器中检查用户角色,非管理员访问管理接口一律返回403。

4. 前端核心实现与交互细节

4.1 项目初始化与路由配置

前端用Vue CLI或Vite初始化项目,技术栈包括Vue、Vue Router、Axios、Element UI(或Element Plus,看Vue版本)。Vue Router需要配置好路由表,页面级组件包括:首页、商品列表页、商品详情页、购物车页、登录页、注册页、个人中心页、订单列表页、订单详情页、结算页、支付结果页、后台管理页面。

路由需要做两件事:一是全局前置守卫,判断访问需要登录的页面时userInfo是否存在,不存在则跳转登录页;二是把后台管理相关的路由统一放在一个懒加载组件里,避免首屏加载过重。

Axios封装也很重要。统一的请求拦截器里给每个请求加上token;响应拦截器里处理统一返回结果,如果code不等于200,则弹出Message提示错误;如果HTTP状态码是401,则清除用户信息并跳转到登录页。这个封装可以省掉每个页面里大量的重复错误处理代码。

4.2 状态管理与购物车同步

Vue全家桶里的状态管理,Vue 2用Vuex,Vue 3用Pinia。购物车数量、用户信息这类会被多个组件共享的数据,应该放进全局状态里管理。比如首页导航栏要显示购物车商品总数,商品详情页加入购物车之后这个数字要立刻变,如果不用全局状态,就得靠事件总线或者刷新页面,很笨拙。

购物车商品数量和购物车详情是两套数据,要注意区分。导航栏的小角标只需要总数,所以可以在加入购物车、修改数量、删除这些操作后,用一个轻量接口重新获取购物车总数并更新到全局状态。完整购物车列表则进购物车页再拉取。

4.3 前端交互细节

商品卡片上的价格显示,建议处理后端返回的以分为单位的价格,或者后端直接返回元为单位的小数,前端用toFixed(2)保证显示两位小数。图片的懒加载可以借助Vue的指令或者Element组件内置属性,家具商城图片多,尤其首页和列表页,不要一次性把几十张高清图片全部加载完。

商品详情页的“立即购买”和“加入购物车”是两个不同的入口,立即购买要直接跳转结算页,但购买的商品数据是临时组装的一份,不能影响购物车原有数据。这里最常见的实现方式是点击立即购买时,前端单独维护一个buyNowItem对象,提交订单时和后端约定只处理这个商品而不是购物车列表。

5. 部署教程与踩坑记录

5.1 本地启动流程

整个项目从下载到运行,顺序是:先启动MySQL导入数据库脚本,再启动后端,最后启动前端。

具体步骤如下:

  1. 安装JDK(建议1.8或更高),配置JAVA_HOME
  2. 安装Maven,配置仓库镜像为国内镜像,加快依赖下载
  3. 安装MySQL,创建数据库,导入项目里的sql文件
  4. 修改后端application.yml中的数据库地址、用户名、密码
  5. 在项目根目录执行mvn spring-boot:run启动后端
  6. 确认8080端口访问后,进入前端目录
  7. 前端安装依赖npm install(或者yarn)
  8. 配置前端代理:开发环境下访问/api路径时,代理转发到http://localhost:8080,这样能绕开跨域问题
  9. 执行npm run dev启动前端开发服务器
  10. 浏览器访问前端地址完成联调

开发环境跨域最简单的方案是配置Vue CLI的devServer.proxy。比如前端运行在8081端口,后端是8080端口,如果不做代理,前端直接请求http://localhost:8080/api/xxx会被浏览器拦截。配了代理之后,前端请求/api/xxx,DevServer帮忙转发到后端,浏览器看到的是同源请求,就没有跨域问题了。

生产环境打包时,前端执行npm run build生成dist静态文件,这些文件一般交给Nginx托管,然后Nginx配置一个/api反向代理到后端服务。这里的关键是Nginx的location配置要同时处理好静态文件路由和前端路由history模式的页面刷新。

配置示例(示意):

server { listen 80; server_name localhost; # 前端静态文件 location / { root /home/www/furniture; 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; } }

try_files这行非常关键,它解决的是Vue Router的history模式在刷新页面时返回404的问题。如果不配置,用户访问商城首页再刷新没问题,但直接刷新/shop/cart这样的路径,Nginx会去找对应的静态文件,找不到就404,加上try_files之后会统一回退到index.html,由前端路由接管。

5.2 后端部署

后端打包执行mvn clean package,生成jar包后直接java -jar xxx.jar运行。如果机器内存吃紧,可以加-Xms256m -Xmx512m限制堆大小。Linux服务器上建议用nohup放在后台运行,日志重定向到文件中方便排查问题。

如果要保证后端异常退出后自动重启,可以写一个systemd服务文件,或者用supervisor管理进程。这个项目阶段选哪个都行,重点是把端口占用、日志路径、进程启停命令搞清楚。

5.3 常见问题速查表

部署和联调阶段最容易踩的坑,我直接整理成了表格,方便你对照排查。

现象可能原因解决方式
后端启动报数据库连接失败MySQL没启动或账号密码不对检查MySQL服务,核对application.yml配置
前端请求接口一直报跨域开发环境没配代理,或后端CORS没配置开发环境配devServer.proxy;生产用Nginx反代
登录之后刷新页面就掉线token只存在内存,没有持久化把token存到localStorage,刷新时重新读
管理员接口返回403用户角色不是管理员或token未携带检查登录账号角色,确认前端请求头带Authorization
前端npm install非常慢或失败npm源是官方源切换为国内npm镜像,或设置代理
订单提交后库存不减少事务未生效或SQL条件写错检查Service方法是否标注@Transactional,检查更新SQL
Maven下载依赖慢仓库源是中央仓库修改settings.xml镜像为阿里云镜像
部署后页面刷新404Nginx没有配置try_files补上try_files $uri $uri/ /index.html;
数据库导入中文乱码数据库或表字符集不是utf8mb4建库时指定utf8mb4,sql文件本身也要是utf8编码
前后端字段对不上,接口返回nullJava实体字段名和前端驼峰不一致统一命名规范,或用@JsonProperty映射

这些坑我基本上每次做全栈项目都会遇到几个,尤其是前端跨域和部署后刷新404,属于“不踩一遍根本想不到”的问题。建议你在联调阶段先把接口用Postman或Apifox全部过一遍,确认接口没问题,再开始绑定页面,这样能省掉一半的排查时间。

5.4 部署安全与配置小建议

部署上线前有几点建议顺手做一下。第一是数据库密码不要使用弱口令,后端配置文件的密码不要写死默认值。第二是后端的跨域配置如果做了全局CORS,生产环境最好只允许实际域名访问,不要用*通配符。第三是管理端接口要确保被拦截器保护,可以单独定义一个拦截路径规则,比如/admin/**必须校验管理员角色。

如果项目只是用在毕设答辩或者简历展示,部署到本地或者一台云服务器就够了,不需要做高可用、负载均衡这些重型方案,那是去生产环境才需要考虑的事情。把重点放在代码能跑、流程完整、能讲清楚设计细节上,面试官和老师更看重这些。

6. 拓展方向与个人实操体会

这套家具商城做完之后,往哪个方向拓展都有很高的性价比。如果想让系统更“值钱”,可以先引入Redis缓存商品详情和分类页,降低数据库压力;然后引入Spring Security或更严格的Token鉴权机制;接着把订单模块接上真实的第三方支付SDK(沙箱环境就可以);再往上可以加上定时任务处理超时未支付订单,用消息队列处理订单创建后的异步通知。这些点每一个单独拿出来,都足够成为简历上的一个亮点。

就我个人实操经验来说,做这套项目最重要的不是把功能敲完,而是要把几个核心链路彻底打通理解透:从用户注册登录到浏览商品,从加购到下单,从下订单到扣库存,从支付到订单状态流转。这条链路只要你能不看代码,完整地向别人讲清楚每一步发生了什么事、为什么这么设计,这个项目的价值就真正体现在你身上了。

最后还是那句老话:项目不怕简单,怕的是做完之后脑子里还是一片空白。找一个自己感兴趣的业务场景(家具就不错),按真实流程去设计表结构、写接口、调页面,遇到问题就查资料修掉,这一步一步走下来比看十个教程都有用。尤其是部署环节,千万不要觉得“能本地跑就行”,真正把jar包和dist文件扔到一台干净服务器上跑通,那种成就感是本地开发完全比不了的。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/17 3:50:24

OpenClaw实战:用AI代理打造多角色协作团队的完整指南

AI代理(Agent)这个词这两年几乎霸占了技术社区的热搜,到了2026年,我觉得最值得关注的变化已经不再是“单个Agent能做什么”,而是“一群Agent怎么像一个团队一样协作”。单跑一个Agent脚本很容易,真正难的是…

作者头像 李华
网站建设 2026/10/17 3:49:46

AI写论文工具全解析:从大纲到审校的四类能力与使用技巧

过去大半年,不断有学弟学妹和同行朋友问我:市面上的AI写论文工具到底哪个靠谱?尤其是这段时间,冒出不少号称“期刊论文一键生成”的产品,价格从几十到几千不等,宣传语一个比一个猛。我陆陆续续试用过不少&a…

作者头像 李华
网站建设 2026/10/17 3:49:05

LLM代理驱动GPU算子优化:从手工调优到自动闭环的范式转换

1. 从"手写汇编"到"代理驱动":算子优化范式正在换挡2026年过半,如果你还在用纯手工的方式去调一个LLM推理场景下的算子kernel,大概率会被团队里的年轻人用一套代理驱动的自动化流程按在地上摩擦。这不是危言耸听&#xf…

作者头像 李华
网站建设 2026/10/17 3:48:43

Figma Make与LLM协同设计的随机对照实验实证

1. 这不是“AI画图”,而是一场产品设计工作流的实证拆解最近在几个设计团队的内部分享会上,我反复被问到一个问题:“你们用Figma Make做原型,到底省了多少时间?”——不是问“好不好用”,而是直接要数字、要…

作者头像 李华
网站建设 2026/10/17 3:48:36

PyTorch逆归一化详解:从原理到工程实践,解决数据尺度还原难题

看到“pytorch中如何实现逆归一化”这个标题,我猜你多半是已经踩到了那个经典场景:训练时数据归一化挺顺利,loss曲线漂亮得很,结果一到推理阶段,模型输出的预测值跟真实数据量纲对不上,画出来的曲线、算出来…

作者头像 李华
网站建设 2026/10/17 3:48:05

MCP Gateway实战:企业AI上下文治理与防串扰设计

1. 从“上下文陷阱”说起:企业AI落地最容易被忽视的暗礁做过企业级AI应用的人,大概率都经历过这样的场景:一个智能客服系统上线初期表现惊艳,回答准确、语气得体,业务方拍手叫好。可运行两三周之后,用户开始…

作者头像 李华