JNDI解析


 http://blog.csdn.net/zhaosg198312/article/details/3979435

我對於jndi的理解 java naming and directory  interface

命名服務,一個值和另一個值的映射;如學號和姓名

目錄服務,至於目錄服務,從計算機角度理解為在互聯網上有着各種各樣的資源和主機,但是這些內容都是散落在互聯網中,為了訪問這些散落的資源並獲得相應的服務,就需要用到目錄服務.

容器提供jndi,jndi就相當於java應用程序合在一起的粘合劑,容器本身提供了jndi規范的實現

容器實現了jndi規范,將相應的配置和管理交給容器,設置好相應的jndi參數,我們只需要對這么配合進行引用即可。

使用jndi先要初始化一個initialContext,初始上下文,這個初始上下文可以使遠程的也可以是本地的,創建之后就可以從這個上下文中lookup jndi的引用名稱了從而獲得你所需要的資源

關於topic和queue的區別詳見http://www.cnblogs.com/javahuang/archive/2013/04/28/3048957.html

jms的api  http://docs.oracle.com/javaee/1.3/jms/tutorial/1_3_1-fcs/doc/prog_model.html

Connection Factories

At the beginning of a JMS client program, you usually perform a JNDI API lookup of the connection factory   ConnectionFactory一般由jndi創建

其中創建的factory有兩種Each connection factory is an instance of either the QueueConnectionFactory or the TopicConnectionFactory interface

Connections

創建:QueueConnection queueConnection =queueConnectionFactory.createQueueConnection();

TopicConnection topicConnection =  topicConnectionFactory.createTopicConnection();

關閉:queueConnection.close();

topicConnection.close();

When an application completes, you need to close any connections that you have created. Failure to close a connection can cause resources not to be released by the JMS provider. Closing a connection also closes its sessions and their message producers and message consumers.

Sessions

A session is a single-threaded context for producing and consuming messages. You use sessions to create message producers, message consumers, and messages. Sessions serialize the execution of message listeners; --session是單線程上線文生產和消費message,可以用session創建消息生產,消費和消息 session序列

消息監聽 messages listeners

A message listener is an object that acts as an asynchronous event handler for messages. This object implements the MessageListener interface, which contains one method, onMessage. In the onMessage method, you define the actions to be taken when a message arrives.—消息監聽充當異步消息時間處理事件,實現了MessageListener 接口,包含一個方法onMessage(),可以定義一個消息到來時采取的行為

 

TopicSession topicSession = 
  topicConnection.createTopicSession(false, Session.AUTO_ACKNOWLEDGE);

Controlling Message Acknowledgment

 

        

topic可以一對多,queue是一對一

 

 

 

The javax.naming.InitialContext class implements the Context interface and serves as our entry point to a naming system. To use JNDI to access objects in a naming system, you must first create an InitialContextobject. The InitialContext constructor takes a set of properties, in the form of a java.util.Hashtable or one of its subclasses, such as a Properties object. Here is how we created an InitialContext in the Lookup example:
Properties props = new Properties();
props.put(Context.INITIAL_CONTEXT_FACTORY,
"com.sun.jndi.fscontext.RefFSContextFactory");
props.put(Context.PROVIDER_URL, "file:///");

// Create the initial context from the properties we just created
Context initialContext = new InitialContext(props);

jndi調用時,各種應用服務器InitialContext的寫法

  Hashtable properties = new Hashtable();

                properties.put(

                    Context.INITIAL_CONTEXT_FACTORY,

                    "org.exolab.jms.jndi.InitialContextFactory");

                //openJms默認的端口是1099

                properties.put(Context.PROVIDER_URL,

                     "rmi://localhost:1099/");

            Context context = new InitialContext(properties);
調用ejb時,如果客戶端和ejb不在同一個jvm,就要設置InitialContext,不同的應用服務器InitialContext寫法也不同.
Context.INITIAL_CONTEXT_FACTORY:指定到目錄服務的連接工廠
Context.PROVIDER_URL:目錄服務提供者URL

//jboss:
Context.INITIAL_CONTEXT_FACTORY, "org.jnp.interfaces.NamingContextFactory"
Context.URL_PKG_PREFIXES, "org.jboss.naming"
Context.PROVIDER_URL, "localhost:1099"

//weblogic:
Context.INITIAL_CONTEXT_FACTORY, "weblogic.jndi.WLInitialContextFactory"
Context.PROVIDER_URL, "t3://localhost:7001"

//apusic(金蝶):
Context.INITIAL_CONTEXT_FACTORY, "com.apusic.jndi.InitialContextFactory"
Context.PROVIDER_URL, "rmi://localhost:6888"

//WebSphere:
Context.INITIAL_CONTEXT_FACTORY, "com.ibm.websphere.naming.WsnInitialContextFactory"
Context.PROVIDER_URL, "iiop://localhost:900"


//J2EE  SDK(J2EE  RI):
Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.cosnaming.CNCtxFactory"
Context.PROVIDER_URL, "iiop://127.0.0.1:1050"

//SilverStream:
Context.INITIAL_CONTEXT_FACTORY, "com.sssw.rt.jndi.AgInitCtxFactory"
Context.PROVIDER_URL, "sssw://localhost:80"

//OC4J:
Context.INITIAL_CONTEXT_FACTORY, "com.evermind.server.rmi.RMIInitialContextFactory"
Context.PROVIDER_URL, "ormi://127.0.0.1/"

//WAS5:
Context.INITIAL_CONTEXT_FACTORY, "com.ibm.websphere.naming.WsnInitialContextFactory"
Context.PROVIDER_URL, "iiop://localhost:2809"

 

常用JNDI服務提供者連接工廠:
Filesystem:  Com.sun.jndi.fscontext.FSContextFactory或者com.sun.jndi.fscontext.RefFSContextFactory
LDAPv3:    Com.sun.jndi.ldap.LdapCtxFactory
NDS:     com.novell.naming.service.nds.NdsInitialContextFactory
NIS:     com.sun.jndi.nis.NISCtxFactory
RMI registry: com.sun.jndi.rmi.registry.RegistryContextFactory
IBM LDAP服務提供者:   com.ibm.jndi.LDAPCtxFactory
BEA 名字服務提供者:   weblogic.jndi.WLInitialContextFactory
JBOSS名字服務提供者:  org.jnp.interfaces.NamingContextFactory

評論

# 補充Borland Enterprise Server JNDI用法[未登錄] 2008-12-20 23:08 James

Properties props=new Properties(); 
props.put(Context.PROVIDER_URL,"corbaloc::173.6.7.143:14500/NameService"); 
props.put("java.naming.factory.initial","com.inprise.j2ee.jndi.CtxFactory"); 
Context context = new InitialContext(props); 
// Context context = new InitialContext(); 

Object ref = context.lookup("com/borland/examples/j2ee/hello/Hello"); 
HelloWorldHome home = (HelloWorldHome) javax.rmi.PortableRemoteObject.narrow(ref, HelloWorldHome.class); 
hello = home.create(); 

  

 re: jndi調用時,各種應用服務器InitialContext的寫法 2010-07-12 17:01

jndi調用時,各種應用服務器InitialContext的寫法   

 

websphere容器中spring對datasource的集成

 

JNDI 是什么

 

 

JNDI是 Java 命名與目錄接口(Java Naming and Directory Interface),在J2EE規范中是重要的規范之一,不少專家認為,沒有透徹理解JNDI的意義和作用,就沒有真正掌握J2EE特別是EJB的知識。
那么,JNDI到底起什么作用?

要了解JNDI的作用,我們可以從“如果不用JNDI我們怎樣做?用了JNDI后我們又將怎樣做?”這個問題來探討。

沒有JNDI的做法:
程序員開發時,知道要開發訪問MySQL數據庫的應用,於是將一個對 MySQL JDBC 驅動程序類的引用進行了編碼,並通過使用適當的 JDBC URL 連接到數據庫。
就像以下代碼這樣:

Connection conn=null;
try {
  Class.forName("com.mysql.jdbc.Driver",
                true, Thread.currentThread().getContextClassLoader());
  conn=DriverManager.getConnection("jdbc:mysql://MyDBServer?user=qingfeng&password=mingyue");
  /* 使用conn並進行SQL操作 */
  ......
  conn.close();
}
catch(Exception e) {
  e.printStackTrace();
}
finally {
  if(conn!=null) {
    try {
      conn.close();
    } catch(SQLException e) {}
  }
}


這是傳統的做法,也是以前非Java程序員(如Delphi、VB等)常見的做法。這種做法一般在小規模的開發過程中不會產生問題,只要程序員熟悉Java語言、了解JDBC技術和MySQL,可以很快開發出相應的應用程序。

沒有JNDI的做法存在的問題:
1、數據庫服務器名稱MyDBServer 、用戶名和口令都可能需要改變,由此引發JDBC URL需要修改;
2、數據庫可能改用別的產品,如改用DB2或者Oracle,引發JDBC驅動程序包和類名需要修改;
3、隨着實際使用終端的增加,原配置的連接池參數可能需要調整;
4、......

解決辦法:
程序員應該不需要關心“具體的數據庫后台是什么?JDBC驅動程序是什么?JDBC URL格式是什么?訪問數據庫的用戶名和口令是什么?”等等這些問題,程序員編寫的程序應該沒有對 JDBC 驅動程序的引用,沒有服務器名稱,沒有用戶名稱或口令 —— 甚至沒有數據庫池或連接管理。而是把這些問題交給J2EE容器來配置和管理,程序員只需要對這些配置和管理進行引用即可。

由此,就有了JNDI。

用了JNDI之后的做法:
首先,在在J2EE容器中配置JNDI參數,定義一個數據源,也就是JDBC引用參數,給這個數據源設置一個名稱;然后,在程序中,通過數據源名稱引用數據源從而訪問后台數據庫。
具體操作如下(以JBoss為例):
1、配置數據源
在JBoss的 D:/jboss420GA/docs/examples/jca 文件夾下面,有很多不同數據庫引用的數據源定義模板。將其中的 mysql-ds.xml 文件Copy到你使用的服務器下,如 D:/jboss420GA/server/default/deploy。
修改 mysql-ds.xml 文件的內容,使之能通過JDBC正確訪問你的MySQL數據庫,如下:
<?xml version="1.0" encoding="UTF-8"?>
<datasources>
<local-tx-datasource>
    <jndi-name>MySqlDS</jndi-name>
    <connection-url>jdbc:mysql://localhost:3306/lw</connection-url>
    <driver-class>com.mysql.jdbc.Driver</driver-class>
    <user-name>root</user-name>
    <password>rootpassword</password>
<exception-sorter-class-name>org.jboss.resource.adapter.jdbc.vendor.MySQLExceptionSorter</exception-sorter-class-name>
    <metadata>
       <type-mapping>mySQL</type-mapping>
    </metadata>
</local-tx-datasource>
</datasources>

這里,定義了一個名為MySqlDS的數據源,其參數包括JDBC的URL,驅動類名,用戶名及密碼等。

2、在程序中引用數據源:

Connection conn=null;
try {
  Context ctx=new InitialContext();
  Object datasourceRef=ctx.lookup("java:MySqlDS"); //引用數據源
  DataSource ds=(Datasource)datasourceRef;
  conn=ds.getConnection();
  /* 使用conn進行數據庫SQL操作 */
  ......
  c.close();
}
catch(Exception e) {
  e.printStackTrace();
}
finally {
  if(conn!=null) {
    try {
      conn.close();
    } catch(SQLException e) { }
  }
}

直接使用JDBC或者通過JNDI引用數據源的編程代碼量相差無幾,但是現在的程序可以不用關心具體JDBC參數了。
在系統部署后,如果數據庫的相關參數變更,只需要重新配置 mysql-ds.xml 修改其中的JDBC參數,只要保證數據源的名稱不變,那么程序源代碼就無需修改。

由此可見,JNDI避免了程序與數據庫之間的緊耦合,使應用更加易於配置、易於部署。

JNDI的擴展:
JNDI在滿足了數據源配置的要求的基礎上,還進一步擴充了作用:所有與系統外部的資源的引用,都可以通過JNDI定義和引用。

所以,在J2EE規范中,J2EE 中的資源並不局限於 JDBC 數據源。引用的類型有很多,其中包括資源引用(已經討論過)、環境實體和 EJB 引用。特別是 EJB 引用,它暴露了 JNDI 在 J2EE 中的另外一項關鍵角色:查找其他應用程序組件。

EJB 的 JNDI 引用非常類似於 JDBC 資源的引用。在服務趨於轉換的環境中,這是一種很有效的方法。可以對應用程序架構中所得到的所有組件進行這類配置管理,從 EJB 組件到 JMS 隊列和主題,再到簡單配置字符串或其他對象,這可以降低隨時間的推移服務變更所產生的維護成本,同時還可以簡化部署,減少集成工作。 外部資源”。 


總結:
J2EE 規范要求所有 J2EE 容器都要提供 JNDI 規范的實現。JNDI 在 J2EE 中的角色就是“交換機” —— J2EE 組件在運行時間接地查找其他組件、資源或服務的通用機制。在多數情況下,提供 JNDI 供應者的容器可以充當有限的數據存儲,這樣管理員就可以設置應用程序的執行屬性,並讓其他應用程序引用這些屬性(Java 管理擴展(Java Management Extensions,JMX)也可以用作這個目的)。JNDI 在 J2EE 應用程序中的主要角色就是提供間接層,這樣組件就可以發現所需要的資源,而不用了解這些間接性。

在 J2EE 中,JNDI 是把 J2EE 應用程序合在一起的粘合劑,JNDI 提供的間接尋址允許跨企業交付可伸縮的、功能強大且很靈活的應用程序。這是 J2EE 的承諾,而且經過一些計划和預先考慮,這個承諾是完全可以實現的。

三.JMS和事務
JMS提供兩種事務控制方式,使用事務性的session,在JTA全局事務中使用JMS。
1消息生產者發送的消息會被緩存,在事務被提交之前,消息消費者不會接受到

任何未提交的消息,當消息生產者完成一次業務邏輯之后,消息生產者執行提交

事務,之前所有發送的消息才會被整體性地傳遞到消息消費者,如果事務回滾,

JMS服務器會直接丟棄所有緩存的消息。而對於消息消費者,在接收到並處理多

個消息成功之后,消息消費者提交事務,此時才會向消息生產者確認之前收到的

所有消息。如果事務回滾,JMS服務器會把所有消息退還給相關的消息隊列和消

息主題。這里要注意,使用事務性session時,只是控制有關JMS的操作成為一個

整體,而如果要把有關EJB的操作,數據庫的操作和JMS的操作都看成是一個整體

的話,我們就要使用JTA全局事務。
2.JTA全局事務,
什么是JTA,JTA,即Java Transaction API,譯為Java事務API。我的理解是,

JTA允許兩個或多個網絡計算機上的java平台的組件參與到一個JTA事務中。
在JMS中如何使用?通過JNDI查找來獲得JTA服務器的引用。如:

UserTransaction tx = (UserTransaction)ctx.lookup("javax.transaction.UserTransaction");

tx.begin();

...

tx.commit();

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM