JNDI的理解

JNDI的一篇文章



JNDI全面总结
原理:
         在DataSource中事先建立多个数据库连接,保存在数据库连接池中。当程序访问数据库时,只用从连接池中取空闲状态的数据库连接即可,访问结束,销毁资源,数据库连接重新回到连接池,这与每次去直接访问数据库相比,会节省大量时间和资源。
         JNDI( Java Naming and Directory Interface ),是Java平台的一个标准扩展,提供了一组接口、类和关于命名空间的概念。如同其它很多Java技术一样,JDNI是provider-based的技术,暴露了一个 API和一个服务供应接口(SPI)。这意味着任何基于名字的技术都能通过JNDI而提供服务,只要JNDI支持这项技术。JNDI目前所支持的技术包括 LDAP、CORBA Common Object Service(COS)名字服务、RMI、NDS、DNS、Windows注册表等等。很多J2EE技术,包括EJB都依靠JNDI来组织和定位实体。可以把它理解为一种将对象和名字捆绑的技术,对象工厂负责生产出对象,这些对象都和唯一的名字绑在一起,外部资源可以通过名字获得某对象的引用。
          在javax.naming的包包中提供Context接口,提供了两个很好用的方法:
<1> void bind( String name , Object object )
        将名称绑定到对象。所有中间上下文和目标上下文(由该名称最终原子组件以外的其他所有组件指定)都必须已经存在。
<2>Object lookup( String name )
       检索指定的对象。如果 name为空,则返回此上下文的一个新实例(该实例表示与此上下文相同的命名上下文,但其环境可以独立地进行修改,而且可以并发访问)。
运行机制:
1、 首先程序代码获取初始化的 JNDI 环境并且调用 Context.lookup() 方法从 JNDI 服务提供者那里获一个 DataSource 对象
2、 中间层 JNDI 服务提供者返回一个 DataSource 对象给当前的 Java 应用程序这个 DataSource 对象代表了中间层服务上现存的缓冲数据源
 3、 应用程序调用 DataSource 对象的 getConnection() 方法
4、 当 DataSource 对象的 getConnection() 方法被调用时,中间层服务器将查询数据库 连接缓冲池中有没有 PooledConnection 接口的实例对象。这个 PooledConnection 对象将被用于与数据库建立物理上的数据库连接
5、 如果在缓冲池中命中了一个 PooledCoonection 对象那么连接缓冲池将简单地更 新内部的缓冲连接队列并将该 PooledConnection 对象返回。如果在缓冲池内没 有找到现成的 PooledConnection 对象,那么 ConnectionPoolDataSource 接口将会被 用来产生一个新的 PooledConnection 对象并将它返回以便应用程序使用
6。 中间层服务器调用 PooledConnection 对象的 getConnection() 方法以便返还一个 java.sql.Connection 对象给当前的 Java 应用程序
7、 当中间层服务器调用 PooledConnection 对象的 getConnection() 方法时, JDBC 数据 库驱动程序将会创建一个 Connection 对象并且把它返回中间层服务器
8、 中间层服务器将 Connection 对象返回给应用程序 Java 应用程序,可以认为这个 Connection 对象是一个普通的 JDBC Connection 对象使用它可以和数据库建立。事 实上的连接与数据库引擎产生交互操作 。
9、 当应用程序不需要使用 Connection 对象时,可以调用 Connection 接口的 close() 方 法。请注意这种情况下 close() 方法并没有关闭事实上的数据库连接,仅仅是释 放了被应用程序占用的数据库连接,并将它还给数据库连接缓冲池,数据库连接 缓冲池会自动将这个数据库连接交给请求队列中下一个的应用程序使用。
现在,数据库的连接没有用到连接池几乎很少很少,每个项目组都可能有自己的数据库连接池组件,各容器提供商也提供了各自的数据库连接池,下面介绍一下tomcat的数据库连接管理。
tomcat6 数据源配置(server.xml方式和context.xml方式)
在server.xml下配置你必需重启服务器才能生效,而context.xml配置保存后tomcat会自动加载无需重启
在JNDI配配置数据源中需注意:项目下需要引入数据库驱动包,并且TOMCAT下也需要引入,不然会报错的
1.context.xml方式
Tomcat-6.0.26\conf\context.xml文件当添加以下的配置信息:
<Resource name="jdbc/mysql" auth="Container" type="javax.sql.DataSource"
               maxActive="100" maxIdle="30" maxWait="60" wait_timeout="18800" timeBetweenEvictionRunsMillis="300000" 		                                            		minEvictableIdleTimeMillis="600000"
               username="root" password="jdzxdb" driverClassName="com.mysql.jdbc.Driver"
               url="jdbc:mysql://localhost:3306/sxtele?comautoReconnect=true&failOverReadOnly=false"  removeAbandoned="true" 			            		removeAbandonedTimeout="60" logAbandoned="true"/>
 <Resource name="jdbc/db2" auth="Container" type="javax.sql.DataSource"
               maxActive="100" maxIdle="30" maxWait="60" wait_timeout="18800" timeBetweenEvictionRunsMillis="300000"   					       		minEvictableIdleTimeMillis="600000"
               username="lcgluser" password="lcgluser" driverClassName="com.ibm.db2.jcc.DB2Driver"
               url="jdbc:db2://133.64.46.65:50000/STEDWDB"  removeAbandoned="true" removeAbandonedTimeout="60" logAbandoned="true"/>
 其中:
name 表示指定的jndi名称
auth 表示认证方式,一般为Container
type 表示数据源床型,使用标准的javax.sql.DataSource
maxActive 表示连接池当中最大的数据库连接
maxIdle 表示最大的空闲连接数
maxWait 当池的数据库连接已经被占用的时候,最大等待时间
logAbandoned 表示被丢弃的数据库连接是否做记录,以便跟踪
username 表示数据库用户名
password 表示数据库用户的密码
driverClassName 表示JDBC DRIVER
url 表示数据库URL地址
 
注意,这里你配置的name值要和程序中使用的是一样的,比如按照这个例子,程序就应该是这样的
Java代码
      String gENV = "java:comp/env/";  
      Context ctx = new InitialContext();    
      DataSource ds = (DataSource)ctx .lookup(gENV+"jdbc/mysql");  
      Connection conn = ds.getConnection(); 
      String gENV = "java:comp/env/";
      Context ctx = new InitialContext();
      DataSource ds = (DataSource)ctx.lookup(gENV+"jdbc/db2");
      Connection conn = ds.getConnection();
 
关于获取数据源的语法,大体有(javax.sql.DataSource) ctx.lookup ("java:comp/env/XXX")和(javax.sql.DataSource) ctx.lookup("XXX")两种写法,好多人以为这两种写法是相同的,以为都是通过JNDI来获取数据源。其实java:comp/env和 JNDI是不同的,java:comp/env 是环境命名上下文(environment naming context(ENC)),是在EJB规范1.1以后引入的,引入这个是为了解决原来JNDI查找所引起的冲突问题,也是为了提高EJB或者J2EE应用的移植性。ENC是一个引用,引用是用于定位企业应用程序的外部资源的逻辑名。引用是在应用程序部署描述符文件中定义的。在部署时,引用被绑定到目标可操作环境中资源的物理位置(JNDI名)。使用ENC是把对其它资源的JNDI查找的硬编码解脱出来,通过配置这个引用可以在不修改代码的情况下,将引用指向不同的EJB(JNDI)。 在J2EE中的引用常用的有




前端时间总是在搞不清JNDI到底是干什么,虽然是一值在用,却不知道他最初出现的原因,用来,说不清是用来干什么,下面我相信介能解开这个迷雾里。

转贴一篇】 
------------ 
JNDI是 Java 命名与目录接口(Java Naming and Directory Interface),在J2EE规范中是重要的规范之一,不少专家认为,没有透彻理解JNDI的意义和作用,就没有真正掌握J2EE特别是EJB的知识。 

那么,JNDI到底起什么作用? //带着问题看文章是最有效的 

要了解JNDI的作用,我们可以从“如果不用JNDI我们怎样做?用了JNDI后我们又将怎样做?”这个问题来探讨。 

没有JNDI的做法: 

程序员开发时,知道要开发访问MySQL数据库的应用,于是将一个对 MySQL JDBC 驱动程序类的引用进行了编码,并通过使用适当的 JDBC URL 连接到数据库。 
就像以下代码这样: 

Java代码 
  1. Connection conn=null;  
  2. try {  
  3.   Class.forName("com.mysql.jdbc.Driver",  
  4.                 true, Thread.currentThread().getContextClassLoader());  
  5.   conn=DriverManager.  
  6.     getConnection("jdbc:mysql://MyDBServer?user=qingfeng&password=mingyue");  
  7.   ......  
  8.   conn.close();  
  9. catch(Exception e) {  
  10.   e.printStackTrace();  
  11. finally {  
  12.   if(conn!=null) {  
  13.     try {  
  14.       conn.close();  
  15.     } catch(SQLException e) {}  
  16.   }  
  17. }  



这是传统的做法,也是以前非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引用参数,给这个数据源设置一个名称;然后,在程序中,通过数据源名称引用数据源从而访问后台数据库。 

//红色的字可以看出,JNDI是由j2ee容器提供的功能 

具体操作如下(以JBoss为例): 
1、配置数据源 
在JBoss 的 D:\jboss420GA\docs\examples\jca 文件夹下面,有很多不同数据库引用的数据源定义模板。将其中的 mysql-ds.xml 文件Copy到你使用的服务器下,如 D:\jboss420GA\server\default\deploy。 
修改 mysql-ds.xml 文件的内容,使之能通过JDBC正确访问你的MySQL数据库,如下: 
Java代码 
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <datasources>  
  3. <local-tx-datasource>  
  4.     <jndi-name>MySqlDS</jndi-name>  
  5.     <connection-url>jdbc:mysql://localhost:3306/lw</connection-url>  
  6.     <driver-class>com.mysql.jdbc.Driver</driver-class>  
  7.     <user-name>root</user-name>  
  8.     <password>rootpassword</password>  
  9. <exception-sorter-class-name>  
  10. org.jboss.resource.adapter.jdbc.vendor.MySQLExceptionSorter  
  11. </exception-sorter-class-name>  
  12.     <metadata>  
  13.        <type-mapping>mySQL</type-mapping>  
  14.     </metadata>  
  15. </local-tx-datasource>  
  16. </datasources>  


这里,定义了一个名为MySqlDS的数据源,其参数包括JDBC的URL,驱动类名,用户名及密码等。 

2、在程序中引用数据源: 

Java代码 
  1. Connection conn=null;  
  2. try {  
  3.   Context ctx=new InitialContext();  
  4.   Object datasourceRef=ctx.lookup("java:MySqlDS"); //引用数据源  
  5.   DataSource ds=(Datasource)datasourceRef;  
  6.   conn=ds.getConnection();  
  7.   ......  
  8.   c.close();  
  9. catch(Exception e) {  
  10.   e.printStackTrace();  
  11. finally {  
  12.   if(conn!=null) {  
  13.     try {  
  14.       conn.close();  
  15.     } catch(SQLException e) { }  
  16.   }  
  17. }  


直接使用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 规范的实现。 //sun 果然喜欢制定规范JNDI 在 J2EE 中的角色就是“交换机” —— J2EE 组件在运行时间接地查找其他组件、资源或服务的通用机制。在多数情况下,提供 JNDI 供应者的容器可以充当有限的数据存储,这样管理员就可以设置应用程序的执行属性,并让其他应用程序引用这些属性(Java 管理扩展(Java Management Extensions,JMX)也可以用作这个目的)。JNDI 在 J2EE 应用程序中的主要角色就是提供间接层,这样组件就可以发现所需要的资源,而不用了解这些间接性。 

在 J2EE 中,JNDI 是把 J2EE 应用程序合在一起的粘合剂,JNDI 提供的间接寻址允许跨企业交付可伸缩的、功能强大且很灵活的应用程序。这是 J2EE 的承诺,而且经过一些计划和预先考虑,这个承诺是完全可以实现的。 


从上面的文章中可以看出: 
1、JNDI 提出的目的是为了解藕,是为了开发更加容易维护,容易扩展,容易部署的应用。 
2、JNDI 是一个sun提出的一个规范(类似于jdbc),具体的实现是各个j2ee容器提供商,sun   只是要求,j2ee容器必须有JNDI这样的功能。 
3、JNDI 在j2ee系统中的角色是“交换机”,是J2EE组件在运行时间接地查找其他组件、资源或服务的通用机制。 
4、JNDI 是通过资源的名字来查找的,资源的名字在整个j2ee应用中(j2ee容器中)是唯一的。 

再转一篇文章: 


JNDI全称 Java Naming and Directory Interface 
JNDI是Java平台的一个标准扩展,提供了一组接口、类和关于命名空间的概念。如同其它很多Java技术一样,JDNI是provider-based的技术,暴露了一个API和一个服务供应接口(SPI)。这意味着任何基于名字的技术都能通过JNDI而提供服务,只要JNDI支持这项技术。JNDI目前所支持的技术包括LDAP、CORBA Common Object Service(COS)名字服务、RMI、NDS、DNS、Windows注册表等等。很多J2EE技术,包括EJB都依靠JNDI来组织和定位实体。 
JDNI通过绑定的概念将对象和名称联系起来。在一个文件系统中,文件名被绑定给文件。在DNS中,一个IP地址绑定一个URL。在目录服务中,一个对象名被绑定给一个对象实体。 
JNDI中的一组绑定作为上下文来引用。每个上下文暴露的一组操作是一致的。例如,每个上下文提供了一个查找操作,返回指定名字的相应对象。每个上下文都提供了绑定和撤除绑定名字到某个对象的操作。JNDI使用通用的方式来暴露命名空间,即使用分层上下文以及使用相同命名语法的子上下文。 
jndi的用途: 
1。你可以用jndi来得到object类的属性 
如: 
Java代码 
  1. Attribute attr =directory.getAttributes(personName).get("email");   
  2. String email = (String)attr.get();   

2。你可以用jndi来搜索对象 
如: 
Java代码 
  1. foxes = directory.search("o=Wiz,c=US""sn=Fox", controls);   

查找谁的名字叫Fox在wiz部门的员工? 
3。你可以用jndi通过naming/directory服务查询像printers和databases的对象 
如:查询 Printer 
Java代码 
  1. Printer printer = (Printer)namespace.lookup(printerName);   
  2. printer.print(document);   

4。你可以用jndi列表出命名空间的特殊级别的内容 
如: 
Java代码 
  1. NamingEnumeration list = namespace.list("o=Widget, c=US";   
  2. while (list.hasMore()) {   
  3. NameClassPair entry = (NameClassPair)list.next();   
  4. display(entry.getName(), entry.getClassName());   
  5. }   
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值