1. 项目概述
这个基于SpringBoot2+Vue3的游戏销售平台是我在研究生期间完成的一个完整商业级项目,前后耗时3个月开发完成。作为一个全栈项目,它采用了目前企业级开发中最主流的技术栈组合,后端使用SpringBoot2框架搭建RESTful API服务,前端基于Vue3实现响应式界面,数据持久层采用MyBatis-Plus简化数据库操作,MySQL8.0作为关系型数据库存储核心业务数据。
在实际开发过程中,我发现很多同学在做类似项目时容易陷入两个极端:要么过度关注UI效果而忽视业务逻辑的严谨性,要么只注重后端实现导致用户体验糟糕。这个项目的一个显著特点是前后端完全分离,通过明确的接口规范进行通信,既保证了系统的可维护性,又能快速迭代前端界面。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 技术架构解析
2.1 后端技术栈选型
选择SpringBoot2作为后端框架主要基于以下几个实际考量:
- 自动配置特性大幅减少了XML配置,我在开发时通过@SpringBootApplication一个注解就完成了90%的基础配置
- 内嵌Tomcat服务器使得部署异常简单,只需打包成jar即可运行
- 与MyBatis-Plus的完美集成让数据库操作效率提升50%以上
数据库选用MySQL8.0而非5.7版本,主要看中其:
- 窗口函数对数据分析报表的支持
- JSON字段类型便于存储游戏动态属性
- 原子DDL操作在表结构变更时更安全
实际开发中发现的一个坑:MySQL8.0默认的身份验证插件从mysql_native_password改为了caching_sha2_password,如果客户端驱动不兼容会导致连接失败。解决方案是在创建用户时显式指定插件:CREATE USER 'game'@'%' IDENTIFIED WITH mysql_native_password BY 'password';
2.2 前端技术方案
Vue3相比Vue2有几个对项目特别有利的改进:
- Composition API让代码组织更灵活,特别是游戏筛选这类复杂交互逻辑
- 更好的TypeScript支持,我在开发时能提前发现80%的类型错误
- 性能提升显著,在游戏列表页这种数据量大的场景下渲染速度快了约30%
项目中使用到的关键前端库:
- Element Plus:构建管理后台的UI基础
- Axios:处理HTTP请求,我封装了统一的拦截器处理JWT认证
- Vue Router:实现前端路由,配合导航守卫做权限控制
- Pinia:状态管理,替代Vuex的更轻量方案
3. 核心功能实现
3.1 用户认证与授权
采用JWT(JSON Web Token)实现无状态认证,具体流程:
- 用户登录成功后,后端生成包含用户ID和角色的JWT
- 前端将JWT存储在localStorage中(实际项目应考虑HttpOnly Cookie)
- 每次请求通过Authorization头携带JWT
- 后端通过过滤器验证JWT有效性
安全增强措施:
- 设置合理的过期时间(如2小时)
- 使用HTTPS传输防止中间人攻击
- 敏感操作需要二次验证
java复制// JWT生成示例代码
public String generateToken(UserDetails userDetails) {
Map<String, Object> claims = new HashMap<>();
claims.put("roles", userDetails.getAuthorities().stream()
.map(GrantedAuthority::getAuthority)
.collect(Collectors.toList()));
return Jwts.builder()
.setClaims(claims)
.setSubject(userDetails.getUsername())
.setIssuedAt(new Date(System.currentTimeMillis()))
.setExpiration(new Date(System.currentTimeMillis() + 1000 * 60 * 60 * 2)) // 2小时过期
.signWith(SignatureAlgorithm.HS256, secretKey)
.compact();
}
3.2 游戏商品管理
采用领域驱动设计(DDD)的思想组织代码结构:
- GameAggregate:聚合根,包含游戏基本信息、价格、库存等
- GameRepository:仓储接口,定义数据访问契约
- GameService:应用服务,处理业务逻辑
价格策略设计:
- 基础价格存储在game表price字段
- 折扣信息单独维护在promotion表
- 最终价格通过策略模式计算得出
java复制public interface PriceStrategy {
BigDecimal calculatePrice(BigDecimal originalPrice);
}
@Service
public class DiscountStrategy implements PriceStrategy {
@Override
public BigDecimal calculatePrice(BigDecimal originalPrice) {
// 获取当前有效的折扣率
BigDecimal discountRate = getCurrentDiscountRate();
return originalPrice.multiply(discountRate);
}
}
4. 订单系统实现
4.1 订单状态机设计
使用状态模式管理订单生命周期:
mermaid复制stateDiagram
[*] --> PENDING
PENDING --> PAID: 支付成功
PENDING --> CANCELLED: 用户取消
PENDING --> EXPIRED: 超时未支付
PAID --> REFUNDED: 申请退款
对应的Java实现:
java复制public interface OrderState {
void pay(Order order);
void cancel(Order order);
void refund(Order order);
}
public class PaidState implements OrderState {
@Override
public void refund(Order order) {
// 退款处理逻辑
order.setState(new RefundedState());
}
}
4.2 支付集成方案
支持多种支付方式接入:
- 支付宝沙箱环境(开发测试用)
- 微信支付Native API
- 模拟支付(用于演示)
支付回调处理要点:
- 验证签名防止伪造请求
- 处理幂等性问题(相同通知可能多次触发)
- 异步更新订单状态
5. 性能优化实践
5.1 数据库优化
-
索引策略:
- 用户表的username和email字段添加唯一索引
- 游戏表的category和price字段添加复合索引
- 订单表的user_id和order_time字段添加索引
-
查询优化:
- 分页查询使用limit配合order by保证稳定性
- 关联查询控制在3表以内,复杂查询走冗余字段
-
缓存应用:
- Redis缓存热门游戏信息
- 本地缓存(Caffeine)存储不常变的配置数据
5.2 前端性能提升
- 图片懒加载:游戏封面图在进入视口时再加载
- 组件异步加载:路由级代码分割
- 数据预取:用户hover到详情链接时预加载数据
6. 部署与监控
6.1 容器化部署
Docker Compose编排方案:
yaml复制version: '3'
services:
mysql:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: root
volumes:
- mysql_data:/var/lib/mysql
backend:
build: ./backend
ports:
- "8080:8080"
depends_on:
- mysql
frontend:
build: ./frontend
ports:
- "80:80"
6.2 监控方案
- Spring Boot Actuator暴露健康检查端点
- Prometheus收集指标数据
- Grafana展示监控仪表盘
- ELK日志收集系统
7. 开发经验总结
- 接口设计要前后端协同,使用Swagger或YAPI维护文档
- 复杂状态管理优先考虑状态机模式
- 分页查询一定要考虑性能,避免全表扫描
- 支付集成要处理好异步通知和订单状态同步
踩过的一个典型坑:初期没有设计好游戏与分类的多对多关系,导致后期需要重构数据库。建议在设计阶段就考虑好实体关系,使用中间表处理多对多关联。
项目后续可扩展方向:
- 引入推荐算法提升转化率
- 增加游戏试玩功能
- 开发商家入驻系统
- 实现多语言支持
