這一篇把前幾天的 API 契約與RabbitMQ Producer 串起來,完整走一遍:
POST /bid/buy(REST) → 組事件 OrderCreateEvent → 發到 Exchange / Queue → Wallet 消費。
API-first 怎麼落到程式
用 OpenAPI/Stoplight 先定義 /bid/buy,產出 Spring 介面與 DTO,像下面這樣:
• operationId: post-bid-add、/bid/buy 的 POST
• PlaceBuyOrderReq { bidPrice, amount, bidder(UUID) } 的 schema
這讓 Controller 端可以很乾淨地把 PlaceBuyOrderReq 交給 Service,後續專心把 REST 轉成事件。
RabbitMQ 設定與常數
使用 Spring AMQP 建立 TopicExchange / Queue / Binding 與 JSON 轉換器,並把名稱抽到共用常數(eap-common)管理:
• ORDER_EXCHANGE
• ORDER_CREATE_QUEUE
• ORDER_CREATE_ROUTING_KEY
• Jackson2JsonMessageConverter()(事件物件會自動序列化成 JSON)
REST → 事件的映射
在 PlaceBuyOrderService 中,把請求變成 OrderCreateEvent(orderId/userId/price/amount/orderType/createdAt),再丟給 Rabbit:
@Service
public class PlaceBuyOrderService {
@Autowired private RabbitTemplate rabbitTemplate;
public void execute(PlaceBuyOrderReq request) {
OrderCreateEvent event = OrderCreateEvent.builder()
.orderId(UUID.randomUUID())
.userId(request.getBidder())
.price(request.getBidPrice())
.amount(request.getAmount())
.orderType(OrderType.BUY.name())
.createdAt(LocalDateTime.now())
.build();
rabbitTemplate.convertAndSend(ORDER_EXCHANGE, ORDER_CREATE_ROUTING_KEY, event);
}
}
這裡的常數(ORDER_EXCHANGE/ORDER_CREATE_ROUTING_KEY)是從共用模組抽出來,避免命名走鐘以及提高可維護性。
4) 範例請求與實際事件
• REST 請求
POST /bid/buy
Content-Type: application/json
{
"bidPrice": 100,
"amount": 1,
"bidder": "123e4567-e89b-12d3-a456-426614174000"
}
• 發出去的事件(簡化)
{
"orderId": "a0f2e8aa-8a2d-4b9c-8ab8-5b7a4ca59b7c",
"userId": "123e4567-e89b-12d3-a456-426614174000",
"price": 100,
"amount": 1,
"orderType": "BUY",
"createdAt": "2025-08-23T12:34:56"
}