这个基于Spring Boot的庆祝生日商城系统是一个完整的电子商务解决方案,专为生日庆祝场景设计。作为一名有10年开发经验的Java全栈工程师,我经常被问到如何从零开始构建一个完整的电商系统。这个项目不仅包含了商城的基本功能,还针对生日场景做了特殊设计,比如礼物推荐、贺卡定制等特色功能。
系统采用目前主流的Spring Boot+Vue前后端分离架构,后端使用MyBatis Plus作为ORM框架,数据库选用MySQL。这种技术组合既保证了系统的稳定性和性能,又能快速迭代开发。我在项目中特别注重代码的可维护性和扩展性,采用了清晰的分层架构和模块化设计。
系统采用标准的MVC设计模式,但根据现代Web开发的最佳实践做了优化:
视图层(View):使用Vue.js构建响应式前端界面,通过axios与后端API交互。我特别设计了组件化的前端架构,将页面拆分为可复用的组件,比如商品卡片、购物车组件等。
控制层(Controller):Spring Boot的@RestController处理HTTP请求,我在这里做了统一的异常处理和日志记录。每个API都遵循RESTful规范,返回标准化的JSON数据。
服务层(Service):业务逻辑的核心所在。我采用了领域驱动设计(DDD)的思想,将复杂的业务逻辑封装在服务层。例如,订单服务处理下单、支付、退款等完整流程。
数据访问层(DAO):使用MyBatis Plus简化数据库操作。我特别设计了通用的BaseMapper和BaseService,减少了大量重复的CRUD代码。
后端框架:Spring Boot 2.7.x
前端框架:Vue 3 + Element Plus
数据库:MySQL 8.0
ORM框架:MyBatis Plus 3.5.x
系统采用JWT(JSON Web Token)实现无状态认证,这是我经过多次项目验证的可靠方案:
java复制// JWT工具类核心代码
public class JwtUtil {
private static final String SECRET = "your-secret-key";
private static final long EXPIRATION = 86400000L; // 24小时
public static String generateToken(UserDetails userDetails) {
return Jwts.builder()
.setSubject(userDetails.getUsername())
.setIssuedAt(new Date())
.setExpiration(new Date(System.currentTimeMillis() + EXPIRATION))
.signWith(SignatureAlgorithm.HS512, SECRET)
.compact();
}
public static String getUsernameFromToken(String token) {
return Jwts.parser()
.setSigningKey(SECRET)
.parseClaimsJws(token)
.getBody()
.getSubject();
}
}
安全注意事项:
针对生日场景,商品系统做了特殊设计:
商品分类:
商品属性扩展:
java复制public class Product {
private Long id;
private String name;
private BigDecimal price;
// 生日特有属性
private String suitableAge;
private String suitableGender;
private String giftOccasion;
private boolean canCustomize; // 是否支持定制
private String customizeOptions; // 定制选项JSON
}
实现技巧:
订单系统是电商的核心,我采用了状态机模式管理订单生命周期:
java复制public enum OrderStatus {
UNPAID, // 待支付
PAID, // 已支付
SHIPPED, // 已发货
COMPLETED, // 已完成
CANCELLED, // 已取消
REFUNDED // 已退款
}
// 状态转换规则
public class OrderStateMachine {
private static final Map<OrderStatus, List<OrderStatus>> TRANSITIONS = Map.of(
UNPAID, List.of(PAID, CANCELLED),
PAID, List.of(SHIPPED, REFUNDED),
SHIPPED, List.of(COMPLETED, REFUNDED)
);
public static boolean canTransition(OrderStatus from, OrderStatus to) {
return TRANSITIONS.getOrDefault(from, List.of()).contains(to);
}
}
关键设计点:
用户表(users)
sql复制CREATE TABLE `users` (
`id` bigint NOT NULL AUTO_INCREMENT,
`username` varchar(50) NOT NULL,
`password` varchar(100) NOT NULL,
`email` varchar(100) NOT NULL,
`phone` varchar(20) DEFAULT NULL,
`avatar` varchar(255) DEFAULT NULL,
`status` tinyint DEFAULT '1' COMMENT '1-正常,0-禁用',
`created_at` datetime DEFAULT CURRENT_TIMESTAMP,
`updated_at` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `idx_username` (`username`),
UNIQUE KEY `idx_email` (`email`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
商品表(products)
sql复制CREATE TABLE `products` (
`id` bigint NOT NULL AUTO_INCREMENT,
`name` varchar(100) NOT NULL,
`description` text,
`price` decimal(10,2) NOT NULL,
`stock` int NOT NULL DEFAULT '0',
`category_id` bigint NOT NULL,
`main_image` varchar(255) DEFAULT NULL,
`detail_images` text COMMENT 'JSON数组',
`suitable_age` varchar(50) DEFAULT NULL,
`suitable_gender` varchar(10) DEFAULT NULL,
`sales` int DEFAULT '0',
`status` tinyint DEFAULT '1' COMMENT '1-上架,0-下架',
`created_at` datetime DEFAULT CURRENT_TIMESTAMP,
`updated_at` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `idx_category` (`category_id`),
KEY `idx_sales` (`sales`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
联合索引设计:对高频查询条件建立合适的联合索引
sql复制ALTER TABLE orders ADD INDEX idx_user_status (user_id, status);
覆盖索引:确保查询可以通过索引直接获取数据,避免回表
sql复制-- 好的覆盖索引查询
SELECT id, name FROM products WHERE category_id = 5;
-- 需要回表的查询
SELECT * FROM products WHERE category_id = 5;
避免索引失效:
后端开发环境:
前端开发环境:
服务器配置建议:
部署步骤:
后端打包:
bash复制mvn clean package -DskipTests
前端构建:
bash复制npm run build
使用Docker部署(推荐):
dockerfile复制# Dockerfile示例
FROM openjdk:11-jre
COPY target/*.jar app.jar
ENTRYPOINT ["java","-jar","/app.jar"]
数据库初始化:
bash复制mysql -u root -p < schema.sql
JVM调优:
bash复制java -jar -Xms512m -Xmx1024m -XX:+UseG1GC app.jar
数据库连接池配置:
yaml复制spring:
datasource:
hikari:
maximum-pool-size: 20
minimum-idle: 5
connection-timeout: 30000
idle-timeout: 600000
max-lifetime: 1800000
缓存策略:
问题1:MyBatis Plus查询结果与预期不符
解决方案:
问题2:Vue组件间通信混乱
解决方案:
问题1:数据库连接池耗尽
排查步骤:
问题2:JVM内存溢出
排查步骤:
前端性能优化:
后端性能优化:
数据库优化:
社交化功能:
个性化推荐:
营销功能:
微服务化改造:
容器化进阶:
监控体系完善:
在实际开发过程中,我特别注重代码的可读性和可维护性。每个重要方法都添加了详细的注释,关键业务逻辑有单元测试覆盖。项目采用Git进行版本控制,按照功能分支工作流进行协作开发。对于团队协作,我建议使用标准的代码规范检查工具如Checkstyle和SonarQube,确保代码质量一致。