今天教大家如何設計一個圖書商城?, 基于目前主流的技術:前端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
可以自己注冊用戶。