今天教大家如何设计一个图书商城 , 基于目前主流的技术:前端vue,后端springboot。
同时还带来的项目的部署教程。
视频演示
图片演示







一. 系统概述
商城是一款比较庞大的系统,需要有商品中心,库存中心,订单中心,收货地址和运费管理。先看下我们要实现的商城有哪些功能:
1. 商品分类管理。
2. 商品管理。
3.库存管理。
4.订单管理。
5. 评价管理。
6.用户管理。
7.运费和运费模板管理。
8. 系统公告管理。
9.首页轮播图管理。
10. 用户购物车。
二. 核心功能实现思想
库存系统的设计
库存最大的问题就是超卖,也就是说有多个人同时并发下单,库存需要保持一致性,不会扣减到小于0的情况。普通的设计就是加一个全局锁。每个人下单都需要等待上一个人下单完成。
这样严重影响效率。这里我们库存的设计流程如下:
1. 首先我们将库存分为 数据库库存 和 销售库存。 数据库库存就是存储到数据库的商品库存值,销售库存就是用户下单,页面所在的库存值。
2. 后台管理上架商品时,会设置一个初始库存,我们将初始库存存储到数据库库存 和 销售库存 。
3.当用户下单时,不是直接扣减的数据库库存,而是通过redis的 decrement 方法,对销售库存进行扣减。但是redis的扣减操作这里还不是一个原子性操作,需要先从redis查出库存,然后进行decrment操作。这两步操作我们用reddsion的分布式锁来控制原子性,同时,我们将加锁的维度控制到了商品id。这样大大提高了并发效率。
3. 库存扣减后,我们又通过redis消费队列,实现了对数据库库存的同步。这样保持了redis库存和数据库库存的一致性。
4. 后台我们设计的是对商品只能加加库存,和减少库存的操作,而不是直接修改库存值。如果你直接修改库存值,就有可能会导致库存数据不一致,难以跟踪。
5. 我们还设计了库存的扣减,新增日志,方便对库存进行跟踪管理。
库存扣减的部分代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 | /** * 扣减库存(使用Redisson分布式锁) * @param productId 商品ID * @param quantity 扣减数量 * @return true-扣减成功,false-扣减失败(库存不足) */ public boolean deductInventory(String productId, int quantity) { String lockKey = "lock:inventory:" + productId; String inventoryKey = "inventory:" + productId; RLock lock = redissonClient.getLock(lockKey); try { // 尝试加锁,最多等待10秒,锁过期时间30秒 boolean locked = lock.tryLock( 10 , 30 , TimeUnit.SECONDS); if (locked) { String stock = (String) redisTemplate.opsForValue().get(inventoryKey); if (StringUtils.isEmpty(stock)){ return false ; } if (Integer.parseInt(stock) < quantity) { return false ; } // 扣减库存 redisTemplate.opsForValue().decrement(inventoryKey, quantity); return true ; } return false ; } catch (InterruptedException e) { Thread.currentThread().interrupt(); return false ; } finally { // 释放锁 if (lock.isHeldByCurrentThread()) { lock.unlock(); } } } /** * 设置商品库存 * @param productId 商品ID * @param quantity 库存数量 */ public void setInventory(String productId, int quantity) { String inventoryKey = "inventory:" + productId; redisTemplate.opsForValue().set(inventoryKey, quantity); System.out.println( "库存设置: 商品id:" + productId + " , 数量:" + quantity); } /** * 获取商品库存 * @param productId 商品ID * @return 当前库存数量 */ public int getInventory(String productId) { String inventoryKey = "inventory:" + productId; Object value = redisTemplate.opsForValue().get(inventoryKey); return value == null ? 0 : Integer.parseInt(value.toString()); } |
商品系统的设计
商品包含了很多属性,这里我设计的商品表如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | CREATE TABLE `product` ( `product_id` int NOT NULL AUTO_INCREMENT COMMENT '商品id' , `product_name` varchar( 100 ) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '商品名称' , `category_id` int NOT NULL COMMENT '类目id' , `product_title` varchar( 300 ) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '商品标题' , `product_intro` text CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '商品详情' , `product_picture` varchar( 200 ) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '商品封面图' , `product_price` double NOT NULL COMMENT '商品原价' , `product_selling_price` double NOT NULL COMMENT '商品售卖价' , `product_num` int NOT NULL COMMENT '商品库存' , `product_sales` int NOT NULL COMMENT '销量' , `state` tinyint DEFAULT '0' COMMENT '0-上架 1- 下架' , `score` double DEFAULT NULL COMMENT '推荐评分,总共有5星' , PRIMARY KEY (`product_id`) USING BTREE ) ENGINE=InnoDB AUTO_INCREMENT= 20 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin COMMENT= '商品' ; |
商品还关联了多图
1 2 3 4 5 6 7 | CREATE TABLE `product_picture` ( `id` int NOT NULL AUTO_INCREMENT COMMENT '主键id' , `product_id` int NOT NULL COMMENT '商品id' , `product_picture` varchar( 200 ) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '商品图片' , `intro` text CHARACTER SET utf8 COLLATE utf8_general_ci, PRIMARY KEY (`id`) USING BTREE ) ENGINE=InnoDB AUTO_INCREMENT= 167 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin COMMENT= '商品图片' ; |
商品还有一个动态的字典属性

动态字典属性表设计
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | CREATE TABLE `product_attr` ( `id` int NOT NULL AUTO_INCREMENT, `product_id` int NOT NULL, `product_attr_config_id` int NOT NULL COMMENT '商品属性字典id' , `attr_val` varchar( 500 ) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '属性值' , PRIMARY KEY (`id`) USING BTREE ) ENGINE=InnoDB AUTO_INCREMENT= 190 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin COMMENT= '商品属性与字典关联' ; CREATE TABLE `product_attr_config` ( `id` int NOT NULL AUTO_INCREMENT, `attr_name` varchar( 500 ) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '字典描述' , `attr_key` varchar( 500 ) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '字典key' , PRIMARY KEY (`id`) USING BTREE ) ENGINE=InnoDB AUTO_INCREMENT= 8 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin COMMENT= '商品属性字典' ; |
订单系统的设计
我们将订单的状态设计成以下几种:0-待付款 1-待发货 2-待收货 3-待评价 4-已完成 5-退款中 6-已退款 7-已取消。
订单状态扭转流程:
1. 用户点击购买商品或从购物车点击,则商品进入待付款状态,此时,商品库存被锁,也就是实实在在的扣减了销售库存。
2. 当30分钟超过后,用户未支付上面的待付款订单,则订单状态扭转为已取消,库存回流,此笔订单结束。
3. 当用户30分钟内支付后,订单扭转为代发货。
4. 管理员登录管理后台,将待发货订单进行发货操作后,订单状态变成待收货。
5. 用户可以对待收获订单进行收获和退款操作,如果是退款,则变成退款中,管理员进行退款确认,确认后,订单变成已退款,退款成功后,库存回流。此订单结束。
6. 如果用户确认收获,则订单变成待评价,用户可以进行评价,评价完成后,订单变成已完成,此订单结束。
订单表设计如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | CREATE TABLE `orders` ( `order_id` varchar( 200 ) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL, `user_id` int NOT NULL COMMENT '用户id' , `product_id` int NOT NULL COMMENT '商品id' , `product_num` int NOT NULL COMMENT '商品数量' , `order_state` int NOT NULL COMMENT '订单状态 0-待付款 1-待发货 2-待收货 3-待评价 4-已完成 5-退款中 6-已退款 7-已取消' , `product_price` double NOT NULL COMMENT '下单商品价格' , `shipping_price` double NOT NULL COMMENT '下单运费价格' , `refund_cause` varchar( 2255 ) COLLATE utf8mb4_bin DEFAULT NULL COMMENT '退款原因' , `order_remark` varchar( 2000 ) COLLATE utf8mb4_bin NOT NULL COMMENT '订单备注' , `pay_type` int DEFAULT NULL COMMENT '支付方式:0-支付宝 1-微信' , `address` varchar( 2000 ) COLLATE utf8mb4_bin NOT NULL COMMENT '收获地址' , `create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间' , PRIMARY KEY (`order_id`) USING BTREE ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin COMMENT= '订单' ; |
三. 技术栈概述
后端技术栈:
JDK8 + springboot + mysql8
前端技术栈:
vue + Axios 等
四. 项目部署教程
前端部署
安装node , 版本:v22.15.0 , 安装完成后。
进入到项目 hadluo-shop-webadmin 目录下,这个项目是vue的管理后台, 右键,运行cmd,运行下面命令:
npm run dev
由于我已经跟你npm install好了,所以你无需执行,直接run就可以了!!
运行项目

进入到项目 hadluo-shop-h5 目录下,这个项目是vue的前端, 右键,运行cmd,运行下面命令:
npm run dev
由于我已经跟你npm install好了,所以你无需执行,直接run就可以了!!
运行项目

到此前端项目部署完成。
执行sql
自己安装好数据库,注意,必须是mysql8 ,否则代码运行会出错。新建一个 wxhadluo-bookshop 数据库, 然后执行 “wxhadluo-bookshop.sql”
Redis安装
项目需要安装redis,直接下载一个windows版本的redis即可,没有的联系我。
启动后端项目
然后部署后端 , 打开idea, 导入maven工程 hadluo-bookshop。
打开resources目录, 修改 application.yml 配置文件,主要修改下面几个信息:

然后启动 main 启动类 : Application.class
五. 访问项目
管理后端:
http://localhost:3001/
账号:wx-hadluo, 密码: 123456
前端:
http://localhost:3000/
用户: 453423@qq.com / 123456
可以自己注册用户。