宠物商城平台系统源码:Spring Boot+Vue前后端分离项目实战
2026/9/15 22:15:40 网站建设 项目流程

宠物商城这类的项目,这几年在课程设计、毕业设计和简历项目里出现频率相当高。作为一个完整的全栈练手项目,它能把前端展示、后端接口、数据库设计、权限控制、订单流程这些核心知识点全部串起来,非常适合用来检验自己对 Web 开发整体流程的掌握程度。我这次要分享的是一套宠物商城平台网站系统的完整交付方案,包含全部源码、数据库脚本和配套文档。这套系统我从需求拆分到部署上线完整跑通过一遍,整体采用前后端分离的架构,后端基于 Spring Boot 框架构建 RESTful API,前端使用 Vue 配合 Element UI 实现管理后台与商城页面,数据库选用 MySQL 设计了一套覆盖用户、商品、购物车、订单、评论等核心业务的数据模型。

对正在准备课程设计答辩、毕业设计或者想往系统里加功能丰富简历的同学来说,这套系统的价值在于——它不是一个只有 CRUD 的玩具项目,而是把真实商城系统的关键链路做了完整落地。从用户注册登录、商品浏览搜索、购物车管理,到订单提交、支付模拟、后台商品上下架、订单状态跟踪,每一步都有对应的表结构和接口设计。

这套方案不是只能跑起来就完事。我更想把整个拆解过程记录下来,从设计思路上讲清楚为什么这样建表、为什么这样设计接口、业务流转里的关键环节怎么处理,最后再把部署时容易踩的坑都列出来。如果你正打算开发类似的管理系统,或者想把这类项目做到能拿得出手的水平,这篇文章应该能帮你省下不少摸索的时间。

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

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

商城类系统天然就分两个使用场景:普通用户在前台浏览商品、下单购买,管理员在后台管理商品、处理订单。这两类用户的操作路径差异很大,如果做成传统的单体应用,页面渲染逻辑和服务端代码搅在一起,后期每加一个功能都要小心翼翼,生怕动了一行代码影响其他页面。

我选择前后端分离架构,核心考虑是让前端和后端可以独立开发、独立测试、独立部署。前端通过 HTTP 请求调用后端接口拿到 JSON 数据,自己负责页面渲染和交互逻辑;后端只专注业务逻辑和数据处理,通过统一风格的接口对外提供服务。这样拆开之后,开发阶段两边可以并行推进,后端的接口写好了直接用 Swagger 文档对接,前端也完全可以用 Mock 数据先跑起来。

1.2 技术栈选型与版本说明

这套系统的技术栈组合在目前的主流生态里算是相当稳妥的搭配,既有足够的学习价值,也有很好的就业市场需求匹配度。

后端部分,Spring Boot 2.x 搭配 MyBatis Plus 是目前非常主流的组合。Spring Boot 负责自动配置和快速启动,MyBatis Plus 在 MyBatis 的基础上提供了通用的 mapper 方法和条件构造器,单表 CRUD 几乎不用手写 SQL,大幅减少了样板代码。权限认证这块用的是 JWT,无状态认证机制非常适合前后端分离的场景,用户登录成功后得到一个 token,后续每次请求带上这个 token 即可。

前端部分,Vue 2 + Element UI 是一套经典成熟的组合。Vue 的响应式数据绑定和组件化开发模式,用来做商城这种交互丰富的页面非常顺手。Element UI 提供了表格、表单、弹窗、分页这些现成组件,后台管理页面的开发速度可以快很多。

数据库方面选择 MySQL 8.0,这是当前使用最广泛的版本。下面是我测试时使用的具体环境版本:

技术组件版本说明
JDK1.8稳定成熟,兼容性最好
Spring Boot2.7.x目前最常用的 2.x 分支
MyBatis Plus3.5.x增强版 ORM 框架
MySQL8.0.x主流关系型数据库
Vue2.6.xSPA 前端框架
Element UI2.15.x桌面端组件库
Maven3.6+依赖管理与项目构建

之所以没有追新上 Spring Boot 3 和 Vue 3,主要是考虑到这套项目的定位是学习和小型项目交付。Spring Boot 2.7 的生态资料最丰富,踩坑时很容易搜到答案;Vue 2 的 Element UI 组件库对后端转前端的同学更友好,API 设计简单直接。

1.3 数据库为什么用 MySQL 而不是其他

商城业务对事务的要求比较高,下单、扣库存、生成订单记录这些操作必须保证要么全部成功、要么全部失败,MySQL 的 InnoDB 存储引擎天然支持 ACID 事务,这一点是很多 NoSQL 数据库比不了的。同时商品、用户、订单这些实体之间有清晰的关系结构,例如一个用户对应多个订单、一个订单包含多个商品明细,这种一对多、多对多的关系用关系型数据库表达最自然。

对比过 PostgreSQL 和 MySQL 之后,最终选了 MySQL。原因很实际:一是 MySQL 的安装配置和学习资料多,遇到问题容易找到解决方案;二是这套系统后续如果要部署上线,国内主流的云厂商对 MySQL 的托管服务非常成熟,运维成本低;三是 MyBatis Plus 对 MySQL 的语法兼容做得最好,分页、条件查询这些功能开箱即用。

2. 数据库设计的核心细节

2.1 核心表结构设计思路

数据库设计是整个系统最关键的环节,表结构是否合理直接决定了后续开发的复杂度。这套商城系统我规划了八张核心业务表,它们分别是用户表、商品分类表、商品表、购物车表、订单主表、订单明细表、地址表和评论表。另外还有一张轮播图表,用来管理商城首页的横幅展示。

在设计这些表的时候,我遵循了几个关键原则。第一,范式与反范式平衡。例如订单主表里会冗余一份收货人姓名、电话和完整地址,有同学问为什么不直接关联地址表,这其实是反范式设计——因为订单生成后即使地址被修改,订单里的快照信息也不能变,这是业务刚需。第二,主键统一使用自增 id,同时设置主键索引,查询性能有保障。第三,所有金额字段全部用 decimal 类型而不是 float,这一点非常重要,float 在计算 0.1 + 0.2 的时候会丢失精度,涉及钱的字段必须用定点数。

2.2 用户表和商品表的字段设计

用户表是系统的基础表,我设计了如下的核心字段:

CREATE TABLE `user` ( `id` INT NOT NULL AUTO_INCREMENT COMMENT '用户ID', `username` VARCHAR(50) NOT NULL COMMENT '用户名', `password` VARCHAR(100) NOT NULL COMMENT '密码(BCrypt加密)', `nickname` VARCHAR(50) DEFAULT NULL COMMENT '昵称', `avatar` VARCHAR(255) DEFAULT NULL COMMENT '头像URL', `phone` VARCHAR(20) DEFAULT NULL COMMENT '手机号', `email` VARCHAR(100) DEFAULT NULL COMMENT '邮箱', `role` TINYINT NOT NULL DEFAULT 0 COMMENT '角色 0-普通用户 1-管理员', `status` TINYINT NOT NULL DEFAULT 1 COMMENT '状态 1-正常 0-禁用', `create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `update_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', PRIMARY KEY (`id`), UNIQUE KEY `uk_username` (`username`) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COMMENT='用户表';

密码字段我用 BCrypt 加密存储,而不是 MD5。MD5 虽然快,但彩虹表攻击很容易把简单密码反查出来。BCrypt 是自带盐值的哈希算法,相同密码每次加密结果都不同,安全性高一个量级。

商品表的设计则要考虑到商城的展示需求。除了基础的商品名称、价格、库存、封面图、详情描述之外,还设置了分类 id 关联分类表,上下架状态字段控制前台显示逻辑,销量字段做排序依据。这里有一个小细节:库存字段默认值是 0,每次下单扣减的时候要加判断条件防止超卖。

2.3 订单相关表的关联关系

订单表是商城系统的核心,我设计了一张订单主表和一张订单明细表。订单主表存储订单的整体信息,包括订单编号、用户 id、订单状态、商品总金额、实付金额、收货地址快照、支付时间等;订单明细表存储订单里每一项商品的快照信息,包括商品 id、商品名称、商品图片、购买单价、购买数量、小计金额。

这里要注意的关联关系是:订单主表和明细表是一对多的关系,一个订单包含多条明细。两条表通过订单 id 关联。明细表里为什么也要冗余商品名称和图片?还是那个思路——商品信息可能随时修改,但订单确认时的商品信息必须保持原样,这是对用户权益的保障。

订单编号我用了时间戳加随机数的组合方式生成,例如202501011200001234567,这样既保证了唯一性,又能从订单号里直接看出下单时间,排查问题的时候很方便。

2.4 数据库脚本文件的重要性

很多初学者在做这类项目的时候不重视数据库脚本的整理,直接在本地建表就开始写代码,做完之后整个项目的数据库结构都散落在自己的电脑里。这套系统在交付时我专门维护了一份完整的pet_shop.sql文件,里面包含了建库语句、建表语句、初始化数据和测试账号。

这样做有三个好处。第一,项目换一台电脑或者换一个人接手,一条命令就能把数据库环境搭建起来,不需要手动一张表一张表去建。第二,初始化数据可以保证演示效果,系统跑起来直接就有商品分类、商品信息和管理员账号,不需要自己手工录入。第三,数据库脚本也是文档的一部分,评审老师或者面试官可以通过脚本快速了解系统的数据模型。

3. 核心功能模块拆解与实现

3.1 用户端包含哪些页面与功能

用户端的功能设计围绕“逛-选-买-查”四个核心动作展开。商城首页展示轮播图、推荐商品和新品上架;商品列表页支持按分类筛选和关键词搜索,还有按销量和价格排序的功能;商品详情页展示商品大图、价格、库存、销量和详情描述;购物车页面支持勾选商品、修改数量、删除商品和批量结算;订单结算页需要填写收货地址、选择支付方式、生成订单;个人中心可以查看自己的订单列表、订单详情和修改个人信息。

从技术实现层面来看,用户端的核心挑战在于购物车数据的前后端同步。购物车表的设计上我以用户 id 作为外键关联,每条记录包含商品 id、加入数量和加入时间。用户登录状态下购物车功能走后端接口,数据存储在数据库里,这样换设备登录购物车数据也不会丢。

3.2 管理后台的功能规划

管理后台面向系统管理员,功能权限比用户端要高很多。我规划了仪表盘、用户管理、商品管理、分类管理、订单管理和轮播图管理六个模块。仪表盘展示系统核心数据,例如用户总量、商品总量、订单总量和销售额;用户管理支持查询用户、启用禁用用户;商品管理支持商品的增删改查和上下架操作;分类管理维护商品分类树;订单管理可以查看所有用户的订单、修改订单状态;轮播图管理维护商城首页的横幅图片。

后台功能看起来很简单,但有一个关键点需要设计好——权限控制。普通用户请求后台接口必须被拦截,管理系统只允许有管理员角色的用户访问。这个通过后端的拦截器实现,JWT token 里携带了用户角色信息,拦截器里判断角色再放行请求。

3.3 购物车模块的实现逻辑

购物车模块是整个交易链路的前端入口,它的核心业务逻辑是商品数量的增减与库存的关系检查。用户把商品加入购物车的时候,后端接口要做一个判断:如果购物车里已经存在该商品,则累加数量,否则新增一条购物车记录。

每次修改购物车数量的时候,前端会实时计算出当前这些商品的总额,这个计算在前端完成,提供良好的交互反馈。但真正下单的时候,后端会重新计算订单金额,不会盲目信任前端传过来的金额数据。我强调过很多次:所有涉及钱的逻辑必须以后端计算为准,前端传来的金额只能作为参考。

购物车减库存的操作放在用户提交订单的时候执行,而不是加入购物车的时候,这个逻辑应该很好理解——加购物车是意向,下单才是真正的购买。如果加购物车就把库存扣掉,用户只是随便逛逛把商品加入购物车却不买,库存就会一直被占用,真正想买的用户反而买不到。

3.4 订单模块的状态流转与事务处理

订单模块是整个系统里业务逻辑最复杂的部分,核心在于状态机的流转和多个相关表的联动更新。

我把订单状态设计了五种:待付款、待发货、待收货、已完成、已取消。用户提交订单后订单状态为待付款;用户模拟支付成功后状态变为待发货;管理员在后台发货后状态变为待收货;用户确认收货后状态变为已完成;超时未付款或者用户主动取消则状态变为已取消。

下单接口是典型的需要数据库事务保障的场景。当前端提交订单请求后,后端在一个事务方法里依次执行三步操作:第一步校验库存并生成订单主表记录,第二步生成订单明细表记录并扣减商品库存,第三步清空购物车中已选购的商品。这三步操作要么都执行成功,要么全部回滚。如果第二步扣库存失败,第一步生成的订单记录绝对不能留在数据库里。在 Spring Boot 里实现这个事务非常简单,只需要在 Service 方法上标注@Transactional注解。

3.5 搜索与分页功能的接口设计

商城的商品列表接口必须支持分页查询,不然数据量大了之后一次全部返回,前端渲染会卡顿,网络传输也浪费流量。我这里用 MyBatis Plus 的分页插件,传递 current 页码和 size 每页条数两个参数,返回结果包含总记录数和当前页数据列表,前端配合 Element UI 的 el-pagination 组件实现分页交互。

搜索功能的实现上没有引入 Elasticsearch 这种重量级搜索引擎,因为商城的商品量级还没到那个程度。我用的是 MySQL 的 LIKE 模糊查询,对商品名称和商品描述做匹配,配合索引优化,在数据量几十万的级别下性能完全够用。如果后续商品量涨到百万级、需要做分词搜索,再平滑升级到 Elasticsearch 也不迟。

4. 项目部署与实操记录

4.1 环境准备和配置注意事项

拿到这套系统的源码和数据库脚本之后,想把它跑起来,需要先准备好开发环境。JDK 1.8 需要配置好 JAVA_HOME 环境变量,Maven 需要配置国内镜像源以加快依赖下载速度,MySQL 8.0 安装好后需要设置 root 用户密码并创建数据库。

注意:如果你用的是 MySQL 8.0,要确认驱动依赖也是 8.0 版本。如果数据库是 MySQL 5.7,代码里的驱动类名和连接 URL 参数会稍有不同,这是最常见的环境兼容问题。

前端的运行环境要求 Node.js 版本不低于 12,npm 安装依赖的时候如果网络不稳定,可以把 npm 源切换为国内镜像源。装好依赖后,本地开发模式下启动前端工程和后端工程,后端端口默认配置为 8080,前端开发服务器端口为 8081,通过 Vue CLI 的代理功能把前端的/api开头的请求转发到后端的 8080 端口,可以完美避开跨域问题。

4.2 初始化数据库的完整流程

数据库初始化是整个系统跑起来的第一步,也是最容易出问题的一步。启动 MySQL 服务后,执行下面的命令完成建库和数据导入:

mysql -u root -p # 输入密码后进入 MySQL 命令行 # 创建数据库 CREATE DATABASE IF NOT EXISTS pet_shop DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; # 切换到目标库 USE pet_shop; # 导入建表脚本和初始化数据 source /你的路径/pet_shop.sql;

导入完成后可以用SHOW TABLES查看当前库的表清单,确认八张表加轮播图表都创建成功后,再用SELECT * FROM user检查初始化数据有没有正常导入。系统默认提供了一个管理员账号,用户名 admin,密码是 123456,以及一个测试用户账号。管理员账号用于登录后台管理界面,测试用户用于前台商城体验完整购物流程。

4.3 后端接口配置与启动步骤

后端的配置主要集中在application.yml文件里,需要修改几处关键配置才能正确连接你的数据库。

spring: datasource: url: jdbc:mysql://localhost:3306/pet_shop?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai username: root password: 你的数据库密码 driver-class-name: com.mysql.cj.jdbc.Driver

配置里要特别注意两点:useUnicode=true&characterEncoding=utf8参数保证中文数据的正确读写,serverTimezone=Asia/Shanghai参数解决 MySQL 8.0 时区导致的连接报错。如果这两项缺失或者配置错误,项目启动后查数据时会出现乱码,或者直接报The server time zone value的错误。

配置修改完成后,在项目根目录执行mvn spring-boot:run启动后端服务,或者把项目打成 jar 包执行java -jar pet-shop.jar。日志里出现 Tomcat started 后说明后端启动成功,启动端口默认 8080。

4.4 前端配置与联调关键点

前端工程的配置集中在 Vue CLI 的项目配置文件里。开发模式下最关键的是 devServer 的代理设置。打开前端项目的配置文件,找到 devServer 配置这一段:

devServer: { port: 8081, proxy: { '/api': { target: 'http://localhost:8080', changeOrigin: true } } }

配置里,前端请求统一以/api为前缀,代理将请求转发到http://localhost:8080后端服务。例如前端请求/api/user/login,实际对应后端的接口地址是http://localhost:8080/user/loginhttp://localhost:8080/api/user/login,具体要看后端 Controller 里 class 的 RequestMapping 定义。

配置好代理之后执行npm install安装依赖,再执行npm run serve启动前端开发服务器。浏览器访问http://localhost:8081就能看到商城首页。前后端联调的时候建议打开浏览器开发者工具,切到 Network 面板观察请求的 URL 和响应内容,接口报错时能快速定位是前端请求问题还是后端逻辑问题。

5. 常见问题排查与避坑指南

5.1 启动阶段的高频报错

这个项目在学习和部署的过程中,有几个坑是出现频率极高的,我在下面把这些坑和对应的解决方案直接列出来。

报错信息产生原因解决办法
Access denied for user 'root'@'localhost'数据库密码错误或用户权限不足检查 application.yml 中的账号密码与 MySQL 实际配置是否一致
The server time zone value is unrecognizedMySQL 连接时区问题连接 URL 加上 serverTimezone=Asia/Shanghai
java.lang.IllegalStateException: Cannot load driver class数据库驱动依赖缺失检查 pom.xml 是否引入 mysql-connector-java 依赖,版本与 MySQL 版本匹配
Port 8080 was already in use运行端口被其他进程占用改配置换端口,或查找占用进程后结束它
Failed to bind properties under 'spring.datasource'配置文件格式错误检查 yaml 文件缩进,datasource 的子属性必须正确对齐

数据库连接失败是启动阶段最常见的拦路虎。我建议遇到连接类报错时,先不要去看代码,直接用命令行工具测一下数据库账号能不能正常登录,这个排查思路可以快速缩小问题范围。如果命令行能登录但程序连不上,再检查驱动和 URL 配置。

5.2 接口请求报 404 和 500 的处理策略

前后端联调阶段,404 错误通常意味着请求路径匹配不上后端的接口定义。打开后端日志看请求的实际 URI,对比 Controller 类上的 RequestMapping 和具体方法上的路径注解,检查两级路径拼接后的结果,注意区分是否有多余的斜杠。还有一种情况是前后端代理配置了 /api 前缀,但后端 Controller 路径本身没带 api,代理去掉了前缀而后端实际路径不含 api,这样会导致 404。

500 错误代表后端抛出了未捕获的异常,看日志里的堆栈信息是定位问题的唯一途径。常见的 500 原因包括 SQL 语法错误、空指针异常、类型转换错误。我遇到过很多次的情况是前端传了某个字段为 null,后端调用String.length()方法时直接空指针。这种问题需要在代码里加上参数校验,或者用 MyBatis Plus 的@NotBlank注解做入参校验。

5.3 业务逻辑里容易踩的隐形坑

比启动报错更隐蔽的是业务逻辑层面的问题,这些问题程序能跑通,但数据会出错。

第一个是下单并发导致的超卖问题。如果两个用户同时购买同一个商品的最后一两件库存,两个请求同时读到库存为 1,都判断库存充足,然后各自扣减库存,库存就变成了 -1,出现超卖。解决办法是在商品表的库存更新 SQL 里加库存判断条件:UPDATE product SET stock = stock - #{num} WHERE id = #{id} AND stock >= #{num},这是乐观锁的思路,更新操作影响行数为 0 说明库存不足,事务回滚。

第二个是金额精度问题。计算订单总金额的时候,如果用 double 类型做乘法运算,例如 0.1 乘以 3 得到的结果可能是 0.30000000000000004,金额显示上会出现很诡异的小尾巴。金额必须用 BigDecimal 类型,构造时注意要用字符串构造器new BigDecimal("0.1"),不要直接new BigDecimal(0.1),否则精度丢失的问题依然存在。

第三个是日期字段处理。MySQL 的 DATETIME 类型与 Java 的 Date/LocalDateTime 之间转换时,如果前端传的是字符串日期格式,请求到后端后必须格式化匹配。统一在实体类上用@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")注解,可以保证序列化和反序列化时日期格式的一致性。

5.4 本地部署测试通过后的验收清单

一个商城系统开发完之后,不能只说能登录能浏览就算完成。我在交付前会按照下面的清单逐项测试:

  • 用户注册功能是否可用,用户名重复是否被拦截
  • 用户登录是否校验密码,密码错误是否有提示
  • 商品列表是否按分类正常筛选,搜索是否有返回结果
  • 购物车加购、增减数量、删除商品是否正常执行
  • 购物车下单后库存是否同步扣减,购物车是否清空
  • 订单状态是否能按照待付款到已完成的流程流转
  • 管理后台管理员登录后是否能管理商品和订单
  • 普通用户访问后台管理接口是否被拦截
  • 所有数据在刷新页面后是否能持久化展示

这个验收清单基本覆盖了商城系统主干链路的全部核心功能。每一项都通过后,项目才算真正达到可交付状态。

6. 源码结构与文档配套详解

6.1 后端代码的分层架构

拿到源码之后,首先要看懂后端工程的包结构,理解了分层架构,之后的修改和扩展才能做到心中有数。这套系统的后端工程按照经典的三层架构组织代码。

controller 包存放接口层,负责接收前端请求和返回响应数据;service 包存放业务逻辑层,处理具体的业务规则;mapper 包存放数据访问层,配合 MyBatis Plus 操作数据库;entity 包对应数据库表的实体类;config 包存放配置类,包括跨域配置、拦截器配置、MyBatis Plus 分页插件配置;common 包存放通用返回结果类和常量定义;util 包存放工具类,例如 JWT 工具类和密码加密工具类。

6.2 前端代码的模块划分

前端工程的核心目录是 src,下面按照功能模块划分。api 目录存放所有请求后端接口的封装方法,例如 user.js、product.js、cart.js、order.js;assets 目录存放静态资源和公共样式;components 目录存放公共组件,例如商品卡片组件、分页组件、数量选择器;views 目录存放页面级组件,例如 Home.vue、ProductDetail.vue、Cart.vue、OrderConfirm.vue、Login.vue、Register.vue,以及 admin 目录下的 ProductManage.vue、OrderManage.vue、UserManage.vue。

router 目录定义了前端路由表,包含了每个页面 URL 与组件的映射关系,还配置了路由守卫——没登录的用户不能访问个人中心页面,非管理员不能访问后台管理页面。整体上这份源码是值得花时间精读的,代码风格统一,注释也比较完整,非常适合作为学习和二次开发的底子。如果你打算扩展功能,例如接入在线支付接口、增加优惠券模块,源码中的分层结构也能让你很清晰地知道应该从哪一层切入。

6.3 配套文档包含哪些内容

交付文档是这套方案里容易被忽略但实际上非常重要的部分。完整的配套文档包含需求分析说明书、数据库设计文档、接口文档、部署说明和测试报告。

需求分析说明书描述系统的背景、目标用户、功能需求和非功能需求;数据库设计文档包含每张表的结构说明、字段含义和表间关系;接口文档通过 Swagger 自动生成可视化页面,列出了每个接口的请求方式、参数类型和响应数据结构;部署说明是面向新环境的手把手安装配置指南,从环境配到跑通全流程;测试报告则记录了核心功能的测试用例和测试结果。拿这套文档配合源码,无论是课程设计的文档部分还是毕业论文的技术章节,都有很好的参考基础。

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

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

立即咨询