1. 项目概述
这个基于SpringBoot的商城微信小程序系统是一个完整的电商解决方案,旨在为用户提供便捷的购物体验,同时为管理员提供高效的后台管理功能。系统采用前后端分离架构,前端使用微信小程序开发,后端基于SpringBoot框架构建,数据库采用MySQL存储数据。
我在实际开发过程中发现,这种架构组合特别适合中小型电商项目。SpringBoot的快速开发特性让我们能在短时间内搭建起稳定的后端服务,而微信小程序的轻量级特性则提供了优秀的用户体验。系统分为普通用户和管理员两大角色,涵盖了从商品展示到订单管理的完整电商流程。
2. 系统架构设计
2.1 技术选型解析
后端技术栈:
- SpringBoot 2.7.x:作为核心框架,提供自动配置和快速启动能力
- MyBatis-Plus 3.5.x:简化数据库操作,内置常用CRUD方法
- Redis 6.x:用于缓存热点数据和会话管理
- JWT:实现安全的用户认证机制
前端技术栈:
- 微信小程序原生开发:使用WXML、WXSS和JavaScript
- Vant Weapp组件库:提供丰富的UI组件
- ECharts for WeChat:用于数据可视化展示
数据库:
- MySQL 8.0:主数据库,采用InnoDB引擎
- 配置了读写分离,主库负责写操作,从库负责读操作
选择这些技术的主要考虑是:
- SpringBoot的"约定优于配置"原则大大减少了XML配置
- MyBatis-Plus的ActiveRecord模式简化了DAO层开发
- 微信小程序无需安装的特性提供了更好的用户体验
- MySQL的成熟稳定性和社区支持
2.2 系统分层架构
系统采用经典的三层架构:
code复制表现层(微信小程序)
↓
业务逻辑层(SpringBoot)
↓
数据访问层(MyBatis-Plus)
↓
数据存储层(MySQL)
每层职责明确:
- 表现层:处理用户交互和界面展示
- 业务逻辑层:实现核心业务规则和流程
- 数据访问层:封装数据库操作
- 数据存储层:持久化业务数据
这种分层设计使得系统具有很好的可维护性和扩展性。我在开发中发现,清晰的层次划分让团队协作更加高效,后端开发可以专注于业务逻辑,而前端开发可以独立进行界面优化。
3. 核心功能实现
3.1 用户模块
用户模块实现了完整的注册登录流程:
java复制// 用户注册逻辑示例
@PostMapping("/register")
public Result register(@RequestBody UserDTO userDTO) {
// 验证手机号是否已注册
if(userService.checkMobileExist(userDTO.getMobile())){
return Result.fail("手机号已注册");
}
// 密码加密存储
String encryptedPwd = passwordEncoder.encode(userDTO.getPassword());
// 构建用户实体
User user = User.builder()
.username(userDTO.getUsername())
.mobile(userDTO.getMobile())
.password(encryptedPwd)
.build();
// 保存用户
userService.save(user);
return Result.success();
}
关键点:
- 采用BCryptPasswordEncoder进行密码加密,避免明文存储
- 注册时进行手机号唯一性校验
- 使用DTO对象接收参数,与实体类分离
- 返回统一的Result格式,便于前端处理
3.2 商品模块
商品模块实现了商品分类和搜索功能:
java复制// 商品搜索实现
public Page<Product> searchProducts(ProductQuery query, Pageable pageable) {
QueryWrapper<Product> wrapper = new QueryWrapper<>();
if(StringUtils.isNotBlank(query.getKeyword())){
wrapper.like("title", query.getKeyword())
.or()
.like("description", query.getKeyword());
}
if(query.getCategoryId() != null){
wrapper.eq("category_id", query.getCategoryId());
}
if(query.getMinPrice() != null){
wrapper.ge("price", query.getMinPrice());
}
if(query.getMaxPrice() != null){
wrapper.le("price", query.getMaxPrice());
}
return productMapper.selectPage(pageable, wrapper);
}
优化技巧:
- 使用MyBatis-Plus的QueryWrapper构建动态查询条件
- 支持多条件组合搜索
- 分页查询减轻数据库压力
- 添加商品缓存,减少数据库访问
3.3 购物车模块
购物车实现采用Redis存储,提高性能:
java复制// 购物车服务实现
@Service
public class CartServiceImpl implements CartService {
@Autowired
private RedisTemplate<String, Object> redisTemplate;
private String getCartKey(Long userId) {
return "cart:" + userId;
}
@Override
public void addToCart(Long userId, CartItem item) {
String key = getCartKey(userId);
redisTemplate.opsForHash().put(key,
item.getProductId().toString(),
JSON.toJSONString(item));
}
@Override
public List<CartItem> getCartItems(Long userId) {
String key = getCartKey(userId);
List<Object> values = redisTemplate.opsForHash().values(key);
return values.stream()
.map(v -> JSON.parseObject(v.toString(), CartItem.class))
.collect(Collectors.toList());
}
}
设计考虑:
- 使用Redis Hash结构存储购物车,key为用户ID
- 每个购物车项存储为JSON字符串
- 设置合理的过期时间(如30天)
- 定期清理长时间未更新的购物车数据
4. 数据库设计与优化
4.1 核心表结构
商品表(products):
sql复制CREATE TABLE `products` (
`id` bigint NOT NULL AUTO_INCREMENT,
`title` varchar(100) NOT NULL COMMENT '商品标题',
`price` decimal(10,2) NOT NULL COMMENT '售价',
`original_price` decimal(10,2) DEFAULT NULL COMMENT '原价',
`stock` int NOT NULL DEFAULT '0' COMMENT '库存',
`category_id` bigint NOT NULL COMMENT '分类ID',
`main_image` varchar(255) DEFAULT NULL COMMENT '主图',
`detail` text COMMENT '商品详情',
`sales` int DEFAULT '0' COMMENT '销量',
`status` tinyint DEFAULT '1' COMMENT '状态:1-上架 0-下架',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `idx_category` (`category_id`),
KEY `idx_status` (`status`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
订单表(orders):
sql复制CREATE TABLE `orders` (
`id` bigint NOT NULL AUTO_INCREMENT,
`order_no` varchar(32) NOT NULL COMMENT '订单编号',
`user_id` bigint NOT NULL COMMENT '用户ID',
`total_amount` decimal(10,2) NOT NULL COMMENT '订单总额',
`payment_amount` decimal(10,2) NOT NULL COMMENT '实付金额',
`payment_type` tinyint DEFAULT NULL COMMENT '支付方式',
`status` tinyint NOT NULL DEFAULT '0' COMMENT '状态:0-待支付 1-已支付 2-已发货 3-已完成 4-已关闭',
`shipping_address` varchar(500) NOT NULL COMMENT '收货地址',
`receiver_name` varchar(50) NOT NULL COMMENT '收货人',
`receiver_phone` varchar(20) NOT NULL COMMENT '联系电话',
`remark` varchar(500) DEFAULT NULL COMMENT '备注',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `uk_order_no` (`order_no`),
KEY `idx_user_id` (`user_id`),
KEY `idx_create_time` (`create_time`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
4.2 性能优化实践
-
索引优化:
- 为常用查询条件添加合适索引
- 避免过度索引,定期分析索引使用情况
- 使用覆盖索引减少回表操作
-
SQL优化:
- 避免SELECT *,只查询需要的字段
- 使用JOIN替代子查询
- 大数据量分页使用延迟关联
-
缓存策略:
- 商品详情使用Redis缓存
- 分类数据使用本地缓存
- 热点数据预加载
5. 微信小程序实现
5.1 小程序页面结构
code复制pages/
|- index/ # 首页
|- category/ # 分类页
|- cart/ # 购物车
|- my/ # 个人中心
|- product/ # 商品详情
|- order/ # 订单相关
5.2 关键实现代码
商品列表页:
javascript复制Page({
data: {
products: [],
loading: false,
page: 1,
hasMore: true
},
onLoad() {
this.loadProducts()
},
loadProducts() {
if(this.data.loading || !this.data.hasMore) return
this.setData({loading: true})
wx.request({
url: 'https://api.example.com/products',
data: {
page: this.data.page,
size: 10
},
success: (res) => {
const newProducts = res.data.list
this.setData({
products: [...this.data.products, ...newProducts],
hasMore: res.data.hasMore,
page: this.data.page + 1
})
},
complete: () => {
this.setData({loading: false})
}
})
},
onReachBottom() {
this.loadProducts()
}
})
购物车实现:
javascript复制// 添加购物车
addToCart(product) {
wx.showLoading({title: '添加中...'})
wx.request({
url: 'https://api.example.com/cart/add',
method: 'POST',
data: {
productId: product.id,
quantity: 1
},
success: () => {
wx.showToast({title: '添加成功'})
this.updateCartBadge()
},
complete: () => {
wx.hideLoading()
}
})
},
// 更新购物车角标
updateCartBadge() {
wx.request({
url: 'https://api.example.com/cart/count',
success: (res) => {
const count = res.data
if(count > 0) {
wx.setTabBarBadge({
index: 2,
text: count.toString()
})
} else {
wx.removeTabBarBadge({index: 2})
}
}
})
}
6. 部署与运维
6.1 服务器环境
- 操作系统:CentOS 7.9
- JDK:OpenJDK 11
- 应用服务器:Tomcat 9
- 数据库:MySQL 8.0
- 缓存:Redis 6.2
6.2 部署流程
- 后端部署:
bash复制# 打包
mvn clean package -DskipTests
# 上传jar包到服务器
scp target/mall-weapp.jar user@server:/data/app/
# 启动服务
nohup java -jar mall-weapp.jar --spring.profiles.active=prod > app.log 2>&1 &
- 前端部署:
- 使用微信开发者工具上传小程序代码
- 提交微信审核
- 审核通过后发布
6.3 监控与日志
- 使用Spring Boot Actuator暴露健康检查端点
- 配置Logback日志,按天归档
- 使用ELK收集和分析日志
- 配置Prometheus监控JVM和系统指标
7. 项目总结与经验分享
在开发这个商城微信小程序系统的过程中,我积累了一些宝贵的经验:
-
微信登录优化:
- 使用微信官方提供的登录流程
- 服务端保存unionid作为用户唯一标识
- 合理设置session_key的有效期
-
支付流程:
- 严格按照微信支付文档实现
- 处理各种支付状态回调
- 记录完整的支付日志便于排查问题
-
性能优化:
- 小程序端使用图片懒加载
- 接口数据按需返回
- 使用WebP格式减小图片体积
-
错误处理:
- 统一异常处理机制
- 友好的错误提示
- 错误日志记录详细上下文
-
安全考虑:
- 接口参数校验
- 防XSS攻击
- 敏感数据加密存储
- 定期安全扫描
这个项目从技术选型到最终上线历时3个月,期间遇到了不少挑战,但也收获了很多。特别是微信生态与SpringBoot后端的结合,既发挥了小程序的传播优势,又保证了后端服务的稳定可靠。未来可以考虑加入更多社交化电商功能,如拼团、秒杀等营销玩法,进一步提升用户活跃度和转化率。