1. 项目概述:全栈电商平台的技术选型与架构设计
去年带队开发某跨境电商项目时,我们最终选择了SpringBoot+Vue3+MyBatis这套技术栈。这个组合在保证开发效率的同时,完美支撑了日均10万+订单的业务规模。今天要剖析的网上购物商城系统,正是采用相同架构的经典实现方案。
这套系统采用前后端分离架构,后端基于SpringBoot 2.7提供RESTful API,前端使用Vue3+TypeScript构建响应式界面,数据持久层采用MyBatis-Plus增强MySQL操作。特别值得注意的是,源码中包含了完整的SKU管理、购物车逻辑和分布式事务处理等电商核心模块的实现。
2. 技术栈深度解析
2.1 SpringBoot后端设计要点
基础框架搭建时推荐使用Spring Initializr生成项目骨架,我通常会额外添加这些依赖:
xml复制<!-- 核心依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.3</version>
</dependency>
<!-- 电商特色模块 -->
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson-spring-boot-starter</artifactId>
<version>3.23.2</version>
</dependency>
商品服务的典型分层结构:
code复制com.example.mall
├── controller # 对外API接口
├── service # 业务逻辑层
│ ├── impl # 实现类
├── dao # 数据访问层
├── entity # 实体类
└── config # 配置类
关键经验:使用@Transactional注解时务必设置rollbackFor=Exception.class,否则某些异常场景下事务不会回滚。我们在支付模块就踩过这个坑。
2.2 Vue3前端工程化实践
推荐使用Vite初始化项目,比传统Webpack构建速度快10倍以上:
bash复制npm create vite@latest mall-frontend --template vue-ts
核心目录结构设计:
markdown复制src/
├── api/ # Axios请求封装
├── assets/ # 静态资源
├── components/ # 公共组件
├── composables/ # 组合式函数
├── router/ # 路由配置
├── stores/ # Pinia状态管理
└── views/ # 页面组件
商品列表页的性能优化技巧:
vue复制<script setup>
// 使用async/await处理异步加载
const { data: goodsList } = await useAsyncData(
'goods',
() => $fetch('/api/goods/list')
)
// 虚拟滚动优化长列表
<VirtualList :items="goodsList" />
</script>
2.3 MyBatis-Plus高效数据操作
在application.yml中配置多数据源:
yaml复制spring:
datasource:
master:
url: jdbc:mysql://localhost:3306/mall?useSSL=false
username: root
password: 123456
slave:
url: jdbc:mysql://replica:3306/mall?useSSL=false
动态SQL示例:
java复制@SelectProvider(type = GoodsSqlBuilder.class, method = "buildQuery")
List<Goods> queryByConditions(GoodsQuery query);
public class GoodsSqlBuilder {
public String buildQuery(GoodsQuery query) {
return new SQL() {{
SELECT("*");
FROM("t_goods");
if (query.getCategoryId() != null) {
WHERE("category_id = #{categoryId}");
}
if (StringUtils.isNotBlank(query.getKeyword())) {
WHERE("name LIKE CONCAT('%',#{keyword},'%')");
}
}}.toString();
}
}
3. 核心业务模块实现
3.1 商品中心设计
ER图关键实体关系:
mermaid复制erDiagram
CATEGORY ||--o{ GOODS : contains
GOODS ||--o{ SKU : has
GOODS ||--o{ GOODS_IMAGE : has
库存扣减的分布式锁实现:
java复制public boolean reduceStock(Long skuId, Integer num) {
String lockKey = "stock_lock:" + skuId;
RLock lock = redissonClient.getLock(lockKey);
try {
boolean locked = lock.tryLock(5, 10, TimeUnit.SECONDS);
if (locked) {
// 执行库存扣减逻辑
return stockService.update()
.setSql("stock = stock - " + num)
.eq("sku_id", skuId)
.gt("stock", num)
.update();
}
} finally {
lock.unlock();
}
return false;
}
3.2 购物车与订单系统
购物车数据结构设计:
json复制{
"userId": 1001,
"items": [
{
"skuId": 2001,
"quantity": 2,
"selected": true,
"price": 2999,
"specs": "8GB+256GB 黑色"
}
]
}
订单状态机设计:
java复制public enum OrderStatus {
UNPAID(1, "待支付"),
PAID(2, "已支付"),
SHIPPED(3, "已发货"),
COMPLETED(4, "已完成"),
CANCELLED(5, "已取消");
// 状态流转校验逻辑
public static boolean canChangeTo(OrderStatus from, OrderStatus to) {
// 具体状态流转规则...
}
}
3.3 支付与结算系统
支付宝沙箱接入示例:
java复制@RestController
@RequestMapping("/payment")
public class PaymentController {
@PostMapping("/alipay")
public String createAlipayOrder(@RequestBody OrderDTO order) {
AlipayTradePagePayRequest request = new AlipayTradePagePayRequest();
request.setReturnUrl(paymentProperties.getReturnUrl());
request.setNotifyUrl(paymentProperties.getNotifyUrl());
AlipayTradePagePayModel model = new AlipayTradePagePayModel();
model.setOutTradeNo(order.getOrderNo());
model.setTotalAmount(order.getAmount().toString());
model.setSubject(order.getSubject());
model.setProductCode("FAST_INSTANT_TRADE_PAY");
request.setBizModel(model);
return alipayClient.pageExecute(request).getBody();
}
}
4. 部署与性能优化
4.1 生产环境部署方案
推荐使用Docker Compose编排:
yaml复制version: '3'
services:
backend:
image: mall-backend:1.0
ports:
- "8080:8080"
environment:
- SPRING_PROFILES_ACTIVE=prod
depends_on:
- mysql
- redis
frontend:
image: mall-frontend:1.0
ports:
- "80:80"
mysql:
image: mysql:8.0
volumes:
- mysql_data:/var/lib/mysql
environment:
- MYSQL_ROOT_PASSWORD=123456
- MYSQL_DATABASE=mall
volumes:
mysql_data:
4.2 缓存与性能调优
多级缓存配置策略:
- 本地缓存(Caffeine):高频访问的基础数据
- Redis缓存:分布式共享数据
- MySQL:持久化存储
示例缓存注解使用:
java复制@Cacheable(value = "goods", key = "#id", unless = "#result == null")
public Goods getById(Long id) {
return goodsMapper.selectById(id);
}
@CacheEvict(value = "goods", key = "#goods.id")
public void updateGoods(Goods goods) {
goodsMapper.updateById(goods);
}
5. 常见问题排查指南
5.1 跨域问题解决方案
后端全局CORS配置:
java复制@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*")
.allowedMethods("GET", "POST", "PUT", "DELETE")
.allowedHeaders("*")
.maxAge(3600);
}
}
5.2 接口幂等性处理
使用token机制防止重复提交:
java复制@PostMapping("/order/create")
public Result createOrder(@RequestBody OrderDTO dto,
@RequestHeader("X-Idempotent-Token") String token) {
if (!redisTemplate.opsForValue().setIfAbsent(
"idempotent:" + token, "1", 30, TimeUnit.MINUTES)) {
throw new BusinessException("请勿重复提交订单");
}
return orderService.createOrder(dto);
}
5.3 数据库连接池优化
推荐配置(基于HikariCP):
yaml复制spring:
datasource:
hikari:
maximum-pool-size: 20
minimum-idle: 5
connection-timeout: 30000
idle-timeout: 600000
max-lifetime: 1800000
connection-test-query: SELECT 1
这套电商系统源码中最值得借鉴的是其清晰的模块划分和事务处理逻辑。特别是在订单创建流程中,采用TCC模式处理分布式事务的做法,在实际业务中能有效保证数据一致性。建议开发者重点研究库存服务与订单服务间的交互设计,这是电商系统的核心难点所在。