在這篇文章中,我將分享我如何在 order-service 中設定 RabbitMQ,並在使用者掛買單時,發送一筆 OrderCreateEvent 到指定的佇列中,作為事件驅動架構的第一步。
RabbitMQ 基礎設定
首先要先在build.gradle中加入spring-boot對於rabbimq的相關依賴用以支援 Spring Boot 自動配置 RabbitMQ 元件與模板
implementation 'org.springframework.boot:spring-boot-starter-amqp'
然後我們必須在程式中配置我們要使用的RabbitMQ相關設定來建立我們傳遞訊息所使用的頻道,在 Spring 框架中,我們不需要手動建立或管理 RabbitMQ 這類元件的生命週期。這是因為 Spring 採用了 控制反轉(IoC) 和 相依注入(DI) 的原則,也就是「你只要說出你要什麼,Spring 就會幫你準備好」。像是這段設定檔:
@Configuration
public class RabbitMQConfig {
@Bean
public MessageConverter jsonMessageConverter() {
return new Jackson2JsonMessageConverter();
}
@Bean
public TopicExchange orderExchange() {
return new TopicExchange(ORDER_EXCHANGE);
}
@Bean
public Queue orderCreateQueue() {
return new Queue(ORDER_CREATE_QUEUE);
}
@Bean
public Binding bindOrderCreateQueue(Queue orderCreateQueue, TopicExchange orderExchange) {
return BindingBuilder.bind(orderCreateQueue).to(orderExchange).with(ORDER_CREATE_ROUTING_KEY);
}
}
@Configuration 的意思是:這是一個「配置類別」,Spring 啟動時會掃描它,就像掃描設定檔一樣。
@Bean 則表示:這個方法的回傳值要交給 Spring 託管,變成一個可被「注入使用」的元件(也叫 Bean)。
這樣一來,我們就不需要自己 new TopicExchange(...) 或寫連線邏輯,而是透過 @Autowired 把需要的元件直接拿來用,像是自動配對好的插頭一樣。
這段設定的目的是讓 Spring 在啟動時,掃描這些標記後:
發送事件:PlaceBuyOrderService
在使用者送出掛買單時,我會組成一筆事件物件並發送到 RabbitMQ:
@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);
}
}
同樣的這邊也使用了@Autowired來讓spring生成rabbitTemplate物件來幫我們進行發送事件的功能,有興趣的可以參考spring.doc中對於該物件的詳細方法(RabbitTemplate (Spring AMQP 3.2.6 API)),他類似於JdbcTemplate,hibernate會使用的session一樣目的是讓使用者專注於業務邏輯,而不必煩惱連線、序列化、訊息確認等細節。
這筆事件會被 wallet-service 接收,進行餘額驗證、資產鎖定與扣款處理。
事件物件:OrderCreateEvent
@Data
@Builder
public class OrderCreateEvent {
private UUID orderId;
private UUID userId;
private Integer price;
private Integer amount;
private String orderType; // "BUY" or "SELL"
private LocalDateTime createdAt;
}
我使用 @Builder 與 @Data 等lombok提供的方便方法搭配 Serializable 進行資料建構與傳輸。
這樣就完成了從 REST API → 事件構建 → RabbitMQ 發送的流程。下一篇我將介紹 wallet-service 中如何接收這筆事件並執行資產鎖定邏輯,正式實現事件驅動的第二步!