Java 消息服務(JMS)構建鬆耦合、可擴展的分布式系統。本文系統介紹 JMS 核心模型、消息類型、消息驅動 Bean(MDB)異步處理機制,並以 GlassFish 為平台,通過一個「Web 訪問追蹤器」實戰案例,演示從 Servlet 過濾器捕獲請求、JMS 異步發送、MDB 消費持久化到 JAXB XML 存儲的完整鏈路,包含資源配置、部署描述符、測試驗證全流程。
| 類型 | 描述 |
|---|---|
| TextMessage | 字符串文本或 java.lang.String |
| ObjectMessage | 可序列化 Java 對象(Serializable) |
| BytesMessage | 字節流 |
| MapMessage | 鍵值對集合 |
| StreamMessage | 基本類型數據流 |
javax.jms.MessageListener 接口,核心方法 onMessage(Message msg)。@MessageDriven(mappedName="queueName") 注解聲明,@Resource 注入 MessageDrivenContext。GlassFish 整合 Sun Java System Message Queue,提供開箱即用的 JMS Provider。需配置兩類資源:
asadmin 配置。webTrackerConnFactory,Resource Type: javax.jms.QueueConnectionFactory。webTrackerQueue,Physical Destination: webTrackerQueue,Resource Type: javax.jms.Queue。QueueConnectionFactory 和 Queue)創建連接、會話、生產者,發送 ObjectMessage 到隊列。onMessage() 接收消息,轉換為 DTO,持久化到 XML 文件。webAccessLog.xml。Servlet Filter 發送消息:
@Resource(name="connFactory", mappedName="webTrackerConnFactory")
private QueueConnectionFactory qFactory;
@Resource(name="jmsQueue", mappedName="webTrackerQueue")
private Queue queue;
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) {
// ... 提取請求數據到 RequestData DTO ...
QueueConnection qConn = qFactory.createConnection();
Session session = qConn.createSession(false, Session.AUTO_ACKNOWLEDGE);
ObjectMessage msg = session.createObjectMessage();
msg.setObject(data);
session.createProducer(queue).send(msg);
// ... 關閉資源 ...
chain.doFilter(req, res);
}
MDB 接收並持久化:
@MessageDriven(mappedName = "webTrackerQueue")
public class WebTrackerEJB implements MessageListener {
@Resource private MessageDrivenContext mdbContext;
public void onMessage(Message message) {
if (message instanceof ObjectMessage) {
RequestData data = (RequestData) ((ObjectMessage) message).getObject();
persistToXml(data); // 使用 JAXB 寫入 XML
}
}
}
JAXB XML 讀寫:
// 解編
JAXBContext jc = JAXBContext.newInstance("demo.webtracker.xmlgen");
Unmarshaller u = jc.createUnmarshaller();
WebAccess access = (WebAccess) u.unmarshal(new FileInputStream(xmlPath)).getValue();
// 編組
Marshaller m = jc.createMarshaller();
m.marshal(accessData, new File(xmlPath));
ejb-jar.xml 聲明 MDB、事務屬性;sun-ejb-jar.xml 綁定 JNDI 名稱與連接工廠。若已使用注解,可省略。
-Dxmlstore.path=/path/to/webAccessLog.xml。https://host:port/webTracker,瀏覽頁面產生請求。