什么是JNDI?



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配置时的密码

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

    /*使用conn 进行数据库SQL操作*/

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

        }

    }

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值