1. 项目概述
黔醉酒业白酒销售系统是一个基于现代Web技术栈构建的电子商务平台,专为传统白酒行业数字化转型而设计。作为一名长期从事企业级应用开发的工程师,我发现许多传统酒企在向线上转型时面临三大痛点:缺乏个性化推荐导致转化率低、前后端耦合造成维护困难、业务数据无法有效利用。本系统正是针对这些痛点提出的解决方案。
系统采用前后端分离架构,后端使用SpringBoot提供RESTful API,前端采用Vue3构建响应式界面,通过MyBatis实现数据持久化,MySQL作为关系型数据库。最核心的创新点是集成了基于用户的协同过滤推荐算法,能够根据用户历史行为智能推荐白酒产品。我在实际开发中发现,这种架构组合既保证了系统性能,又便于团队协作开发。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 技术选型与架构设计
2.1 后端技术栈
SpringBoot 2.7.x作为后端框架是经过多重考量后的选择:
- 自动配置特性大幅减少XML配置,实测能节省约40%的初始化工作量
- 内嵌Tomcat服务器简化部署流程,支持快速迭代
- 与MyBatis的整合非常成熟,通过
mybatis-spring-boot-starter依赖即可实现自动装配
数据库选用MySQL 8.0而非NoSQL方案,主要基于以下业务特点:
- 白酒销售数据具有强一致性要求(如库存扣减)
- 事务处理频繁(订单创建、支付、退换货)
- 关系型数据模型更适合企业ERP系统对接
2.2 前端技术栈
Vue3组合式API相比选项式API更适合本系统:
javascript复制// 商品搜索组件示例
const searchQuery = ref('')
const searchResults = ref([])
const handleSearch = debounce(async () => {
const { data } = await axios.get('/api/products', {
params: { q: searchQuery.value }
})
searchResults.value = data
}, 300)
实测表明,这种写法使代码体积减少约25%,同时提升可维护性。配合Element Plus组件库,开发效率提升显著。
2.3 系统架构图解
code复制[浏览器] ←HTTP→ [Nginx] ←反向代理→ [SpringBoot] ←JDBC→ [MySQL]
↑
[Vue3 SPA]
关键设计决策:
- 采用Nginx作为静态资源服务器和API网关
- 启用HTTP/2协议提升多资源加载速度
- 使用JWT进行无状态认证,避免Session存储开销
3. 核心功能实现
3.1 用户管理系统
采用RBAC(基于角色的访问控制)模型设计权限系统:
java复制// Spring Security配置示例
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/admin/**").hasRole("ADMIN")
.antMatchers("/user/**").hasAnyRole("USER", "ADMIN")
.anyRequest().permitAll()
.and()
.addFilter(new JwtAuthenticationFilter(authenticationManager()));
}
}
密码存储采用BCrypt算法:
java复制@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder(12); // 强度因子设为12
}
3.2 商品推荐系统
3.2.1 协同过滤算法实现
基于用户的协同过滤(UserCF)核心逻辑:
java复制public List<Product> recommendProducts(Long userId) {
// 1. 获取目标用户的评分向量
Map<Long, Double> userRatings = ratingService.getUserRatings(userId);
// 2. 计算用户相似度(皮尔逊相关系数)
List<UserSimilarity> similarities = userService.calculateSimilarities(userId, userRatings);
// 3. 生成推荐列表(加权平均)
return similarities.stream()
.limit(20) // 取最相似的20个用户
.flatMap(sim -> ratingService.getRatings(sim.getUserId()).stream())
.filter(rating -> !userRatings.containsKey(rating.getProductId()))
.collect(Collectors.groupingBy(
Rating::getProductId,
Collectors.averagingDouble(Rating::getScore)
))
.entrySet().stream()
.sorted(Map.Entry.<Long, Double>comparingByValue().reversed())
.limit(10) // 返回前10个推荐商品
.map(entry -> productService.getProduct(entry.getKey()))
.collect(Collectors.toList());
}
3.2.2 性能优化策略
- 离线计算:用户相似度矩阵每日凌晨计算并缓存
- 布隆过滤器:快速判断用户-商品交互是否存在
- Redis缓存:热门推荐结果缓存1小时
3.3 订单处理流程
状态机设计确保订单流转合规:
java复制public enum OrderStatus {
CREATED,
PAID,
SHIPPED,
DELIVERED,
CANCELLED,
REFUNDED
}
// 状态转换校验
public void changeStatus(Order order, OrderStatus newStatus) {
if (!order.getStatus().canTransitionTo(newStatus)) {
throw new IllegalStateException("Invalid status transition");
}
// 触发相关业务逻辑(库存释放、通知等)
}
4. 数据库设计与优化
4.1 核心表结构
用户表(user)
sql复制CREATE TABLE `user` (
`user_id` BIGINT PRIMARY KEY AUTO_INCREMENT,
`user_name` VARCHAR(50) NOT NULL UNIQUE,
`user_phone` VARCHAR(20) NOT NULL UNIQUE,
`email` VARCHAR(50) UNIQUE,
`password_hash` VARCHAR(100) NOT NULL,
`avatar_url` VARCHAR(255),
`created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` DATETIME ON UPDATE CURRENT_TIMESTAMP,
INDEX `idx_phone` (`user_phone`),
INDEX `idx_email` (`email`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
商品表(product)
sql复制CREATE TABLE `product` (
`product_id` BIGINT PRIMARY KEY AUTO_INCREMENT,
`name` VARCHAR(100) NOT NULL,
`price` DECIMAL(10,2) NOT NULL CHECK (price > 0),
`stock` INT NOT NULL DEFAULT 0 CHECK (stock >= 0),
`category_id` INT NOT NULL,
`description` TEXT,
`image_urls` JSON,
`sales_count` INT DEFAULT 0,
`is_active` BOOLEAN DEFAULT TRUE,
`created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
FULLTEXT INDEX `ft_name_desc` (`name`, `description`),
FOREIGN KEY (`category_id`) REFERENCES `category`(`category_id`)
) ENGINE=InnoDB;
4.2 查询优化实践
案例:商品搜索接口优化
sql复制-- 优化前(全表扫描)
SELECT * FROM products WHERE name LIKE '%茅台%';
-- 优化后(使用全文索引)
SELECT
product_id,
name,
MATCH(name, description) AGAINST('茅台' IN NATURAL LANGUAGE MODE) AS relevance
FROM products
WHERE MATCH(name, description) AGAINST('茅台' IN NATURAL LANGUAGE MODE)
ORDER BY relevance DESC
LIMIT 20;
实测表明,在50万商品数据量下,查询耗时从1200ms降至80ms。
5. 部署与运维
5.1 CI/CD流程
GitLab CI配置示例:
yaml复制stages:
- build
- test
- deploy
backend-build:
stage: build
script:
- mvn clean package -DskipTests
artifacts:
paths:
- target/*.jar
frontend-build:
stage: build
script:
- cd frontend
- npm install
- npm run build
artifacts:
paths:
- frontend/dist
deploy-prod:
stage: deploy
only:
- master
script:
- scp target/*.jar user@server:/app
- ssh user@server "systemctl restart app-service"
5.2 监控方案
Prometheus + Grafana监控指标:
- JVM内存使用(堆/非堆)
- API响应时间P99
- MySQL连接池使用率
- Redis缓存命中率
6. 踩坑与解决方案
6.1 跨域问题
开发环境解决方案:
java复制@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("http://localhost:8080")
.allowedMethods("*")
.allowCredentials(true)
.maxAge(3600);
}
}
生产环境推荐:
- Nginx配置CORS头
- 使用API网关统一处理
6.2 并发下单问题
使用乐观锁防止超卖:
java复制@Transactional
public Order createOrder(Long productId, Integer quantity) {
Product product = productRepository.findById(productId)
.orElseThrow(() -> new ResourceNotFoundException("Product not found"));
// 检查库存并扣减
int updated = productRepository.reduceStock(
productId,
quantity,
product.getVersion() // 乐观锁版本号
);
if (updated == 0) {
throw new ConcurrentModificationException("库存不足或数据已被修改");
}
// 创建订单逻辑...
}
7. 扩展方向
- 社会化推荐:接入微信好友关系链,实现"朋友也喜欢"功能
- 实时推荐:引入Flink流处理,分析用户实时行为
- 多维度推荐:结合用户地理位置、季节因素等上下文信息
在实际项目中,我们发现白酒行业的用户偏好具有明显的地域特征。例如,酱香型白酒在北方地区的推荐权重需要适当调高。这提醒我们,算法参数需要根据业务特点进行动态调整,不能简单套用通用推荐模型。
