1. 项目背景与核心价值
作为一名经历过多个电商项目的老手,我深知饰品电商系统的特殊之处。相比普通商品,饰品品类对图片展示、分类筛选和个性化推荐有着更高要求。这次基于SSM框架开发的饰品商城,不仅解决了毕设需求,更探索了垂直品类电商的技术实现方案。
这个系统的核心价值在于:
- 为中小饰品商家提供了完整的线上销售解决方案
- 采用主流技术栈实现高性价比的技术架构
- 通过模块化设计保证系统的可扩展性
- 优化了移动端购物体验,符合当前消费趋势
2. 技术选型与架构设计
2.1 技术栈解析
后端技术组合:
- Spring 5.3.18:控制反转和AOP实现业务解耦
- Spring MVC:采用RESTful风格设计API接口
- MyBatis 3.5.9:配合PageHelper实现高效分页
- Shiro 1.8.0:完成认证授权和会话管理
前端技术方案:
- Vue 2.6 + Element UI:构建管理后台
- Thymeleaf 3.0.12:服务端渲染商品详情页
- ECharts 5.3.2:实现销售数据可视化
数据库设计要点:
- MySQL 8.0采用InnoDB引擎
- 建立商品SPU/SKU分离模型
- 支付订单表做水平分表设计
- 使用Redis缓存热点商品数据
2.2 系统架构图解
code复制[浏览器层]
↑↓ HTTP/HTTPS
[表现层]
↑↓ Service调用
[业务逻辑层]
↑↓ DAO接口
[数据访问层]
↑↓ JDBC
[数据存储层]
├─ MySQL(主业务数据)
├─ Redis(缓存/会话)
└─ Elasticsearch(商品搜索)
2.3 关键技术实现
商品模块设计:
java复制// 商品SPU实体类
public class ProductSpu {
private Long id;
private String title;
private String subTitle;
private Long categoryId;
private List<ProductSku> skuList;
// 其他字段...
}
// 商品SKU实体类
public class ProductSku {
private Long id;
private Long spuId;
private String specValues; // JSON格式存储规格
private BigDecimal price;
private Integer stock;
// 其他字段...
}
购物车优化方案:
- 未登录用户使用Cookie存储临时购物车
- 登录后合并临时购物车到数据库
- 采用Redis Hash结构存储用户购物车
- 定期清理超过30天的未结算商品
3. 核心功能实现细节
3.1 商品展示系统
图片处理方案:
- 使用Thumbnailator生成三种尺寸图片:
- 800x800(详情页展示)
- 400x400(列表页展示)
- 100x100(缩略图)
- 图片存储采用七牛云OSS
- 实现WebP格式自动转换
商品筛选实现:
sql复制SELECT * FROM product
WHERE category_id = ?
AND price BETWEEN ? AND ?
AND id IN (
SELECT product_id FROM product_spec
WHERE spec_value IN (...)
)
ORDER BY
CASE WHEN ? = 'price_asc' THEN price END ASC,
CASE WHEN ? = 'price_desc' THEN price END DESC
LIMIT ?,?
3.2 订单处理流程
状态机设计:
code复制待支付 --支付成功--> 待发货
待支付 --取消/超时--> 已关闭
待发货 --发货--> 待收货
待收货 --确认收货--> 已完成
待收货 --申请退款--> 退款中
退款中 --商家同意--> 已退款
库存扣减方案:
java复制@Transactional
public boolean placeOrder(Order order) {
// 1. 校验库存
for(OrderItem item : order.getItems()){
int affected = productMapper.reduceStock(
item.getSkuId(),
item.getQuantity());
if(affected == 0){
throw new BusinessException("库存不足");
}
}
// 2. 创建订单
orderMapper.insert(order);
// 3. 记录订单商品
orderItemMapper.batchInsert(order.getItems());
// 4. 清空购物车
cartService.clear(order.getUserId());
return true;
}
4. 性能优化实践
4.1 数据库优化
索引策略:
- 商品表:建立(category_id, status, create_time)联合索引
- 订单表:建立(user_id, status)索引
- 搜索字段:对商品名称建立全文索引
SQL优化示例:
sql复制-- 优化前
SELECT * FROM order WHERE status = 'PAID' ORDER BY create_time DESC;
-- 优化后
SELECT * FROM order
WHERE status = 'PAID'
AND create_time > DATE_SUB(NOW(), INTERVAL 3 MONTH)
ORDER BY create_time DESC
LIMIT 100;
4.2 缓存策略
多级缓存设计:
- JVM缓存:使用Caffeine缓存基础数据
- Redis缓存:
- 商品详情:30分钟过期
- 分类树:永不过期,有更新时删除
- 秒杀库存:使用Redis原子计数器
- CDN缓存:静态资源缓存1年
缓存击穿解决方案:
java复制public Product getProduct(Long id) {
// 1. 尝试从缓存获取
Product product = redisTemplate.opsForValue().get("product:"+id);
if(product == null) {
// 2. 获取分布式锁
Lock lock = redissonClient.getLock("lock:product:"+id);
try {
if(lock.tryLock(3, 10, TimeUnit.SECONDS)) {
// 3. 再次检查缓存
product = redisTemplate.opsForValue().get("product:"+id);
if(product == null) {
// 4. 查询数据库
product = productMapper.selectById(id);
if(product != null) {
// 5. 写入缓存
redisTemplate.opsForValue().set(
"product:"+id,
product,
30, TimeUnit.MINUTES);
} else {
// 6. 缓存空对象防止穿透
redisTemplate.opsForValue().set(
"product:"+id,
new NullProduct(),
5, TimeUnit.MINUTES);
}
}
}
} finally {
lock.unlock();
}
}
return product instanceof NullProduct ? null : product;
}
5. 安全防护措施
5.1 常见攻击防护
XSS防护:
java复制// 使用Spring HtmlUtils转义输出
model.addAttribute("productName",
HtmlUtils.htmlEscape(product.getName()));
// 设置HttpOnly和Secure的Cookie
response.setHeader("Set-Cookie",
"JSESSIONID=" + sessionId + "; Path=/; HttpOnly; Secure");
CSRF防护:
html复制<!-- 表单中添加CSRF Token -->
<input type="hidden"
th:name="${_csrf.parameterName}"
th:value="${_csrf.token}">
5.2 支付安全方案
- 支付参数签名验证
- 敏感信息加密传输(使用RSA)
- 支付结果异步通知校验
- 订单金额与服务端校验
- 支付日志完整记录
6. 部署与监控
6.1 服务器部署方案
生产环境配置:
- 阿里云ECS(2核4G)×2
- 负载均衡:SLB
- 数据库:RDS MySQL 高可用版
- 缓存:Redis 集群版
- 对象存储:OSS
Docker部署示例:
dockerfile复制FROM openjdk:8-jdk
COPY target/mall.jar /app.jar
EXPOSE 8080
ENTRYPOINT ["java","-jar","/app.jar"]
6.2 监控指标
基础监控:
- CPU/Memory/Disk使用率
- JVM内存和GC情况
- 数据库连接池状态
业务监控:
- 订单创建成功率
- 支付转化率
- 接口响应时间P99
- 商品页PV/UV
7. 踩坑经验分享
7.1 图片上传问题
问题现象:
用户上传大尺寸图片导致OOM
解决方案:
- 前端限制上传文件大小(5MB以内)
- 后端使用ImageIO读取图片尺寸
- 采用流式处理避免内存溢出
- 添加图片内容校验(防止上传非图片文件)
7.2 订单超时处理
错误做法:
使用定时任务扫描未支付订单
优化方案:
java复制// 使用Redis的key过期事件
redisTemplate.opsForValue().set(
"order:"+orderId,
"1",
30, TimeUnit.MINUTES);
// 监听过期事件
@Configuration
public class RedisConfig {
@Bean
RedisMessageListenerContainer container(RedisConnectionFactory factory) {
RedisMessageListenerContainer container = new RedisMessageListenerContainer();
container.setConnectionFactory(factory);
container.addMessageListener((message, pattern) -> {
String expiredKey = message.toString();
if(expiredKey.startsWith("order:")){
String orderId = expiredKey.split(":")[1];
orderService.cancelUnpaidOrder(orderId);
}
}, new PatternTopic("__keyevent@0__:expired"));
return container;
}
}
8. 扩展方向建议
-
推荐系统集成:
- 基于用户行为的协同过滤
- 实时推荐使用Redis的SortedSet
-
秒杀功能实现:
- 库存预热到Redis
- 令牌桶限流
- 请求队列削峰
-
多商户支持:
- 增加店铺概念
- 分商户结算系统
- 自定义店铺装修
这个项目从技术选型到最终上线,让我对电商系统的核心模块有了更深入的理解。特别是在高并发场景下的优化方案,通过实际测试验证了各种技术决策的有效性。建议后续开发者可以在此基础上,继续完善监控体系和自动化测试覆盖。