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、远程用户校验、商品校验及库存扣减逻辑做准备

相关推荐
椰椰椰耶1 天前
[SpringCloud][12]Nacos配置中心详解,快速上手,Nacos和Eureka的区别
spring·spring cloud·eureka
半旧夜夏2 天前
【保姆级】微服务组件环境搭建(Docker Compose版)
java·linux·spring cloud·微服务·云原生·容器
Devin~Y2 天前
从内容社区到AIGC客服:Spring Boot、Redis、Kafka、K8s、RAG的三轮大厂Java面试对话(附标准答案)
java·spring boot·redis·spring cloud·kafka·kubernetes·micrometer
西凉的悲伤2 天前
Spring Boot 、Spring Cloud 微服务架构认证授权方案
spring boot·spring cloud·微服务·架构·认证授权
西凉的悲伤3 天前
Spring Cloud Gateway介绍
java·spring cloud·gateway
JAVA社区4 天前
Java高级全套教程(十)—— SpringCloudAlibaba超详细实战详解
java·开发语言·spring cloud·面试·职场和发展
JAVA社区4 天前
Java高级全套教程(九)—— SpringCloud超详细实战详解
java·开发语言·后端·spring cloud·面试·职场和发展
Devin~Y4 天前
大厂Java面试实录:Spring Boot/Cloud、Kafka、Redis、K8s 可观测性 + RAG/Agent(小Y翻车版)
java·spring boot·redis·spring cloud·kafka·kubernetes·mybatis