Spring Cloud 学习与实践(4):订单服务开发

文章目录

  • [Spring Cloud 学习与实践(4):订单服务开发](#Spring Cloud 学习与实践(4):订单服务开发)
    • [1. 本章目标](#1. 本章目标)
    • [2. cloud-order 模块结构](#2. cloud-order 模块结构)
    • [3. 订单表设计](#3. 订单表设计)
    • [4. DTO 设计](#4. DTO 设计)
    • [5. 订单实体](#5. 订单实体)
    • [6. Mapper](#6. Mapper)
    • [7. Service 接口与实现](#7. Service 接口与实现)
    • [8. Controller](#8. Controller)
    • [9. order.http 测试](#9. order.http 测试)
    • [10. 故障演练总结](#10. 故障演练总结)

Spring Cloud 学习与实践(4):订单服务开发

本章目标:开发订单服务 cloud-order,实现本地订单创建和查询接口,并通过故障演练展示当前版本的设计缺陷,为后续 OpenFeign 调用用户和商品服务、库存扣减打基础。


1. 本章目标

本章主要完成:

  1. 搭建 cloud-order 模块
  2. 创建订单表 t_order
  3. 创建订单实体 Order
  4. 创建 DTO CreateOrderRequest
  5. 创建 Mapper、Service 和 Controller
  6. 实现本地创建订单逻辑
  7. 订单查询接口
  8. 故意演练不校验用户、商品和价格
  9. 总结当前缺陷并引出后续服务间远程调用必要性

2. cloud-order 模块结构

text 复制代码
cloud-order
├── pom.xml
└── src
    ├── main
    │   ├── java
    │   │   └── com.example.cloud.order
    │   │       ├── CloudOrderApplication.java
    │   │       ├── controller
    │   │       │   └── OrderController.java
    │   │       ├── dto
    │   │       │   └── CreateOrderRequest.java
    │   │       ├── entity
    │   │       │   └── Order.java
    │   │       ├── mapper
    │   │       │   └── OrderMapper.java
    │   │       └── service
    │   │           ├── OrderService.java
    │   │           └── impl
    │   │               └── OrderServiceImpl.java
    │   └── resources
    │       └── application.yml
    └── test
        └── http
            └── order.http

3. 订单表设计

在数据库 cloud_demo 中执行:

sql 复制代码
DROP TABLE IF EXISTS t_order;

CREATE TABLE t_order (
    id BIGINT NOT NULL AUTO_INCREMENT COMMENT '订单ID',
    user_id BIGINT NOT NULL COMMENT '用户ID',
    product_id BIGINT NOT NULL COMMENT '商品ID',
    product_name VARCHAR(128) NOT NULL COMMENT '下单时的商品名称快照',
    amount DECIMAL(10, 2) NOT NULL COMMENT '订单金额',
    status TINYINT NOT NULL DEFAULT 0 COMMENT '订单状态:0待处理,1已完成,2已取消',
    create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
    PRIMARY KEY (id),
    KEY idx_user_id (user_id),
    KEY idx_product_id (product_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='订单表';

示例数据可通过接口创建。


4. DTO 设计

CreateOrderRequest.java

java 复制代码
@Data
public class CreateOrderRequest {
    private Long userId;
    private Long productId;
    private String productName;
    private BigDecimal amount;
}

说明:

  • DTO 与实体分离,防止客户端直接控制数据库字段
  • 便于后续 OpenFeign 调用重构接口参数

5. 订单实体

Order.java

java 复制代码
@Data
@TableName("t_order")
public class Order {
    @TableId(type = IdType.AUTO)
    private Long id;
    private Long userId;
    private Long productId;
    private String productName;
    private BigDecimal amount;
    private Integer status;
    private LocalDateTime createTime;
}

6. Mapper

OrderMapper.java

java 复制代码
@Mapper
public interface OrderMapper extends BaseMapper<Order> {
}

7. Service 接口与实现

OrderService.java

java 复制代码
public interface OrderService extends IService<Order> {
    Order createOrder(CreateOrderRequest request);
}

OrderServiceImpl.java

java 复制代码
@Service
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements OrderService {

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Order createOrder(CreateOrderRequest request) {
        if (request == null || request.getUserId() == null || request.getProductId() == null
                || request.getProductName() == null || request.getAmount() == null) {
            throw new BizException(ErrorCode.PARAM_ERROR, "参数不完整");
        }

        Order order = new Order();
        order.setUserId(request.getUserId());
        order.setProductId(request.getProductId());
        order.setProductName(request.getProductName());
        order.setAmount(request.getAmount());
        order.setStatus(0);

        boolean success = save(order);
        if (!success) {
            throw new BizException(ErrorCode.BIZ_ERROR, "创建订单失败");
        }

        return order;
    }
}

8. Controller

OrderController.java

java 复制代码
@RestController
@RequestMapping("/orders")
@RequiredArgsConstructor
public class OrderController {

    private final OrderService orderService;

    @PostMapping
    public Result<Order> create(@RequestBody CreateOrderRequest request) {
        return Result.success(orderService.createOrder(request));
    }

    @GetMapping("/{id}")
    public Result<Order> getById(@PathVariable Long id) {
        Order order = orderService.getById(id);
        if (order == null) {
            return Result.fail(ErrorCode.NOT_FOUND, "订单不存在");
        }
        return Result.success(order);
    }
}

9. order.http 测试

完整内容↓

javascript 复制代码
### 正常创建订单
POST http://localhost:9400/orders
Content-Type: application/json

{
  "userId": 1,
  "productId": 1,
  "productName": "机械键盘",
  "amount": 299.00
}

### 查询订单详情
GET http://localhost:9400/orders/1

### 查询不存在的订单
GET http://localhost:9400/orders/999

### 参数错误:缺少用户 ID
POST http://localhost:9400/orders
Content-Type: application/json

{
  "productId": 1,
  "productName": "机械键盘",
  "amount": 299.00
}

### 故障演练:不存在的用户仍然可以创建订单
POST http://localhost:9400/orders
Content-Type: application/json

{
  "userId": 999999,
  "productId": 1,
  "productName": "机械键盘",
  "amount": 299.00
}

### 故障演练:不存在的商品仍然可以创建订单
POST http://localhost:9400/orders
Content-Type: application/json

{
  "userId": 1,
  "productId": 999999,
  "productName": "不存在的商品",
  "amount": 0.01
}

### 故障演练:客户端可以伪造商品价格
POST http://localhost:9400/orders
Content-Type: application/json

{
  "userId": 1,
  "productId": 1,
  "productName": "机械键盘",
  "amount": 0.01
}

包含:

  • 正常订单创建
  • 查询订单
  • 用户不存在、商品不存在、伪造金额的订单创建

示例:

http 复制代码
POST http://localhost:9400/orders
Content-Type: application/json

{
  "userId": 999999,
  "productId": 1,
  "productName": "机械键盘",
  "amount": 299.00
}

结果仍然创建成功,说明本章故意保留的缺陷:

  1. 用户 ID 可以伪造
  2. 商品 ID 可以伪造
  3. 商品名称和金额可以伪造
  4. 库存未扣减

测试后数据库如图↓

10. 故障演练总结

  • 本章订单服务完全本地落库
  • 故意不校验用户、商品、价格,方便演练后续服务间调用
  • 为第 5~7 章引出 OpenFeign、远程用户校验、商品校验及库存扣减逻辑做准备

相关推荐
LiaoWL1233 小时前
【SpringCloud合集-04】Sentinel 流量控制与熔断降级 学习笔记
学习·spring cloud·sentinel
Misnearch6 小时前
nacos配置管理改造
java·spring cloud·nacos
worilb10 小时前
Spring Cloud 学习与实践(15):使用 TraceId 与 MDC 串联微服务日志
学习·spring cloud·微服务
长不胖的路人甲1 天前
SpringCloud 服务雪崩、熔断、降级
后端·spring·spring cloud
weixin_BYSJ19871 天前
springboot美食食谱小程序---附源码24044
java·spring boot·python·spring cloud·django·tomcat·php
worilb2 天前
Spring Cloud 学习与实践(13):使用 Seata 解决分布式事务问题
分布式·学习·spring cloud
Devin~Y2 天前
电商场景下的Java面试实战:从Spring Boot微服务到Kafka、Redis与AI RAG
java·spring boot·redis·elasticsearch·spring cloud·微服务·kafka
SizeTheMoment2 天前
Spring Cloud 微服务认证体系深度解析:从架构设计到安全实践
安全·spring cloud·微服务
微三云 - 廖会灵 (私域系统开发)5 天前
电商系统微服务拆分实战:从单体到Spring Cloud的分布式事务踩坑与补偿方案
分布式·spring cloud·微服务
k↑5 天前
SpringCloud + React19 集成Scalar的API文档
后端·spring·spring cloud