三亩地 三亩地SAN MU DI · CODE DIARY
ARTICLE DETAIL

日记详情

真实记录编程学习的某一天,欢迎挑你感兴趣的翻一翻。

Spring Boot外卖系统开发实战:核心模块与JWT认证

Spring Boot外卖系统开发实战:核心模块与JWT认证

1. 项目背景与核心目标

"苍穹外卖-day02"这个标题背后,隐藏着一个典型的外卖平台后端开发实战项目。作为系列开发的第二天,通常意味着我们已经完成了基础环境搭建,开始进入核心业务逻辑的实现阶段。

从项目命名方式来看,这很可能是一个采用敏捷开发模式的外卖系统开发实践。Day02的定位非常明确:在完成基础框架搭建后,开始实现外卖平台的核心业务流程。根据我的开发经验,这个阶段通常会涉及以下几个关键模块:

  • 用户端功能:登录验证、菜品浏览、购物车管理
  • 商家端功能:商品管理、订单处理
  • 平台端功能:数据统计、权限控制

2. 技术架构选型分析

2.1 后端技术栈选择

基于当前主流的外卖平台开发实践,我推测这个项目可能采用了以下技术组合:

  • Spring Boot:作为基础框架,提供快速开发能力
  • MyBatis/MyBatis-Plus:处理数据持久层
  • Redis:缓存热点数据,提升系统响应速度
  • MySQL:作为主数据库存储业务数据

这种技术组合的优势在于:

  1. 开发效率高,适合快速迭代
  2. 社区支持完善,遇到问题容易找到解决方案
  3. 性能表现均衡,能够满足外卖平台的基本需求

2.2 接口设计原则

在Day02的开发中,API设计需要遵循几个关键原则:

  1. RESTful风格:使用标准的HTTP方法和状态码
  2. 版本控制:在URL中包含版本号,如/api/v1/orders
  3. 参数校验:对所有输入参数进行严格验证
  4. 错误处理:统一的错误码和错误信息格式

3. 核心功能模块实现

3.1 用户认证模块

外卖系统的用户认证通常采用JWT(JSON Web Token)方案。具体实现步骤如下:

  1. 用户登录成功后,服务端生成JWT token
  2. token中包含用户ID、角色等基本信息
  3. 客户端在后续请求中携带token
  4. 服务端通过拦截器验证token有效性

关键代码示例:

// JWT工具类 public class JwtUtil { private static final String SECRET_KEY = "your-secret-key"; private static final long EXPIRATION_TIME = 86400000; // 24小时 public static String generateToken(UserDetails userDetails) { return Jwts.builder() .setSubject(userDetails.getUsername()) .setIssuedAt(new Date()) .setExpiration(new Date(System.currentTimeMillis() + EXPIRATION_TIME)) .signWith(SignatureAlgorithm.HS512, SECRET_KEY) .compact(); } public static boolean validateToken(String token) { try { Jwts.parser().setSigningKey(SECRET_KEY).parseClaimsJws(token); return true; } catch (Exception e) { return false; } } }

3.2 菜品管理模块

菜品是外卖平台的核心数据,其管理功能需要特别注意:

  1. 数据结构设计

    • 菜品基本信息表
    • 菜品分类表
    • 菜品规格表(如辣度、大小等)
  2. 关键接口实现

    • 菜品列表分页查询
    • 按分类筛选菜品
    • 菜品详情获取
    • 菜品上下架操作

注意:菜品图片建议使用OSS存储,数据库只保存图片URL。同时要考虑图片的CDN加速问题。

3.3 购物车功能实现

购物车是连接用户和订单的关键模块,其核心逻辑包括:

  1. 数据结构
public class CartItem { private Long dishId; // 菜品ID private String dishName; // 菜品名称 private Integer quantity; // 数量 private BigDecimal price; // 单价 private String image; // 图片 private List<CartItemSpec> specs; // 规格选择 }
  1. 存储策略选择

    • 用户未登录:存储在浏览器本地存储
    • 用户已登录:同步到服务端Redis
  2. 关键操作

    • 添加商品到购物车
    • 修改购物车商品数量
    • 删除购物车商品
    • 清空购物车

4. 数据库设计与优化

4.1 核心表结构

-- 菜品表 CREATE TABLE `dish` ( `id` bigint NOT NULL AUTO_INCREMENT, `name` varchar(64) NOT NULL COMMENT '菜品名称', `category_id` bigint NOT NULL COMMENT '分类ID', `price` decimal(10,2) NOT NULL COMMENT '价格', `image` varchar(255) COMMENT '图片URL', `description` varchar(255) COMMENT '描述信息', `status` tinyint DEFAULT 1 COMMENT '状态 0停售 1启售', `create_time` datetime NOT NULL, `update_time` datetime NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; -- 购物车表 CREATE TABLE `shopping_cart` ( `id` bigint NOT NULL AUTO_INCREMENT, `user_id` bigint NOT NULL COMMENT '用户ID', `dish_id` bigint NOT NULL COMMENT '菜品ID', `specs` varchar(255) COMMENT '规格JSON', `number` int NOT NULL DEFAULT 1 COMMENT '数量', `create_time` datetime NOT NULL, PRIMARY KEY (`id`), UNIQUE KEY `idx_user_dish` (`user_id`,`dish_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

4.2 索引优化建议

  1. 高频查询字段必须建立索引,如:

    • 菜品表的category_id
    • 购物车表的user_id和dish_id组合
  2. 避免过度索引,每个表索引数量控制在5个以内

  3. 使用EXPLAIN分析慢查询,针对性优化

5. 常见问题与解决方案

5.1 高并发下的购物车冲突

问题现象:多个终端同时修改购物车导致数据不一致

解决方案

  1. 使用Redis的WATCH/MULTI/EXEC实现乐观锁
  2. 前端实现排队机制,避免短时间内重复提交
  3. 后端采用版本号控制,检测数据冲突

5.2 菜品缓存一致性问题

问题现象:后台修改菜品信息后,前端仍然显示旧数据

解决方案

  1. 采用"先更新数据库,再删除缓存"策略
  2. 设置合理的缓存过期时间(如5分钟)
  3. 对关键数据变更发送消息通知,触发缓存更新

5.3 分页查询性能优化

问题现象:菜品列表翻页时,越往后越慢

解决方案

  1. 使用覆盖索引优化COUNT查询
  2. 采用"游标分页"替代传统LIMIT分页
  3. 对大表考虑使用分区表技术

6. 开发环境配置建议

6.1 本地开发环境

  1. IDE选择

    • IntelliJ IDEA(推荐)
    • VS Code + Java插件
  2. 数据库工具

    • Navicat
    • DBeaver
    • MySQL Workbench
  3. API测试工具

    • Postman
    • Insomnia
    • Swagger UI

6.2 项目依赖管理

建议使用Gradle或Maven管理依赖,示例pom.xml配置:

<dependencies> <!-- Spring Boot Starter --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- MyBatis Plus --> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.5.3</version> </dependency> <!-- Redis --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> </dependencies>

7. 测试策略与质量保障

7.1 单元测试要点

  1. 使用JUnit 5 + Mockito编写单元测试

  2. 重点测试:

    • 业务逻辑计算
    • 异常处理流程
    • 边界条件
  3. 示例测试用例:

@Test public void testAddToCart() { // 准备测试数据 CartItemDTO cartItemDTO = new CartItemDTO(); cartItemDTO.setDishId(1L); cartItemDTO.setQuantity(2); // 模拟依赖组件 when(dishMapper.selectById(anyLong())).thenReturn(new Dish()); // 执行测试 cartService.addToCart(cartItemDTO, 1L); // 验证结果 verify(cartMapper, times(1)).insert(any()); }

7.2 集成测试建议

  1. 使用Testcontainers进行数据库集成测试
  2. 对核心业务流程编写端到端测试
  3. 使用Jacoco生成测试覆盖率报告

8. 项目部署与监控

8.1 生产环境部署

  1. 服务器配置建议

    • 2核4G起步(根据预估流量调整)
    • 使用Docker容器化部署
    • 配置合理的JVM参数
  2. 部署流程

    # 构建项目 mvn clean package -DskipTests # 构建Docker镜像 docker build -t sky-takeaway . # 运行容器 docker run -d -p 8080:8080 --name takeaway sky-takeaway

8.2 系统监控配置

  1. 使用Spring Boot Actuator暴露健康检查端点
  2. 集成Prometheus + Grafana监控系统指标
  3. 配置日志收集系统(ELK或Loki)

9. 项目扩展与演进

9.1 后续迭代方向

  1. 功能扩展

    • 优惠券系统
    • 会员积分体系
    • 智能推荐算法
  2. 架构升级

    • 引入消息队列解耦
    • 服务拆分微服务化
    • 分布式事务处理

9.2 性能优化空间

  1. 数据库读写分离
  2. 引入二级缓存(Caffeine)
  3. 静态资源CDN加速
  4. 接口响应缓存

在实际开发"苍穹外卖-day02"的过程中,我发现最大的挑战不在于技术实现本身,而在于如何在保证功能完整性的同时,为后续迭代预留足够的扩展空间。特别是在数据结构设计阶段,需要充分考虑未来可能新增的业务场景,避免后期频繁的数据库结构调整。

← 返回列表