Message-Driven Bean (MDB) 是 EJB 2.0 引入的異步消息消費者,實現 MessageDrivenBean 與 MessageListener 接口,由容器管理生命周期與併發池。本文系統梳理 JMS 模型、MDB 架構、點對點/發布訂閱兩種模式,並提供完整部署範例。
| 特性 | 點對點 | 發布/訂閱 |
|---|---|---|
| 目的地 | Queue | Topic |
| 消費者數量 | 單一 | 多個 |
| 時間依賴 | 無(消息持久化) | 有(訂閱者需在線),可用持久訂閱緩解 |
| 確認機制 | 消費者確認 | 自動/客戶端/重複確認模式 |
setMessageDrivenContext(MessageDrivenContext):注入容器上下文。ejbCreate():無參公共方法,實例化資源(JMS 連接、DataSource 等)。onMessage(Message):核心業務方法,容器調用處理消息,通常 cast 為 TextMessage/ObjectMessage 等。ejbRemove():清理資源,容器決定調用時機,異常時可能不調用,需在 onMessage 中做好資源保護。QueueConnectionFactory qcf = (QueueConnectionFactory) jndi.lookup("java:comp/env/jms/MyQueueConnectionFactory");
Queue queue = (Queue) jndi.lookup("java:comp/env/jms/QueueName");
QueueConnection qc = qcf.createQueueConnection();
QueueSession qs = qc.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
QueueSender sender = qs.createSender(queue);
TextMessage msg = qs.createTextMessage();
for (int i=0; i<3; i++) {
msg.setText("Message " + i);
sender.send(msg);
}
qc.close();
SimpleMessageBeanpublic class SimpleMessageBean implements MessageDrivenBean, MessageListener {
private MessageDrivenContext mdc;
public void setMessageDrivenContext(MessageDrivenContext ctx) { this.mdc = ctx; }
public void ejbCreate() {}
public void ejbRemove() {}
public void onMessage(Message msg) {
try {
if (msg instanceof TextMessage) {
System.out.println("MDB 收到: " + ((TextMessage)msg).getText());
} else {
System.err.println("非預期消息類型: " + msg.getClass().getName());
}
} catch (JMSException e) {
mdc.setRollbackOnly(); // 標記事務回滾,消息將重投
}
}
}
ejb-jar.xml 關鍵片段<message-driven>
<ejb-name>SimpleMessageEJB</ejb-name>
<ejb-class>SimpleMessageBean</ejb-class>
<transaction-type>Container</transaction-type>
<message-destination-type>javax.jms.Queue</message-destination-type>
<activation-config>
<activation-config-property>
<activation-config-property-name>destinationType</activation-config-property-name>
<activation-config-property-value>javax.jms.Queue</activation-config-property-value>
</activation-config-property>
</activation-config>
</message-driven>
ejb-jar.xml、廠商專用描述符)。j2eeadmin -addJmsDestination jms/MyQueue queue 建立 Queue。j2ee -verbose 查看 MDB 輸出。runclient -client app.ear -name Client -textauth 發送測試消息。