1. 项目概述
这个基于SpringBoot的运动用品商城系统是一个典型的B2C电子商务平台,专为体育用品零售行业设计开发。我在实际开发过程中发现,这类系统与传统电商平台相比有几个显著特点:商品SKU属性复杂(如运动鞋有尺码、颜色、款式等多维度属性)、促销活动频繁(尤其是体育赛事期间)、用户对物流时效性要求较高。
系统采用前后端分离架构,后端基于SpringBoot 2.7 + MyBatis Plus技术栈,前端使用Vue.js + ElementUI,数据库选用MySQL 8.0。这种技术组合在保证系统性能的同时,极大提升了开发效率——从零开始搭建基础框架到完成核心功能,我们团队仅用了3周时间。
2. 核心功能模块设计
2.1 用户系统实现
采用RBAC权限模型设计用户体系,包含以下关键表结构:
sql复制CREATE TABLE `user` (
`id` bigint NOT NULL AUTO_INCREMENT,
`username` varchar(50) NOT NULL COMMENT '登录账号',
`password` varchar(100) NOT NULL COMMENT '加密密码',
`phone` varchar(20) DEFAULT NULL COMMENT '手机号',
`avatar` varchar(255) DEFAULT NULL COMMENT '头像URL',
`status` tinyint DEFAULT '1' COMMENT '状态(0-禁用 1-正常)',
`created_at` datetime DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `idx_username` (`username`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
密码加密采用BCrypt算法,这是目前最安全的密码哈希方案之一:
java复制@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
2.2 商品管理系统
体育用品的特殊性在于需要处理多维度的SKU属性。我们采用"SPU+SKU"的双层结构:
- SPU表存储商品基本信息(如"Adidas跑步鞋")
- SKU表存储具体规格(如"42码/黑色")
关键实现技巧:
java复制// 商品规格组合生成算法
public List<ProductSpecCombination> generateSpecCombinations(List<SpecGroup> groups) {
List<ProductSpecCombination> result = new ArrayList<>();
if (groups.isEmpty()) return result;
// 使用笛卡尔积算法生成所有规格组合
result = groups.stream()
.reduce(new ArrayList<ProductSpecCombination>(),
(acc, group) -> {
if (acc.isEmpty()) {
return group.getItems().stream()
.map(item -> new ProductSpecCombination(item))
.collect(Collectors.toList());
}
return acc.stream()
.flatMap(comb -> group.getItems().stream()
.map(item -> comb.combineWith(item)))
.collect(Collectors.toList());
},
(list1, list2) -> {
list1.addAll(list2);
return list1;
});
return result;
}
2.3 订单系统设计
订单模块采用状态机模式管理订单生命周期:
java复制public enum OrderStatus {
UNPAID(1, "待支付"),
PAID(2, "已支付"),
SHIPPED(3, "已发货"),
COMPLETED(4, "已完成"),
CANCELLED(5, "已取消"),
REFUNDED(6, "已退款");
// 状态转换校验逻辑
public static boolean canChangeTo(OrderStatus from, OrderStatus to) {
switch (from) {
case UNPAID:
return to == PAID || to == CANCELLED;
case PAID:
return to == SHIPPED || to == REFUNDED;
// 其他状态转换规则...
default:
return false;
}
}
}
3. 关键技术实现
3.1 高并发库存控制
采用Redis分布式锁+乐观锁双重机制防止超卖:
java复制public boolean decreaseStock(Long skuId, Integer quantity) {
String lockKey = "stock_lock:" + skuId;
String lockValue = UUID.randomUUID().toString();
try {
// 获取分布式锁
Boolean locked = redisTemplate.opsForValue()
.setIfAbsent(lockKey, lockValue, 10, TimeUnit.SECONDS);
if (!locked) {
throw new BusinessException("系统繁忙,请稍后再试");
}
// 乐观锁更新库存
int affectedRows = productMapper.updateStock(
skuId,
quantity,
"stock >= #{quantity}");
return affectedRows > 0;
} finally {
// 释放锁
if (lockValue.equals(redisTemplate.opsForValue().get(lockKey))) {
redisTemplate.delete(lockKey);
}
}
}
3.2 支付系统集成
对接支付宝和微信支付的双渠道方案:
java复制public PaymentResponse createPayment(Order order, PaymentChannel channel) {
switch (channel) {
case ALIPAY:
return alipayService.createPayment(
order.getOrderNo(),
order.getActualAmount(),
"运动商城订单支付");
case WECHAT:
return wechatPayService.createPayment(
order.getOrderNo(),
order.getActualAmount(),
order.getUser().getOpenid());
default:
throw new IllegalArgumentException("不支持的支付渠道");
}
}
支付结果异步通知处理要点:
- 验证签名确保请求合法性
- 处理幂等性(同一通知可能多次到达)
- 订单状态变更需要加分布式锁
3.3 性能优化实践
3.3.1 缓存策略
采用多级缓存架构:
- 本地缓存(Caffeine):存储热点数据,如商品基本信息
- Redis缓存:存储库存、秒杀活动等需要分布式共享的数据
- MySQL:持久化存储
缓存更新策略采用"先更新数据库,再删除缓存"的方式,避免缓存一致性问题。
3.3.2 SQL优化案例
商品列表查询优化前:
sql复制SELECT * FROM product
WHERE category_id = ?
AND status = 1
ORDER BY create_time DESC
优化后:
sql复制SELECT p.* FROM product p
JOIN product_category pc ON p.category_id = pc.id
WHERE p.category_id = ?
AND p.status = 1
AND pc.status = 1
ORDER BY p.sales DESC, p.create_time DESC
建立复合索引:
sql复制ALTER TABLE product ADD INDEX idx_category_status_sales (category_id, status, sales);
4. 系统部署方案
4.1 服务器配置建议
生产环境推荐配置:
- 应用服务器:2核4G × 2台(负载均衡)
- 数据库:4核8G + SSD(主从架构)
- Redis:2核4G(哨兵模式)
- 文件存储:OSS对象存储
4.2 Docker部署示例
后端服务Dockerfile:
dockerfile复制FROM openjdk:11-jre
WORKDIR /app
COPY target/sportshop.jar /app/app.jar
EXPOSE 8080
ENTRYPOINT ["java","-jar","app.jar"]
使用docker-compose编排:
yaml复制version: '3'
services:
mysql:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: ${DB_PASSWORD}
volumes:
- ./mysql/data:/var/lib/mysql
ports:
- "3306:3306"
redis:
image: redis:6.2
ports:
- "6379:6379"
backend:
build: .
ports:
- "8080:8080"
depends_on:
- mysql
- redis
5. 开发注意事项
5.1 常见问题排查
- 跨域问题解决方案:
java复制@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*")
.allowedMethods("GET", "POST", "PUT", "DELETE")
.allowedHeaders("*")
.maxAge(3600);
}
}
- MyBatis Plus分页失效问题:
确保在配置类中添加分页拦截器:
java复制@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor());
return interceptor;
}
5.2 安全防护措施
- XSS防护:
java复制@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.headers()
.xssProtection()
.and()
.contentSecurityPolicy("script-src 'self'");
}
}
- SQL注入防护:
- 始终使用预编译语句
- 禁止拼接SQL字符串
- 使用MyBatis Plus的Wrapper条件构造器
6. 扩展开发建议
6.1 推荐功能扩展
- 运动社区模块:
- 用户晒单分享
- 运动打卡系统
- 装备评测功能
- 智能推荐系统:
java复制public List<Product> recommendProducts(User user) {
// 基于用户行为的协同过滤
List<Product> cfProducts = cfRecommender.recommend(user.getId());
// 基于内容的推荐
List<Product> cbProducts = cbRecommender.recommend(
user.getBrowseHistory());
// 混合推荐结果
return mergeRecommendations(cfProducts, cbProducts);
}
6.2 性能监控方案
集成Prometheus + Grafana监控体系:
- 应用指标采集配置:
java复制@Bean
public MeterRegistryCustomizer<PrometheusMeterRegistry> metricsCommonTags() {
return registry -> registry.config().commonTags(
"application", "sport-shop");
}
- 关键监控指标:
- 接口响应时间(http_server_requests_seconds)
- JVM内存使用(jvm_memory_used_bytes)
- 数据库连接池(hikaricp_connections_active)
这个项目最让我印象深刻的是处理高并发秒杀场景时的各种技术挑战。实际开发中发现,单纯的Redis库存预减并不能完全解决超卖问题,还需要配合消息队列实现请求削峰,以及本地缓存减少Redis压力。最终我们实现的秒杀系统在4核8G的服务器上可以稳定支撑3000+ QPS的秒杀请求。