1. 项目背景与核心需求
在美妆行业数字化转型浪潮下,线上商城系统已成为品牌运营的标配基础设施。传统PHP或JSP架构的电商平台在面对高并发场景和复杂业务逻辑时,往往面临维护成本高、扩展性差的痛点。这正是我们采用SpringBoot+Vue全栈技术栈构建专业级美妆商城管理系统的核心动因。
这个系统需要同时满足三类角色的需求:
- 消费者端:需要商品展示、智能推荐、秒杀抢购等C端功能
- 商家端:需要库存管理、订单处理、营销活动配置等B端功能
- 平台运营:需要数据看板、用户行为分析、风控管理等后台能力
技术选型上,后端采用SpringBoot 2.7.x版本,主要基于:
- 自动配置特性简化了SSM框架的整合复杂度
- 内嵌Tomcat支持快速部署和水平扩展
- Actuator端点提供完善的系统监控能力
- 与MyBatis-Plus的天然契合度,极大提升DAO层开发效率
前端选用Vue 3.x+Element Plus组合,优势在于:
- Composition API使复杂业务组件更易维护
- Pinia状态管理解决多模块数据共享问题
- 基于Vite的构建速度比传统Webpack提升5-8倍
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 系统架构设计
2.1 整体技术架构
采用前后端分离架构,通过RESTful API进行数据交互。系统划分为六个核心模块:
code复制┌───────────────────────────────────────┐
│ 客户端层 │
│ ┌───────────┐ ┌───────────┐ │
│ │ Web前端 │ │ 移动端H5 │ │
│ └───────────┘ └───────────┘ │
└───────────────────┬───────────────────┘
│ HTTP/HTTPS
┌───────────────────▼───────────────────┐
│ 网关层 │
│ ┌─────────────────────────────────┐ │
│ │ API Gateway │ │
│ │ (路由/限流/鉴权/负载均衡) │ │
│ └─────────────────────────────────┘ │
└───────────────────┬───────────────────┘
│
┌───────────────────▼───────────────────┐
│ 业务服务层 │
│ ┌───────┐ ┌───────┐ ┌───────┐ │
│ │用户服务│ │商品服务│ │订单服务│ ... │
│ └───────┘ └───────┘ └───────┘ │
└───────────────────┬───────────────────┘
│
┌───────────────────▼───────────────────┐
│ 数据持久层 │
│ ┌───────┐ ┌───────┐ ┌───────┐ │
│ │ MySQL │ │ Redis │ │ Elasticsearch │
│ └───────┘ └───────┘ └───────┘ │
└───────────────────────────────────────┘
2.2 数据库设计要点
针对美妆行业特点,核心表设计需特别注意:
商品表(product)关键字段:
sql复制CREATE TABLE `product` (
`id` bigint NOT NULL AUTO_INCREMENT,
`spu_code` varchar(64) COMMENT '标准产品单元编码',
`sku_code` varchar(64) COMMENT '库存量单位编码',
`name` varchar(128) NOT NULL,
`subtitle` varchar(256) COMMENT '促销标语',
`category_id` int COMMENT '三级分类ID',
`brand_id` int,
`price` decimal(10,2) COMMENT '划线价',
`actual_price` decimal(10,2) COMMENT '实际售价',
`stock` int DEFAULT 0,
`shelf_status` tinyint COMMENT '上下架状态',
`ingredient` text COMMENT '成分表',
`skin_type` varchar(64) COMMENT '适用肤质',
`shelf_life` varchar(32) COMMENT '保质期',
`origin_place` varchar(64) COMMENT '产地',
`detail_html` text COMMENT '商品详情HTML',
PRIMARY KEY (`id`),
UNIQUE KEY `idx_spu` (`spu_code`),
UNIQUE KEY `idx_sku` (`sku_code`),
KEY `idx_category` (`category_id`),
KEY `idx_brand` (`brand_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
特色功能设计:
- 肤质匹配算法:基于用户填写的肤质测试问卷,在商品详情页动态显示匹配度评分
- 成分交叉分析:建立成分知识图谱,自动提示可能引起过敏反应的成分组合
- 虚拟试妆:集成AR SDK实现口红、眼影等彩妆的实时面部渲染
3. 核心功能实现
3.1 商品三级分类体系
采用递归方式实现美妆行业特有的三级分类结构:
java复制// 分类实体类
@Data
public class Category {
private Long id;
private String name;
private Integer level;
private Long parentId;
private Integer sort;
private String icon;
}
// 树形结构构建
public List<Category> buildTree(List<Category> allCategories) {
return allCategories.stream()
.filter(c -> c.getParentId().equals(0L))
.peek(c -> c.setChildren(getChildren(c, allCategories)))
.sorted(Comparator.comparingInt(Category::getSort))
.collect(Collectors.toList());
}
private List<Category> getChildren(Category root, List<Category> all) {
return all.stream()
.filter(c -> c.getParentId().equals(root.getId()))
.peek(c -> {
if (c.getLevel() < 3) {
c.setChildren(getChildren(c, all));
}
})
.sorted(Comparator.comparingInt(Category::getSort))
.collect(Collectors.toList());
}
前端采用Element Plus的Tree组件渲染:
vue复制<el-tree
:data="categoryTree"
node-key="id"
:props="{
label: 'name',
children: 'children'
}"
@node-click="handleNodeClick"
/>
3.2 高并发秒杀方案
针对限量版美妆产品的秒杀场景,采用分级缓存策略:
-
预热阶段:
- 提前将商品库存加载到Redis:
SET seckill:stock:{skuId} 100 - 生成随机秒杀地址:
SET seckill:path:{skuId} {md5}
- 提前将商品库存加载到Redis:
-
秒杀阶段:
java复制public Result seckill(Long skuId, String path, String userId) {
// 验证秒杀路径
String redisPath = redisTemplate.opsForValue().get("seckill:path:" + skuId);
if (!path.equals(redisPath)) {
return Result.fail("非法请求");
}
// 内存标记减少Redis访问
if (localCache.get("seckill:over:" + skuId)) {
return Result.fail("秒杀已结束");
}
// Redis原子减库存
Long stock = redisTemplate.opsForValue().decrement("seckill:stock:" + skuId);
if (stock < 0) {
localCache.put("seckill:over:" + skuId, true);
return Result.fail("库存不足");
}
// 异步创建订单
seckillOrderQueue.add(new SeckillMessage(userId, skuId));
return Result.success("排队中");
}
- 防刷策略:
- 图形验证码+答题验证组合
- 用户行为分析模型识别机器人
- 基于Lua脚本的IP限流
4. 特色功能实现
4.1 虚拟试妆AR集成
采用腾讯云美妆SDK实现实时试妆效果:
vue复制<template>
<div class="try-on-container">
<video ref="camera" autoplay></video>
<canvas ref="canvas"></canvas>
<div class="color-palette">
<div
v-for="color in lipstickColors"
:key="color.value"
:style="{backgroundColor: color.value}"
@click="applyMakeup(color)"
></div>
</div>
</div>
</template>
<script setup>
import { ref, onMounted } from 'vue';
import { TencentCloudMakeup } from 'tc-makeup-sdk';
const camera = ref(null);
const canvas = ref(null);
let makeupSDK = null;
onMounted(async () => {
const stream = await navigator.mediaDevices.getUserMedia({ video: true });
camera.value.srcObject = stream;
makeupSDK = new TencentCloudMakeup({
licenseKey: 'YOUR_LICENSE_KEY',
cameraElement: camera.value,
canvasElement: canvas.value
});
await makeupSDK.init();
});
const applyMakeup = (color) => {
makeupSDK.applyLipstick({
color: color.value,
opacity: 0.8,
glossiness: 0.5
});
};
</script>
4.2 智能推荐系统
基于协同过滤+内容推荐的混合推荐模型:
java复制// 推荐服务实现
@Service
public class RecommendServiceImpl implements RecommendService {
@Autowired
private UserBehaviorMapper behaviorMapper;
@Autowired
private ProductMapper productMapper;
@Override
public List<Product> recommendForUser(Long userId) {
// 1. 获取用户最近行为
List<UserBehavior> behaviors = behaviorMapper.selectRecentBehaviors(userId, 100);
// 2. 协同过滤推荐
List<Long> cfItems = collaborativeFiltering(behaviors);
// 3. 基于内容的推荐
List<Long> cbItems = contentBasedRecommend(behaviors);
// 4. 混合推荐结果
Set<Long> hybridItems = new LinkedHashSet<>();
hybridItems.addAll(cfItems);
hybridItems.addAll(cbItems);
return productMapper.selectBatchIds(new ArrayList<>(hybridItems));
}
private List<Long> collaborativeFiltering(List<UserBehavior> behaviors) {
// 实现基于用户的协同过滤算法
// ...
}
private List<Long> contentBasedRecommend(List<UserBehavior> behaviors) {
// 实现基于商品特征的推荐
// ...
}
}
5. 部署与性能优化
5.1 容器化部署方案
使用Docker Compose编排关键服务:
yaml复制version: '3.8'
services:
mysql:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: ${DB_PASSWORD}
volumes:
- ./mysql/data:/var/lib/mysql
- ./mysql/conf:/etc/mysql/conf.d
ports:
- "3306:3306"
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
interval: 5s
timeout: 10s
retries: 3
redis:
image: redis:6.2
command: redis-server --appendonly yes
volumes:
- ./redis/data:/data
ports:
- "6379:6379"
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 5s
timeout: 10s
retries: 3
app:
build: .
depends_on:
mysql:
condition: service_healthy
redis:
condition: service_healthy
environment:
SPRING_DATASOURCE_URL: jdbc:mysql://mysql:3306/cosmetic?useSSL=false
SPRING_REDIS_HOST: redis
ports:
- "8080:8080"
5.2 前端性能优化
- 代码分割:
javascript复制// vite.config.js
export default defineConfig({
build: {
rollupOptions: {
output: {
manualChunks: {
element: ['element-plus'],
charts: ['echarts'],
ar: ['@tencentcloud/tc-makeup-sdk']
}
}
}
}
})
- 图片优化策略:
- 使用WebP格式替代PNG/JPG
- 实现懒加载:
vue复制<img
v-lazy="product.image"
:alt="product.name"
class="product-image"
/>
- API请求优化:
- 封装统一的请求层
javascript复制// api/request.js
import axios from 'axios';
const service = axios.create({
baseURL: import.meta.env.VITE_API_BASE_URL,
timeout: 10000,
withCredentials: true
});
// 请求拦截器
service.interceptors.request.use(config => {
config.headers['X-Token'] = getToken();
return config;
});
// 响应拦截器
service.interceptors.response.use(
response => {
const res = response.data;
if (res.code !== 200) {
showError(res.message);
return Promise.reject(new Error(res.message));
}
return res.data;
},
error => {
handleError(error);
return Promise.reject(error);
}
);
export default service;
6. 安全防护措施
6.1 常见Web安全防护
- XSS防御:
java复制// SpringBoot配置HttpFirewall
@Bean
public HttpFirewall strictHttpFirewall() {
StrictHttpFirewall firewall = new StrictHttpFirewall();
firewall.setAllowedHeaderNames(header -> !header.contains("script"));
firewall.setAllowedHeaderValues(header -> !header.contains("script"));
firewall.setAllowedParameterNames(param -> !param.contains("script"));
return firewall;
}
- CSRF防护:
javascript复制// axios全局配置
service.interceptors.request.use(config => {
config.headers['X-CSRF-TOKEN'] = getCsrfToken();
return config;
});
- SQL注入防护:
- 强制使用MyBatis参数化查询
- 安装Druid Filter监控可疑SQL
6.2 业务安全设计
- 优惠券防刷:
java复制public Result claimCoupon(Long couponId, Long userId) {
// 1. 校验领取资格
if (redisTemplate.opsForValue().increment("coupon:limit:"+userId) > 5) {
return Result.fail("领取次数超限");
}
// 2. 分布式锁防并发
String lockKey = "coupon:lock:" + couponId + ":" + userId;
boolean locked = redisTemplate.opsForValue().setIfAbsent(lockKey, "1", 10, TimeUnit.SECONDS);
if (!locked) {
return Result.fail("操作太频繁");
}
try {
// 3. 扣减库存
if (couponMapper.reduceStock(couponId) <= 0) {
return Result.fail("优惠券已领完");
}
// 4. 发放优惠券
userCouponMapper.insert(new UserCoupon(userId, couponId));
return Result.success("领取成功");
} finally {
redisTemplate.delete(lockKey);
}
}
- 支付风控策略:
- 设备指纹识别
- 交易行为建模
- 异地登录检测
7. 监控与运维
7.1 全链路监控体系
- SpringBoot Actuator配置:
yaml复制management:
endpoints:
web:
exposure:
include: "*"
endpoint:
health:
show-details: always
metrics:
enabled: true
metrics:
export:
prometheus:
enabled: true
- 自定义业务指标:
java复制@RestController
public class OrderController {
private final Counter orderCounter;
public OrderController(MeterRegistry registry) {
this.orderCounter = Counter.builder("order.create.count")
.description("订单创建数量")
.tag("type", "normal")
.register(registry);
}
@PostMapping("/order")
public Result createOrder(@RequestBody OrderDTO dto) {
orderCounter.increment();
// 订单创建逻辑
}
}
7.2 日志收集方案
采用ELK Stack处理分布式日志:
yaml复制# filebeat.yml配置
filebeat.inputs:
- type: log
paths:
- /var/log/app/*.log
json.keys_under_root: true
json.add_error_key: true
output.logstash:
hosts: ["logstash:5044"]
java复制// 日志切面示例
@Aspect
@Component
@Slf4j
public class LogAspect {
@Around("execution(* com..controller.*.*(..))")
public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable {
long start = System.currentTimeMillis();
String method = joinPoint.getSignature().toShortString();
try {
Object result = joinPoint.proceed();
log.info("{} | success | {}ms | params: {}",
method,
System.currentTimeMillis() - start,
JsonUtils.toJson(joinPoint.getArgs()));
return result;
} catch (Exception e) {
log.error("{} | failed | {}ms | error: {}",
method,
System.currentTimeMillis() - start,
e.getMessage());
throw e;
}
}
}
8. 项目演进路线
8.1 技术债管理
-
待优化项:
- 商品搜索目前使用LIKE查询,计划迁移到Elasticsearch
- 支付回调处理需要增加幂等性保障
- 优惠券系统需要支持更复杂的发放规则
-
迭代计划:
mermaid复制gantt
title 美妆商城迭代计划
dateFormat YYYY-MM-DD
section 核心功能
会员体系 :done, des1, 2023-01-01,2023-01-15
商品管理 :done, des2, 2023-01-16,2023-02-01
订单流程 :done, des3, 2023-02-02,2023-02-20
section 进阶功能
智能推荐 :active, des4, 2023-02-21,2023-03-10
虚拟试妆 : des5, 2023-03-11,2023-04-01
直播带货 : des6, 2023-04-02,2023-04-20
8.2 团队协作建议
-
代码规范:
- 前端遵循Vue官方风格指南
- 后端采用Alibaba Java Coding Guidelines
- 接口文档使用Swagger + YAPI管理
-
Git工作流:
bash复制# 功能开发流程
git checkout -b feature/xxx
git add .
git commit -m "feat: 添加商品分类功能"
git push origin feature/xxx
# 创建Merge Request进行代码评审
- CI/CD流程:
yaml复制# .gitlab-ci.yml示例
stages:
- test
- build
- deploy
unit-test:
stage: test
script:
- mvn test
build-frontend:
stage: build
script:
- cd frontend
- npm install
- npm run build
artifacts:
paths:
- frontend/dist
deploy-prod:
stage: deploy
script:
- scp -r backend/target/*.jar prod-server:/app
- scp -r frontend/dist prod-server:/nginx/html
only:
- master
