JMS/JNDI 信息傳遞原理(轉)

JNDI -- Java Naming and Directory Interface

JNDI API被用於執行名字和目錄服務。它提供了一致的模型來存取和操作企業級的資源如DNS和LDAP,本地文件系統,後者在應用服務器中的對象。

sun只是提供了JNDI的接口(即規範),IBM, Novell, Sun 和 WebLogic 和JBOSS已經爲 JNDI 提供了服務提供程序,

在JNDI中,在目錄結構中的每一個結點稱爲context。每一個JNDI名字都是相對於context的。這裏沒有絕對名字的概念存在。對一個應用來說,它可以通過使用 InitialContext 類來得到其第一個context:  

    Context ctx = new InitialContext();

    ctx.bind("name", Object);

    ctx.lookup("name");

    

Context:上下文,我的理解是相當與文件系統的中的目錄(JNDI的Naming Service是可以用操作系統的文件系統的,哈哈). 

entry/object:一個節點,相當與文件系統中的目錄或文件. 

filter:查詢/過濾條件是一個字符串表達式如:(&(objectClass=top)(cn=*))查詢出objectClass屬性爲top,cn屬性爲所有情況的entry. 

Attribute:entry/object的屬性可以理解成JAVA對象的屬性,不同的是這個屬性可以多次賦值.

A.將接口分爲Context 和 DirContext   

   JNDI有兩個核心接口Context和DirContext,Context中包含 了基本的名字操作,而DirContext則將這些操作擴展到目錄服務。DirContext 對Context進行了擴展,提供了基本的目錄服務操作, 對名字對象屬性的維護、基於屬性的名字查找等等。   

B.上下文列表的多種方法   

   一般來說有兩種進行上下文列表的應用:上下文瀏覽應用和對上下文中的對象進行實際操作的應用。   

   上下文瀏覽應用一般只需要顯示上下文中包含內容的名字,或者再獲取一些諸如對象的類型之類的信息。這種類型的應用一般都是交互式的,可以允許用戶在列舉的上下文列表中選擇一些進行進一步的顯示。   

   另外有一些應用需要對上下文中的對象進行實際的操作,比如,一個備份程序需要對目錄中所有文件的狀態進行操作,或者某打印機管理員可能需要對大樓中的所有打印機進行復位。爲了進行這樣的操作,程序需要獲取上下文中的實際對象。   

   對於這樣兩種類型的應用,Context接口提供了兩種上下文列表方法list()和 listBindings()。其中list()只返回一系列名字/類映射,而listBindings() 則返回名字、類和對象本身。顯然 list()用於上下文瀏覽應用而listBindings()用於那些需要對對象進行實際操作的應用。   

Hashtable env = new Hashtable();

env.put(Context.INITIAL_CONTEXT_FACTORY,"com.sun.jndi.fscontext.RefFSContextFactory"); 

Context ctx = new InitialContext(env); 

Object obj = ctx.lookup("C:/aaa.txt");

Hashtable env = new Hashtable(); 

env.put(Context.INITIAL_CONTEXT_FACTORY,"com.sun.jndi.ldap.LdapCtxFactory"); 

env.put(Context.PROVIDER_URL,"ldap://127.0.0.1:10389/"); 

DirContext ctx = new InitialDirContext(env);

    

JMS(Java Mes)是用於和麪向消息的中間件相互通信的應用程序接口(API)。它既支持點對點的域,有支持發佈/訂閱(publish/subscribe)類型的域,並且提供對下列類型的支持:經認可的消息傳遞,事務型消息的傳遞,一致性消息和具有持久性的訂閱者支持。

JMS標準是應用最廣泛的消息接口標準。

JMS大體被分爲兩個功能塊,消息生產和消息消費.由消息驅動的bean提供了異步消費消息的能力

  Spring中JMSTemplate主要功能是產生消息

  JMS所提供的消息服務包括兩種機制  

         1.點對點 p2p   單個消息者消費掉(Queue隊列)

             Client1發送消息給消息服務器中的一個隊列,而Client2則從這個隊列中取出消息

         2.發佈/訂閱  publish/Subscribe  如爲持久的訂閱者則會保存到於MQ並處於監聽狀態。(Topic主題)

             類似於廣播,Client1向服務器中的一個消息主題發送消息,對這個消息主題感興趣的客戶端可以預約這個消息主題,當主題存在數據時,所以預約過這個主題的客戶端都會接收到。

  sun出了兩個jms的版本

           1.02 主要分爲兩個目的地類型  TopicConnectionFactory   QueueConnectionFactory

           1.1   中統稱爲 ConnectionFactory

           

 理解一下JMS中的基本概念

     Destination目的地

         例如消息隊列的資源,就要通過JNDI方式查找,目的地用來表示這些管理對象的抽象目的地資源。

     Session會話

         一個會話對象是一個單線程的上下文對象,用於產生消息和消費消息,它是JVM向外提供的資源,也是一個JMS的對象。

         會話是產生消息生產者和消費者的工廠

             TopicPublisher publisher = session.createPublisher(topic);

             TopicSubscriber subscriber = session.createSubscriber(topic);

             QueueSender sender = session.createSender(queue);

             QueueReceiver receiver = session.createReceiver(queue);

         會話也是創建主題消息對象和點對點消息對象的工廠

             TextMessage msg = publisher.session.CreateTextMessage();

             TextMessage msg = sender.session.CreateTextMessage();

     

     Connection 連接

          一個連接對象是由客戶端激活的客戶端與服務提供者之間的連接

     Message消息

          指的是服務提供者與客戶端之間傳遞信息所使用的信息單元。

          每個消息都是由消息頭(Headers),消息屬性(Properties),消息體(Body)三個部分組成.

          A.消息頭有關消息的元數據和消息的路由信息.

              jmsDeliveryMode 發送模式 DeliveryMode.NON_PERSISTENT 當服務器出錯時,消息會丟失  DeliveryMode.PERSISTENT   當服務器出錯時,消息也不會丟失

              jmsExpiration 消息過期時限 控制消息在服務器容器中存活的時間 0時則不會過期

              jmsPriority 消息優先級, 0-4爲普通級別,5-9屬於需要迅速發送

              jmsRedelivered 是否重新分發給接收者  爲true時,如果一個消息接收者接收失敗,則該消息會重新分發給這個消息的接收者

              jmsMessageID 消息的ID,不必設置,會被容器指定一個字符數值

              jmsTimestamp long型的值,消息時間戳,被容器設置

          B.消息屬性由JMS的發送端定義,是一堆鍵值對..對於接收端是隻讀的!

              可以通過getPropertyNames()返回所有的屬性名稱

              setBooleanProperty("name", boolean);

                  .(八種基本類型)

              可以通過以下方法過濾接收者只接收name爲silent的屬性的值

              QueueReceiver receiver = session.createReceiver(queue, "name = 'silent'");

              

          C.消息體負責裝載消息數據內容,對於接收端是隻讀的!

              Message TextMessage ObjectMessage BytesMessage StreamMessage MapMessage

              其都是通過session.createXXXMessage();來創建

              注:全部爲接口.其實現有SpyXXXMessage...由session來管理

          

          

     

     MessageProducer消息生產者

           消息產生由JMS客戶端完成,服務提供者只負責管理這些消息。

           通過 void publish(Message message)和 void send(Message message)

     MessageConsumer消息消費者

           一個消息的消費者可以接收來自某個隊列的消息

           都是通過Message receiver()來從消息隊列中接收消息

JMS使用步驟:(9個步驟)

         利用JNDI找到創建連接使用的工廠類 ConnectionFactory,使用這些工廠類創建一個連接的實例(Connection) ,由連接的實例創建一個會話Session,這個會話 類代表一個會話資源,得用會話類我們可以產生創建新消息的消息生產者(Producer),也可以產生接收消息的消費者(Consumer),而不管發消 息還是接收消息都需要訪問JMS的目標對象(Destination)。

     在使用消費方式時,還可以建立消息的監者(Listener),當一個新的消息產生時,監聽者會得到通知,

1) 創建JNDI上下文,並且查找創建JMS連接使用的工廠類

Hashtable env = new Hashtable(); 

env.put(Context.INITIAL_CONTEXT_FACTORY,"org.jnp.interfaces.NamingContextFactory"); 

env.put(Context.PROVIDER_URL,"ldap://192.168.1.106:1039/"); 

Context iniCtx = new InitialContext(env);

TopicConnectionFactory tcf = (TopicConnectionFactory)iniCtx.lookup("ConnectionFactory");

2) 查找JMS的目標對象

Topic topic = (Topic)iniCtx.lookup("topic/testTopic");

3) 創建JMS連接

TopicConnection conn = tcf.createTopicConnection(); 只要在這裏加入user,pass參數,該消息則爲持久性消息

4) 創建會話

   TopicSession session = conn.createTopicSession(false, Session.AUTO_ACKNOWLEDGE);

5) 創建消息的生產者和消費者

    TopicPublisher publisher = session.createPublisher(topic);

    TopicSubscriber subscriber = session.createSubscriber(topic);

6) 註冊消息的監聽者:

    TextListener listener = new TextListener();

    subscriber.setMessageListener(listener);

    

7) 開始JMS的連接

    conn.start();

8) 發送消息和接收消息

publisher.publish(Message message);

Message message = subscriber.receive();

9) 停止和關閉JMS連接

conn.stop();

session.close();

conn.close();

 

Spring 中對JMS進行了封裝,另使用編寫變得更簡單.對於1.1的JMS其有JmsTemplate,而對於1.02其有JmsTemplate102

      而Spring中的JMS對於Queue和Topic方式並不關心,都整合到一起用了!!

   這裏的JMSTemp需要指定 connectionFactory(org.springframework.jndi.JndiObjectFactoryBean)和 defaultDestination(org.springframework.jndi.JndiObjectFactoryBean)    注意 1.02中必須要設置pubsubDomain屬性,是否以主題形式發送

   

   JMS發送方法

       jmsTemplate.send(new MessageCreator() {

             public Message createMessage(Session session) throws JMSException {

                  //利用Session創建消息並返回該消息實例就行了

             }

    }

    

   JMS接收方法

      Message Msg = jmsTemplate.receive();

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章