码迷,mamicode.com
首页 > 其他好文 > 详细

JNDI

时间:2016-08-06 00:16:37      阅读:196      评论:0      收藏:0      [点我收藏+]

标签:

JNDI基础
一 简介
1.JNDI:Java Naming and Directory Interface,即Java命名和目录接口。JNDI包含了一些标准API接口,Java程序可以通过这些接口来访问命名目录服务。JNDI不依赖于任何独立的命名目录服务器,不管采用哪种命名目录服务器,应用程序都可以通过统一的JNDI接口来调用。要使用JNDI,必须要安装jdk 1.3以上版本。
2.命名服务:就是将名字和计算机系统内的一个对象建立关联,从而允许应用程序通过该名字访问该对象。简而言之,命名服务就是为计算机系统内的对象起名字。
例如在Internet上的域名服务 (domain naming service,DNS) 就是提供将域名映射到IP地址的命名服务,在打开网站时一般都是 在浏览器中输入名字,通过DNS找到相应的IP地址,然后打开。所有的因特网通信都使用TCP、UDP或IP协议。IP地址由4个字节32位二进制数字组成,数字和名字相比,对于人来说名字比数字要容易记忆,但对于计算机来讲,它更善于处理数字。
其实所有的命名服务都提供DNS这种基本功能,即一个系统向命名服务注册,命名服务提供一个值到另一个值的映射。然后,另外一个系统访问命名服务就可以取得映射信息。这种交互关系对分布式企业级应用来讲显得非常重要。
3.目录服务:目录服务是命名服务的拓展,目录服务不仅需要保存名称和对象的关联,还要保存对象的各种属性,这样就允许开发者操作对象的属性,包括增删改查对象的属性。在目录服务中,你可以根据属性搜索对象。JNDI允许你访问文件系统中的文件,定位远程RMI注册的对象,访问象LDAP这样的目录服务,定位网络上的EJB组件。从我们日常生活中去理解目录服务的概念可以从电话簿说起,电话簿本身就是一个比较典型的目录服务,如果你要找到某个人的电话号码,你需要从电话簿里找到这个人的名称,然后再看其电话号码。
4.JNDI结构
技术分享

 

技术分享
JNDI结构包括JNDI API和JNDI SPI
开发者通过JNDI API以一致的方式来访问各种命名服务、目录服务,而JNDI API则保证各种命名服务、目录服务透明的加入JNDI结构中,Naming Manager则负责管理二者之间的转换。。
在开发企业级应用时,JNDI显得尤其重要:客户端代码可以通过JNDI来访问EJB,客户端代码需要通过JNDI来访问容器管理的数据源......Java EE应用中所有远程对象都需要通过JNDI来访问。
二 使用JNDI配置数据源
1.数据源的由来
在Java开发中,使用JDBC操作数据库的四个步骤如下:
加载数据库驱动程序(Class.forName("数据库驱动类");)
连接数据库(Connection con  = DriverManager.getConnection();)
操作数据库(PreparedStatement stat = con.prepareStatement(sql);stat.executeQuery();)
关闭数据库,释放连接(con.close();)
也就是说,所有的用户都需要经过此四步进行操作,但是这四步之中有三步(加载数据库驱动程序、连接数据库、关闭数据库,释放连接)对所有人都是一样的,而所有人只有在操作数据库上是不一样,那么这就造成了性能的损耗。
那么最好的做法是,准备出一个空间,此空间里专门保存着全部的数据库连接,以后用户用数据库操作的时候不用再重新加载驱动、连接数据库之类的,而直接从此空间中取走连接,关闭的时候直接把连接放回到此空间之中。
那么此空间就可以称为连接池(保存所有的数据库连接),但是如果要想实现此空间的话,则必须有一个问题要考虑?
如果没有任何一个用户使用连接,那么那么应该维持一定数量的连接,等待用户使用。
如果连接已经满了,则必须打开新的连接,供更多用户使用。
如果一个服务器就只能有100个连接,那么如果有第101个人过来呢?应该等待其他用户释放连接
如果一个用户等待时间太长了,则应该告诉用户,操作是失败的。
直接用程序实现以上功能,则会比较麻烦,所以在Tomcat 4.1.27之后,在服务器上就直接增加了数据源的配置选项, 直接在服务器上配置好数据源连接池即可。在J2EE服务器上保存着一个数据库的多个连接。每一个连接通过DataSource可以找到。DataSource被绑定在了JNDI树上(为每一个DataSource提供一个名字)客户端通过名称找到在JNDI树上绑定的DataSource,再由DataSource找到一个连接。如下图所示:
技术分享

 

技术分享
那么在以后的操作中,除了数据库的连接方式不一样之外,其他的所有操作都一样,只是关闭的时候不是彻底地关闭数据库,而是把数据库的连接放回到连接池中去。
2.在tomcat中配置JNDI
主要包括三种方式:web.xml    context.xml    server.xml
这三种的区别是,server.xml与context.xml类似都是所有应用通用的,但是context.xml只是把它分离出来单独形成了一个文件而已。在WEB-INF/下的context.xml则是应用自己的,所以如果不想把某些信息公开,放在这里就可以了。
(1)server.xml方式
这种方式设置的是全局JNDI配置,在server.xml下配置你必需重启服务器才能生效,而context.xml配置保存后tomcat会自动加载无需重启。
Step1:在tomcat服务器的lib目录下加入数据库连接的驱动jar包,如
mysql-connector-java-5.1.27.jar  -->mySql数据库的jar包
ojdbc14.jar   -->Oracle数据库的jar包
sqljdbc4.jar   -->SQLServer数据库的jar包
Step2:
(1)server.xml方式
修改tomcat服务器的conf目录下的server.xml配置文件
在server.xml配置文件中有一个自带的全局JNDI配置,如图:
技术分享

 

技术分享
在server.xml中添加全局JNDI数据源配置,在<GlobalNamingResources>下继续添加<Resource>标签,常见的几个数据库的配置如下所示:
<!--配置Oracle数据库的JNDI数据源-->
<Resource
        name="jdbc/oracle"
        auth="Container"
        type="javax.sql.DataSource"
        maxActive="100"
        maxIdle="30"
        maxWait="10000"
        username="lead_oams"
        password="p"
        driverClassName="oracle.jdbc.driver.OracleDriver"
        url="jdbc:oracle:thin:@192.168.1.229:1521:lead"/>
 
<!--配置MySQL数据库的JNDI数据源-->
<Resource
        name="jdbc/mysql"
        auth="Container"
        type="javax.sql.DataSource"
        maxActive="100"
        maxIdle="30"
        maxWait="10000"
        username="root"
        password="root"
        driverClassName="com.mysql.jdbc.Driver"
        url="jdbc:mysql://192.168.1.144:3306/leadtest?useUnicode=true&amp;characterEncoding=utf-8"/>
 
<!--配置SQLServer数据库的JNDI数据源-->
<Resource
        name="jdbc/sqlserver"
        auth="Container"
        type="javax.sql.DataSource"
        maxActive="100"
        maxIdle="30"
        maxWait="10000"
        username="sa"
        password="p@ssw0rd"
        driverClassName="com.microsoft.sqlserver.jdbc.SQLServerDriver"
        url="jdbc:sqlserver://192.168.1.51:1433;DatabaseName=demo"/>
其中,name:表示以后要查找的名称。通过此名称可以找到DataSource,此名称任意更换,但是程序中最终要查找的就是此名称,为了不与其他的名称混淆,所以使用jdbc/oracle,现在配置的是一个jdbc的关于oracle的命名服务。
auth:由容器进行授权及管理,指的用户名和密码是否可以在容器上生效
type:此名称所代表的类型,现在为javax.sql.DataSource
maxActive:表示一个数据库在此服务器上所能打开的最大连接数
maxIdle:表示一个数据库在此服务器上维持的最小连接数
maxWait:最大等待时间。10000毫秒
(2)context.xml方式
选择你所要连接的数据库,打开comcat下的config里的context.xml,将<resource>下的内容复制过去
<Context>
    <WatchedResource>WEB-INF/web.xml</WatchedResource>
    <Resource
        name="jdbc/mysql"
        auth="Container"
        driverClassName="com.mysql.jdbc.Driver"
        type="javax.sql.DataSource"
        maxActive="100"
        maxIdle="30"
        maxWait="10000"
        username="root"
        password="123456"     
        url="jdbc:mysql://localhost:3306/mydb?useUnicode=true&amp;characterEncoding=utf-8"/>
</Context>
Step3:测试
在项目的WEB-INF的web.xml文件中添加JNDI配置的资源引用:
 <!--Oracle数据库JNDI数据源引用 -->
  <resource-ref>
      <description>Oracle DB Connection</description>
      <res-ref-name>oracleDataSource</res-ref-name>
      <res-type>javax.sql.DataSource</res-type>
      <res-auth>Container</res-auth>
 </resource-ref>
 
  <!--MySQL数据库JNDI数据源引用 -->
  <resource-ref>
      <description>MySQL DB Connection</description>
      <res-ref-name>mysqlDataSource</res-ref-name>
      <res-type>javax.sql.DataSource</res-type>
      <res-auth>Container</res-auth>
  </resource-ref>
 
  <!--SQLServer数据库JNDI数据源引用 -->
  <resource-ref>
      <description>SQLServer DB Connection</description>
      <res-ref-name>sqlserverDataSource</res-ref-name>
      <res-type>javax.sql.DataSource</res-type>
      <res-auth>Container</res-auth>
  </resource-ref>
JNDI配置的资源引用包括:
res-ref-name:表示引用资源的名称
res-type:此资源对应的类型为javax.sql.DataSource
res-auth:容器授权管理
(2)编写测试内容
<%@ page import="java.sql.*,javax.sql.*,javax.naming.*"  %>
<%
  Connection conn=null; 
  try
  {
   //初始化查找命名空间
   Context ctx = new InitialContext();
   //InitialContext ctx = new InitialContext();亦可
   //找到DataSource,对名称进行定位java:comp/env是必须加的,后面跟你的DataSource名
   DataSource ds = (DataSource)ctx.lookup("java:comp/env/jdbc/mysql");
   //取出连接
   conn = ds.getConnection();
   System.out.println("connection pool connected !!");   
  } catch (NamingException e) {
   System.out.println(e.getMessage());
  } catch (SQLException e) {
   e.printStackTrace();
  }finally { 
      if(conn!=null) { 
          try { 
          conn.close(); 
          } catch(SQLException e) { } 
    } 
  }
%>
报错:org.apache.tomcat.dbcp.dbcp.SQLNestedException: Cannot create JDBC driver of class ‘‘ for connect URL ‘null‘
三 JNDI常用操作
1.JNDI架构提供了一组标准命名系统的API,这些API在JDK1.3之前是作为一个单独的扩展包jndi.jar(通过这个地址下载),这个基础API构建在与SPI之上。这个API提供如下五个包javax.naming,javax.naming.directory,javax.naming.event,javax.naming.ldap,javax.naming.spi
2.通过JNDI来访问被绑定对象要按一下操作:
(1)创建Context对象
(2)调用Context的lookup方法根据JNDI名称查找被绑定对象;或者调用bind方法来执行绑定;或者调用unbind方法来解除绑定...就是调用Context的方法来执行绑定、查找等操作。
(3)关闭Context
3.Context只是一个接口,通常会使用它的实现类InitialContext来创建实例。InitialContext提供了两个构造器:
InitialContext():读取系统属性作为Context属性来创建InitialContext
InitialContext(Hashtable<?,?> environment):以environment参数指定的属性作为Context属性来创建InitialContext
如果创建InitialContext对象时没有传入任何参数,那么它必须能从系统属性(System.getProperties()方法返回值)中读到合适的Context属性来执行初始化,否则它将抛出NoInitialContextException异常。
在JSP页面中执行以下代码:
<%
  Properties props=System.getProperties();
    for(String name:props.stringPropertyNames()){
        out.println(name+"--->"+props.getProperty(name)+"<br/>");
    }
%>
会看到如下的结果:
技术分享
技术分享
由此可见,当在服务器环境下的Web应用中创建InitialContext时,由于服务器启动时已经添加了它所需的系统属性,因此直接创建InitialContext()就可以了。
Hashtable至少包含如下两个key:
java.naming.factory.initial:可用Context内的INITIA_CONTEXT_FACTORY常量代替,该key的值应该为初始化Context的工厂类。
java.naming.providor.url:可用Context内的PROVIDER_URL常量代替,该key的值应该为Context服务提供者的URL
4.举例
以文件系统的JNDI为例,创建如下InitialContext对象:
public class myTest {
    public static void main(String[] args) throws NamingException {
        final String fileName="lyy.doc";
        Hashtable env=new Hashtable();
        env.put(Context.INITIAL_CONTEXT_FACTORY,"org.apache.naming.java.javaURLContextFactory");
        env.put(Context.PROVIDER_URL, "file:/d:/wscite");
        Context ctx=new InitialContext(env);
        Object file=ctx.lookup(fileName);
        System.out.println(fileName+"名称被绑定到:"+file);
        ctx.close();
    }
}
报错:java.lang.NoClassDefFoundError: org/apache/juli/logging/LogFactory
打开window->Preferences->你所用的jdk版本->edit->add external jars->选择tomact包里的bin的tomcat-juli.jar->添加
上面的程序将d:/wscite目录作为一个Context,然后以此Context来查找对应的名称。对于文件系统的JNDI来说,每个文件夹相当于一个Context,每个文件名相当于一个JNDI名,而文件对象则是实际被绑定的对象。
方法:
(1)查找对象
通过Context提供的lookup(jndi)方法来实现,该方法接受被绑定的JNDI名,返回与之绑定的对象
该方法只能返回一个Object类型的对象,因此要注意强制类型转换
(2)绑定
JNDI通过Context的bind(String name,Object obj)方法来执行绑定,第一个参数是被绑定的JNDI名,第二个参数是被绑定的对象
该方法就相当于为obj对象起了一个name
(3)重新绑定
rebind(String name,Object obj),如果该名称已被绑定,则是修改,如果没绑定就与bind功能相同。

JNDI

标签:

原文地址:http://www.cnblogs.com/lyy-2016/p/5742958.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!