[原创]什么是JNDI?_Tomcat, WebLogic及J2EE讨论区_Weblogic技术|Tuxedo技术|中间件技术|Oracle论坛|JAVA论坛|Linux/Unix技术|hadoop论坛_联动北方技术论坛  
网站首页 | 关于我们 | 服务中心 | 经验交流 | 公司荣誉 | 成功案例 | 合作伙伴 | 联系我们 |
联动北方-国内领先的云技术服务提供商
»  游客             当前位置:  论坛首页 »  自由讨论区 »  Tomcat, WebLogic及J2EE讨论区 »
总帖数
1
每页帖数
101/1页1
返回列表
0
发起投票  发起投票 发新帖子
查看: 3034 | 回复: 0   主题: [原创]什么是JNDI?        下一篇 
panpan.nie
注册用户
等级:大校
经验:4754
发帖:217
精华:2
注册:1970-1-1
状态:离线
发送短消息息给panpan.nie 加好友    发送短消息息给panpan.nie 发消息
发表于: IP:您无权察看 2014-10-10 16:06:48 | [全部帖] [楼主帖] 楼主

JNDI(Java Naming and Directory Interface,Java命名和目录接口),是java平台的一个标准扩展,提供了一组接口、类名空间的概念,可以理解为一种将对象和名字捆绑的技术,对象工厂负责生产处对象,这些对象都和唯一的名字绑在一起,外部资源可以通过名字获得某对象的引用。

可以这么理解:一般使用JDBC连接数据库时,我们需要加载JDBC驱动包和类名,引入数据库服务器名称、用户名、口令等,但这些参数因人而异,一旦改变会使后台代码变动。而使用了JNDI相当于提供了一个配置文件即定义一个数据源,去配置这些参数也就是JDBC引用参数,给这个数据源设置一个名称;然后,在程序中,通过数据源名称引用数据源从而访问后台数据库。

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

没有JNDI的做法:

比如,我们需要访问MySQL数据库的应用,会加载驱动,使用JDBC URL连接到数据库。代码如下:

static String driver = "com.mysql.jdbc.Driver";//驱动程序
String url = "jdbc:mysql://localhost/ppnie";//url指向要访问的数据库名
String user = "root";//Mysql配置时的用户名
String password = "root";//mysql配置时的密码


publicvoid queryDB(String sql)
{
      Connection conn = null;
      Statement stmt = null;
      ResultSet rs = null;
      try {
            Class.forName(driver);//加载驱动程序


            conn = DriverManager.getConnection(url,user,password);//连接数据库
            stmt = conn.createStatement();
            rs = stmt.executeQuery(sql);
            ……
      }
      catch (Exception e)
      {
            e.printStackTrace();
      }
      finally
      {
            if(conn!=null)
            {
                  try {
                        conn.close();
                  } catch (SQLException e) {
                        e.printStackTrace();
                  }
            }
      }
}


没有JNDI的做法存在的问题:

1、数据库服务器名称MyDBServer 、用户名和口令都可能需要改变,由此引发JDBC URL需要修改;

2、数据库可能改用别的产品,如改用DB2或者Oracle,引发JDBC驱动程序包和类名需要修改;

3、随着实际使用终端的增加,原配置的连接池参数可能需要调整;

4、......

解决办法:

程序员应该不需要关心“具体的数据库后台是什么?JDBC驱动程序是什么?JDBC URL格式是什么?访问数据库的用户名和口令是什么?”等等这些问题,程序员编写的程序应该没有对 JDBC 驱动程序的引用,没有服务器名称,没有用户名称或口令 —— 甚至没有数据库池或连接管理。而是把这些问题交给J2EE容器来配置和管理,程序员只需要对这些配置和管理进行引用即可。

由此,就有了JNDI

用了JNDI之后的做法:

首先,在在J2EE容器中配置JNDI参数,定义一个数据源,也就是JDBC引用参数,给这个数据源设置一个名称;然后,在程序中,通过数据源名称引用数据源从而访问后台数据库。

在javax.naming.* 包中提供了Context 接口,其中有方法:

<1> void bind( String name , Object object )


    将名称绑定到对象。所有中间上下文和目标上下文(由该名称最终原子组件以外的其他所有组件指定)都必须已经存在。 

<2>Object lookup( String name )


    检索指定的对象。如果 name为空,则返回此上下文的一个新实例(该实例表与此上下文相同的命名上下文,但其环境可以独立地进行修改,而且可以并发访问)。

原理:

在DataSource中事先建立多个数据库连接,保存在数据库连接池中。当程序访问数据库时,只用从连接池中取空闲状态的数据库连接即可,访问结束,销毁资源,数据库连接重新回到连接池,这与每次去直接访问数据库相比,会节省大量时间和资源。

运行机制: 

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() 方法并没有关闭事实上的数据库连接,仅仅是释放了被应用程序占用的数据库连接,并将它还给数据库连接缓冲池,数据库连接缓冲池会自动将这个数据库连接交给请求队列中下一个的应用程序使用。

代码实现:

String JNDINAME="MySqlDS"; // 已配置的数据源
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
String sql = "select * from temp;";
try {
      Context ctx = new InitialContext();
      Object datasourceRef = ctx.lookup(JNDINAME);
      DataSource ds = (DataSource)datasourceRef;
      conn = ds.getConnection();
      stmt = conn.createStatement();
      rs = stmt.executeQuery(sql);
      while(rs.next())
      {
      }
} catch (NamingException e) {
      e.printStackTrace();
} catch (SQLException e) {
      e.printStackTrace();
}
finally
{
if(conn!=null)
{
      try
      {
            conn.close();
      }
      catch (SQLException e)
      {
            e.printStackTrace();
      }
}
}




赞(0)    操作        顶端 
总帖数
1
每页帖数
101/1页1
返回列表
发新帖子
请输入验证码: 点击刷新验证码
您需要登录后才可以回帖 登录 | 注册
技术讨论