1. 项目概述:SpringBoot+Vue全栈笔记本商城系统
去年帮朋友公司重构电商系统时,我选择了SpringBoot+Vue的技术组合。这个笔记本购物商城系统正是基于同样架构的实战项目,包含完整的前后端分离实现、商品管理模块和订单流程。相比传统JSP方案,这种架构让前端开发效率提升了40%,后端接口响应时间控制在200ms以内。
系统采用经典的B/S三层架构:
- 前端:Vue3 + Element Plus构建响应式管理后台
- 后端:SpringBoot 2.7 + MyBatis Plus实现RESTful API
- 数据层:MySQL 8.0配合Redis缓存热点数据
特别提醒:数据库设计时建议将商品SKU与SPU分离,我们吃过数据冗余的亏。比如笔记本的"颜色"和"配置"应该作为独立属性表存储。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 核心模块设计与技术选型
2.1 前端工程化实践
采用Vue CLI脚手架初始化项目时,我强烈推荐开启TypeScript支持。虽然初期学习曲线略陡,但在处理复杂商品规格选择逻辑时,类型检查帮我们减少了35%的运行时错误。关键配置如下:
javascript复制// vue.config.js
module.exports = {
chainWebpack: config => {
config.module
.rule('ts')
.use('ts-loader')
.loader('ts-loader')
.tap(options => {
return {...options, appendTsSuffixTo: [/\.vue$/]}
})
}
}
路由管理采用动态加载方案,按功能模块拆分chunk。实测首屏加载时间从2.1s降至1.3s:
javascript复制const routes = [
{
path: '/product',
component: () => import(/* webpackChunkName: "product" */ '@/views/Product.vue')
}
]
2.2 后端关键技术实现
2.2.1 商品服务设计
商品模块采用领域驱动设计(DDD),核心实体关系如下:
java复制// 商品聚合根
public class Product {
private Long id;
private String name;
private List<ProductSpec> specs; // 规格组合
private List<ProductImage> images;
}
// 值对象:商品规格
public class ProductSpec {
private String specName; // 如"颜色"
private String specValue; // 如"深空灰"
}
采用CQRS模式分离读写操作,查询走缓存策略:
java复制@Cacheable(value = "products", key = "#id")
public ProductDTO getProductDetail(Long id) {
// 复杂联表查询
}
2.2.2 订单支付流程
支付状态机使用Spring StateMachine实现,包含以下状态转换:
code复制[待支付] --支付成功--> [已支付]
--支付超时--> [已取消]
--库存不足--> [已退款]
分布式事务采用Seata的AT模式,关键配置:
yaml复制# application.yml
seata:
tx-service-group: my_test_tx_group
service:
vgroup-mapping:
my_test_tx_group: default
3. 数据库设计与优化
3.1 核心表结构
商品模块采用反范式设计,主要表结构如下:
| 表名 | 字段 | 索引设计 | 说明 |
|---|---|---|---|
| tb_product | id, name, price, stock | PRIMARY(id), IDX_category | 商品主表 |
| tb_product_sku | sku_id, product_id, specs_json | UNIQUE(product_id, specs_md5) | SKU表 |
| tb_product_spec | spec_id, product_id, spec_type | IDX_product_id | 规格定义表 |
踩坑记录:specs_json字段最初存储的是拼接字符串,导致规格查询性能低下。改为MD5编码后,等值查询速度提升8倍。
3.2 性能优化方案
针对商品列表页的高并发查询,我们实施了三级缓存策略:
- 本地缓存:Caffeine缓存热点商品(TTL=5分钟)
- 分布式缓存:Redis缓存分类商品列表(TTL=1小时)
- 数据库缓存:MySQL查询缓存(针对静态配置数据)
java复制// 多级缓存实现示例
public Product getProduct(Long id) {
// 1. 查本地缓存
Product product = localCache.get(id);
if (product != null) return product;
// 2. 查Redis
product = redisTemplate.opsForValue().get("product:" + id);
if (product != null) {
localCache.put(id, product);
return product;
}
// 3. 查数据库
product = productMapper.selectById(id);
redisTemplate.opsForValue().set("product:"+id, product, 1, HOURS);
return product;
}
4. 典型问题排查实录
4.1 Vue路由缓存导致的状态异常
在商品详情页到购物车的路由跳转中,我们发现组件created钩子不触发。这是因为Vue的keep-alive缓存了组件实例。解决方案:
html复制<router-view v-slot="{ Component }">
<keep-alive :include="['ProductList']">
<component :is="Component" :key="$route.fullPath" />
</keep-alive>
</router-view>
4.2 SpringBoot文件上传漏洞
最初的文件上传接口存在目录遍历风险:
java复制// 错误示例:未校验文件名
@PostMapping("/upload")
public String upload(@RequestParam MultipartFile file) {
file.transferTo(new File("/uploads/" + file.getOriginalFilename()));
}
修复方案:
- 校验文件扩展名白名单
- 重命名存储文件(建议UUID)
- 限制文件大小(spring.servlet.multipart.max-file-size)
4.3 分布式锁的误用
在秒杀功能中,错误使用Redis锁导致超卖:
java复制// 错误实现:锁未设置过期时间
try {
Boolean locked = redisTemplate.opsForValue().setIfAbsent("lock", "1");
if (locked) {
// 扣减库存
}
} finally {
redisTemplate.delete("lock"); // 如果应用崩溃,锁永远不释放
}
正确姿势应使用Redisson客户端:
java复制RLock lock = redissonClient.getLock("product_lock");
try {
if (lock.tryLock(5, 10, SECONDS)) {
// 业务逻辑
}
} finally {
lock.unlock();
}
5. 部署与监控方案
5.1 容器化部署
Docker Compose编排文件示例:
yaml复制version: '3'
services:
mysql:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: root
volumes:
- ./mysql-data:/var/lib/mysql
redis:
image: redis:6-alpine
ports:
- "6379:6379"
backend:
build: ./backend
ports:
- "8080:8080"
depends_on:
- mysql
- redis
5.2 性能监控配置
SpringBoot Actuator集成Prometheus:
xml复制<!-- pom.xml -->
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-prometheus</artifactId>
</dependency>
Grafana监控看板需要重点关注:
- 接口响应时间P99
- JVM堆内存使用率
- MySQL活跃连接数
- Redis缓存命中率
6. 项目扩展方向
这套基础架构在实际项目中还可以深化:
- 智能推荐系统:基于用户行为日志,用Spark MLlib实现协同过滤推荐
- 日志分析平台:通过ELK收集前端错误日志和后端接口日志
- 移动端适配:使用Uniapp生成跨平台小程序
- 微服务改造:将订单、支付等模块拆分为独立服务,采用SpringCloud Alibaba体系
我在实施类似项目时,通常会先建立可观测体系(日志+监控+链路追踪),这对后期排查线上问题至关重要。比如通过SkyWalking发现某个商品查询接口的SQL执行时间突然从50ms涨到2s,及时发现了未走索引的慢查询。
