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();