消息傳遞系統通常被成為MOM(Message Oriented MiddleWare),作為消息服務器,MOM需要客戶端用統一的標準訪問服務器,JMS標準是使用
最廣泛的消息接口標準.
JMS消息分點對點、基於主題的消息兩種
點對點方式:是兩個客戶端建立消息隊列,消息發送者(sender)把消息(Message)給消息服務器中的一個隊列(Queue),消息接受者(receiver)從服務器中這個隊列中
獲取消息.
主題消息:消息發送者響向消息服務器中的一個主題發送消息(Message),對這個消息有訂閱的接受者都會接受到這個消息.
JMS中的主要名詞:
1)目的地(Desination)
?是發送者和接受者的一個共同的地點,發送者把消息發送到這裡,接受者從這裡獲取消息,是我們在服務器中創建的一個隊列,服務器會對這個地方的所有消息維護。
2)會話
?消息發送者和接受,都要通過JNDI獲取消息服務器的上下文,session就是這樣的一個上下文對象,它可以創建消息生產者、消費者,可以創建點對點消息、主題消息
所有的消息操作都圍繞這個會話展開.
消息結構的介紹
用過web services(SOAP)應該知道消息包括信封、消息頭、主體、附件.同樣JMS消息結構也是差不多包括消息頭、消息屬性、消息體.
以JMS、SOAP為基礎可以實現面向消息模型(MOM Message Oriented Model)。
JMS消息樣式:
SpyTextMessage {
???? Header {
??????? jmsDestination? : QUEUE.mytestjms
??????? jmsDeliveryMode : 2
??????? jmsExpiration?? : 0
??????? jmsPriority???? : 4
??????? jmsMessageID??? : ID:6-11454947326091
??????? jmsTimeStamp??? : 1145494732609
??????? jmsCorrelationID: null
??????? jmsReplyTo????? : null
??????? jmsType???????? : null
??????? jmsRedelivered? : false
??????? jmsProperties?? : {}
??????? jmsPropReadWrite: false
??????? msgReadOnly???? : true
??????? producerClientId: ID:6
???? }
???? Body {
??????? text??????????? :sender message from liao test
???? }
JMS簡單編程實現點對點的消息 服務器用jboss-4.0.3SP1
1)首先在JBOSS中部屬一個點對點的消息隊列
配置文件放在JBOSS_Home\server\default\deploy\jms
配置文件的內容為:
<?xml version="1.0" encoding="UTF-8"?>
<server>
?<!--是一個點對點的用org.jboss.mq.server.jmx.Queue(Topic),desination的名稱為mytestjms?
? 更多的配置說明可以看原來jboss自帶的Jms配置文件,文件名要用*-service.xml
?-->
? <mbean code="org.jboss.mq.server.jmx.Queue" name="jboss.mq.destination:service=Queue,name=mytestjms">
??? <depends optional-attribute-name="DestinationManager">jboss.mq:service=DestinationManager</depends>
? </mbean>
</server>
2)實現消息發送者
import java.util.Hashtable;
import javax.jms.*;
import javax.naming.*;
public class JMSSender {
??? QueueSession session;
??? QueueConnection conn;
??? QueueSender sender;
??? QueueReceiver receiver;
??? public void clientconnect()throws Exception
??? {
??????? //消息服務器(destination)設置
??????? Hashtable env =? new Hashtable();
??????? env.put(Context.INITIAL_CONTEXT_FACTORY,"org.jnp.interfaces.NamingContextFactory");
??????? env.put(Context.PROVIDER_URL,"localhost");
??????? Context iniCtx = new InitialContext(env)? ;
???????? //查找創建JMS連接的工廠類
??????? Object tmp = iniCtx.lookup("ConnectionFactory");
??????? QueueConnectionFactory qcf = (QueueConnectionFactory)tmp;
????????
??????? //查找JMS目標對象 點對點
??????? Queue queue = (Queue)iniCtx.lookup("queue/mytestjms");
??????? //創建JMS連接
??????? conn = qcf.createQueueConnection();
??????? //創建JMS會話
???????? session = conn.createQueueSession(false,QueueSession.AUTO_ACKNOWLEDGE);
???????? //開始連接
??????? conn.start();
??????? sender = session.createSender(queue);
??????? receiver = session.createReceiver(queue);
??? }
??? public? JMSSender()
??? {
??????? try{
?????????? System.out.println("begin");
??????????? clientconnect();
??????????? TextMessage textmsg = this.session.createTextMessage();
??????????? textmsg.setText("sender message from liao test");
??????????? //發送消息 點對點
??????????? sender.send(textmsg);
??????????? disConnect();
??????????? System.out.println("success");
??????? }catch(Exception e)
??????? {
??????????? e.printStackTrace();
??????? }
??? }
??? /**
???? * 停止和關閉JMS連接
???? * @throws JMSException
???? */
??? public void disConnect() throws JMSException
??? {
??????? conn.stop();
??????? session.close();
??????? conn.close();
??? }
??? public Message receiver() throws JMSException
??? {
??????? return receiver.receive(1000);
??? }
??? public static void main(String[] args)throws Exception
??? {
???????? new JMSSender();
??? }
}
3)實現消息接受者
import java.util.Hashtable;
import javax.jms.*;
import javax.naming.*;
public class JMSReceiver {
??? QueueSession session;
??? QueueConnection conn;
??? QueueReceiver receiver;
???
??? public void clientconnect()throws Exception
??? {
??????? Hashtable env =? new Hashtable();
??????? env.put(Context.INITIAL_CONTEXT_FACTORY,"org.jnp.interfaces.NamingContextFactory");
??????? env.put(Context.PROVIDER_URL,"localhost");
??????? Context iniCtx = new InitialContext(env)? ;
??????? Object tmp = iniCtx.lookup("ConnectionFactory");
??????? QueueConnectionFactory qcf = (QueueConnectionFactory)tmp;
??????? Queue queue = (Queue)iniCtx.lookup("queue/mytestjms");
??????? conn = qcf.createQueueConnection();
???????? session = conn.createQueueSession(false,QueueSession.AUTO_ACKNOWLEDGE);
??????? conn.start();
??????? receiver = session.createReceiver(queue);
??? }
??? public void disConnect() throws JMSException
?? {
?????? conn.stop();
?????? session.close();
?????? conn.close();
?? }
?? public Message receiver() throws JMSException
?? {
?????? return receiver.receive(1000);
?? }
?? public JMSReceiver()throws Exception
?? {
??????? clientconnect();
???????? Message msg = receiver();
???????? System.out.println(msg);
???????? if (msg instanceof TextMessage)
???????? {
???????????? TextMessage tmsg = (TextMessage)msg;
???????????? //消息主題內容:
???????????? System.out.println(tmsg.getText());
???????? }
???????? System.out.println("success");
???????? disConnect();
?
?? }
?
??? public static void main(String[] args)throws Exception
??? {
??????? new JMSReceiver();
??? }
}
主題消息用到Topic,思路基本相同,接受必需先訂閱消息主題,當有發送者把消息發給這個主題的時候
先前訂閱的接受就會收到這個消息。
SOA中JMS也是一個熱門,客戶端通常用JMS發送消息再ESB中調用具體的服務。