1. 项目背景与核心价值
这个茶叶销售系统是我去年为一家中型茶企开发的电商平台,采用SpringBoot+Vue前后端分离架构。当时客户面临三个痛点:传统手工记账效率低下、库存管理混乱、缺乏线上销售渠道。系统上线后实现了日均300+订单处理能力,库存准确率提升到99.7%,特别适合年销售额500万以下的茶叶商家。
关键数据:系统采用Redis缓存后,商品列表接口响应时间从1200ms降至180ms,MySQL配置了读写分离后QPS峰值达到1500
2. 技术架构解析
2.1 后端技术栈
- SpringBoot 2.7.4:选用LTS版本确保稳定性
- MyBatis-Plus 3.5.1:简化CRUD操作,动态表名支持多租户
- Redis 6.x:缓存热点数据(如首页推荐商品)
- RabbitMQ:处理订单超时自动取消等异步任务
java复制// 典型Controller示例
@RestController
@RequestMapping("/api/product")
public class ProductController {
@Cacheable(value = "products", key = "#root.methodName")
@GetMapping
public Result<List<Product>> list() {
return Result.success(productService.list());
}
}
2.2 前端技术栈
- Vue 2.6 + ElementUI:兼容IE11的稳妥选择
- axios:封装了401自动跳转登录等通用逻辑
- vuex-persistedstate:持久化购物车数据
javascript复制// 购物车状态管理
const cartStore = new Vuex.Store({
plugins: [createPersistedState()],
state: {
items: []
},
mutations: {
addItem(state, product) {
const exist = state.items.find(i => i.id === product.id)
exist ? exist.quantity++ : state.items.push({...product, quantity: 1})
}
}
})
3. 数据库设计要点
3.1 核心表结构
| 表名 | 字段数 | 关键字段 | 索引设计 |
|---|---|---|---|
| t_product | 18 | sku_code(唯一), category_id | sku_code, category_id |
| t_order | 23 | order_no(唯一), user_id | order_no, user_id |
| t_inventory | 9 | product_id, warehouse_id | 联合主键(product_id+warehouse_id) |
3.2 分库分表策略
当单品表超过50万条时,按category_id%8进行水平分表。使用ShardingSphere实现透明分片:
yaml复制spring:
shardingsphere:
datasource:
names: ds0,ds1
sharding:
tables:
t_product:
actual-data-nodes: ds$->{0..1}.t_product_$->{0..7}
table-strategy:
inline:
sharding-column: category_id
algorithm-expression: t_product_$->{category_id % 8}
4. 典型业务场景实现
4.1 商品秒杀功能
- Redis预减库存:Lua脚本保证原子性
- MQ削峰:将下单请求异步化处理
- 限流措施:Guava RateLimiter控制并发
lua复制-- 库存扣减Lua脚本
local stock = redis.call('get', KEYS[1])
if tonumber(stock) <= 0 then
return 0
end
redis.call('decr', KEYS[1])
return 1
4.2 订单状态机设计
使用Spring StateMachine实现订单状态流转:
code复制待支付 --支付成功--> 待发货
待支付 --超时未支付--> 已取消
待发货 --发货--> 待收货
待收货 --确认收货--> 已完成
5. 部署与性能优化
5.1 服务器配置建议
- 开发环境:2C4G(Docker Compose部署)
- 生产环境:4C8G×2(Nginx负载均衡)
- 数据库:8C16G+SSD(阿里云RDS MySQL 5.7)
5.2 JVM调优参数
bash复制java -jar \
-Xms2g -Xmx2g \
-XX:+UseG1GC \
-XX:MaxGCPauseMillis=200 \
-XX:ParallelGCThreads=4 \
-XX:ConcGCThreads=2 \
-Dspring.profiles.active=prod \
your-application.jar
6. 常见问题解决方案
6.1 微信支付回调处理
- 验证签名时注意排除sign_type参数
- 使用@Transactional注解保证数据一致性
- 需要处理重复回调(通过订单状态判断)
6.2 库存超卖问题
- 数据库乐观锁:version字段
- Redis分布式锁:Redisson实现
- 最终一致性:定期对账任务
7. 二次开发建议
- 营销功能扩展:可集成优惠券系统(参考开源项目Coupon)
- 数据分析:接入ELK实现销售分析
- 小程序端:基于uni-app快速移植
避坑提示:修改前端路由时需同步调整Nginx配置,否则会出现404。建议使用history模式并配置如下规则:
nginx复制location / {
try_files $uri $uri/ /index.html;
}
8. 源码使用指南
- 导入IDEA后先执行
mvn clean install - 数据库初始化脚本在
/doc/sql/init.sql - 配置邮箱服务需修改
application-mail.yml - 前端开发时需配置代理解决跨域:
javascript复制devServer: {
proxy: {
'/api': {
target: 'http://localhost:8080',
changeOrigin: true
}
}
}
我在实际开发中遇到最棘手的问题是微信支付证书加载问题,最终发现是PKCS12格式证书需要带别名加载:
java复制KeyStore ks = KeyStore.getInstance("PKCS12");
ks.load(new FileInputStream(certPath), mchId.toCharArray());
KeyStore.PrivateKeyEntry entry = (KeyStore.PrivateKeyEntry) ks.getEntry(
"证书别名",
new KeyStore.PasswordProtection(mchId.toCharArray())
);
