1. 项目概述
这个全栈电商管理系统采用SpringBoot+Vue技术栈实现,包含完整的前后端代码和数据库设计。系统模拟小米商城业务场景,实现了商品管理、订单处理、会员体系等核心电商功能模块。
我在实际开发中发现,这类电商系统最难的不是基础CRUD功能的实现,而是如何处理好高并发场景下的库存一致性和订单状态流转。系统采用分布式锁和乐观锁相结合的方式,在保证性能的同时实现了库存的精准控制。
2. 技术架构解析
2.1 后端技术选型
SpringBoot 2.7作为基础框架,配合以下技术组件:
- MyBatis-Plus 3.5:简化DAO层开发
- Redis 6.2:缓存热点数据和分布式锁实现
- RabbitMQ 3.9:异步处理订单状态变更
- Swagger 3.0:API文档自动生成
特别注意:MyBatis-Plus的乐观锁注解@Version在实际使用中需要配合重试机制,我们封装了自定义的RetryTemplate来处理并发冲突。
2.2 前端技术方案
Vue3组合式API开发,主要技术栈:
- Element Plus:UI组件库
- Axios:HTTP请求封装
- Vuex:状态管理
- ECharts:数据可视化
前端工程采用模块化设计,商品展示和订单管理作为独立SPA应用,通过微前端qiankun框架集成。
3. 核心功能实现
3.1 商品中心模块
数据库设计采用纵向分表策略:
CREATE TABLE `product` ( `id` bigint NOT NULL AUTO_INCREMENT, `name` varchar(100) NOT NULL, `price` decimal(10,2) NOT NULL, `stock` int NOT NULL COMMENT '总库存', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; CREATE TABLE `product_sku` ( `id` bigint NOT NULL AUTO_INCREMENT, `product_id` bigint NOT NULL, `specs` json DEFAULT NULL COMMENT '规格JSON', `price` decimal(10,2) NOT NULL, `stock` int NOT NULL, PRIMARY KEY (`id`), KEY `idx_product` (`product_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;库存扣减的关键代码:
@Transactional public boolean reduceStock(Long skuId, Integer quantity) { // 分布式锁防止超卖 String lockKey = "stock_lock:" + skuId; try { boolean locked = redisTemplate.opsForValue() .setIfAbsent(lockKey, "1", 10, TimeUnit.SECONDS); if (!locked) { throw new BusinessException("操作太频繁,请稍后重试"); } ProductSku sku = skuMapper.selectById(skuId); if (sku.getStock() < quantity) { throw new BusinessException("库存不足"); } int rows = skuMapper.updateStock(skuId, quantity); return rows > 0; } finally { redisTemplate.delete(lockKey); } }3.2 订单系统设计
订单状态机设计:
stateDiagram-v2 [*] --> PENDING PENDING --> PAID: 支付成功 PENDING --> CANCELLED: 用户取消 PAID --> SHIPPED: 发货 SHIPPED --> COMPLETED: 确认收货 SHIPPED --> REFUNDING: 申请退款 REFUNDING --> REFUNDED: 退款成功订单分表策略:按用户ID哈希分16张表,解决单表数据量过大问题。
4. 性能优化实践
4.1 缓存设计
采用多级缓存策略:
- 本地Caffeine缓存:缓存时间5分钟
- Redis集群:缓存时间30分钟
- 数据库:原始数据
缓存击穿解决方案:
public Product getProductWithCache(Long id) { String cacheKey = "product:" + id; // 1. 查询本地缓存 Product product = localCache.get(cacheKey); if (product != null) { return product; } // 2. 查询Redis product = redisTemplate.opsForValue().get(cacheKey); if (product != null) { localCache.put(cacheKey, product); return product; } // 3. 获取分布式锁 String lockKey = "product_lock:" + id; try { boolean locked = redisTemplate.opsForValue() .setIfAbsent(lockKey, "1", 30, TimeUnit.SECONDS); if (locked) { // 4. 查询数据库 product = productMapper.selectById(id); if (product != null) { redisTemplate.opsForValue() .set(cacheKey, product, 30, TimeUnit.MINUTES); localCache.put(cacheKey, product); } else { // 缓存空对象防止穿透 redisTemplate.opsForValue() .set(cacheKey, new NullProduct(), 5, TimeUnit.MINUTES); } } else { // 等待重试 Thread.sleep(100); return getProductWithCache(id); } } finally { redisTemplate.delete(lockKey); } return product; }4.2 MySQL优化
- 索引优化:
- 为所有外键字段创建索引
- 为高频查询条件创建组合索引
- 查询优化:
- 避免SELECT *
- 使用JOIN替代子查询
- 配置优化:
innodb_buffer_pool_size = 4G innodb_log_file_size = 256M query_cache_size = 0
5. 安全防护措施
5.1 接口安全
- JWT鉴权方案:
- 使用HS512算法签名
- AccessToken有效期2小时
- RefreshToken有效期7天
- 接口防刷:
- 滑动窗口限流(Redis+Lua实现)
- 关键操作验证码校验
5.2 数据安全
- 敏感数据加密:
// 手机号加密存储 @ColumnEncrypt(algorithm = Algorithm.PBEWithMD5AndDES) private String mobile; - 日志脱敏处理:
@LogMask(pattern = "(\\d{3})\\d{4}(\\d{4})", replace = "$1****$2") private String idCard;
6. 部署方案
6.1 容器化部署
Docker Compose编排文件示例:
version: '3' services: mysql: image: mysql:8.0 environment: MYSQL_ROOT_PASSWORD: ${DB_PASSWORD} volumes: - ./mysql/data:/var/lib/mysql - ./mysql/conf:/etc/mysql/conf.d ports: - "3306:3306" redis: image: redis:6.2 command: redis-server --requirepass ${REDIS_PASSWORD} ports: - "6379:6379" backend: build: ./backend ports: - "8080:8080" depends_on: - mysql - redis frontend: build: ./frontend ports: - "80:80"6.2 监控方案
- SpringBoot Actuator暴露监控端点
- Prometheus + Grafana监控体系
- ELK日志收集系统
7. 开发注意事项
- 代码规范:
- 遵循Alibaba Java Coding Guidelines
- 前端使用ESLint+Prettier
- 提交规范:
- Angular Commit Message规范
- 禁止直接提交到master分支
- 测试要求:
- 单元测试覆盖率≥80%
- 集成测试覆盖核心业务流程
8. 常见问题解决
8.1 分布式事务问题
使用Seata解决跨服务事务:
@GlobalTransactional public void createOrder(OrderDTO orderDTO) { // 1. 扣减库存 stockService.reduceStock(orderDTO.getSkuId(), orderDTO.getQuantity()); // 2. 创建订单 orderService.create(orderDTO); // 3. 扣减积分 memberService.deductPoints(orderDTO.getUserId(), orderDTO.getPoints()); }8.2 前端性能优化
- 图片懒加载:
<img v-lazy="product.image" alt="product"> - 路由懒加载:
const ProductDetail = () => import('./views/ProductDetail.vue') - Webpack分包优化:
config.optimization.splitChunks({ chunks: 'all', maxSize: 244 * 1024 })
9. 扩展建议
- 营销功能扩展:
- 优惠券系统
- 秒杀活动
- 拼团功能
- 数据分析扩展:
- 用户行为分析
- 商品推荐系统
- 多端适配:
- 小程序版本
- APP原生版本
这个项目我在实际开发中最大的体会是:电商系统的复杂度往往来自于业务规则而非技术实现。建议在开发前先梳理清楚所有的业务状态流转和异常处理流程,这会节省大量的后期调试时间。