通过JNDI使用数据源 在本节首先给出了一个实际程序,然后通过程序来讲解如何通过JNDI查询数据源。 import java.sql.*; import javax.sql.*; import oracle.jdbc.driver.*; import oracle.jdbc.pool.OracleDataSource; import javax.naming.*; import javax.naming.spi.*; import java.util.Hashtable; public class DataSourceJNDI { public static void main (String args []) throws SQLException { // 初始化名称服务环境 Context ctx = null; try { Hashtable env = new Hashtable (5); env.put (Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.fscontext.RefFSContextFactory"); env.put (Context.PROVIDER_URL, "file:JNDI"); ctx = new InitialContext(env); } catch (NamingException ne) { ne.printStackTrace(); } bind(ctx, "jdbc/chidb"); lookup(ctx, "jdbc/chidb"); } static void bind (Context ctx, String ln) throws NamingException, SQLException { // 创建一个OracleDataSource实例 OracleDataSource ods = new OracleDataSource(); ods.setDriverType("thin"); ods.setServerName("Chicago"); ods.setNetworkProtocol("tcp"); ods.setDatabaseName("chidb"); ods.setPortNumber(1521); ods.setUser("guest"); ods.setPassword("guest"); // 把OracleDataSource实例注册到JNDI中 System.out.println ("Doing a bind with the logical name : " + ln); ctx.bind (ln,ods); System.out.println ("Successfully bound"); } static void lookup (Context ctx, String ln) throws NamingException, SQLException { // 从JNDI中查询OracleDataSource实例 System.out.println ("Doing a lookup with the logical name : " + ln); OracleDataSource ods = (OracleDataSource) ctx.lookup (ln); System.out.println ("Successful lookup"); // 从查询到的OracleDataSource实例中获取数据库连接 Connection conn = ods.getConnection(); // 进行数据库操作 getUserName(conn); // 关闭连接 conn.close(); conn = null; } static void getUserName(Connection conn) throws SQLException { // 生成一个Statement实例 Statement stmt = conn.createStatement (); // 从addressbook表中选中姓名列 ResultSet rset = stmt.executeQuery ("select NAME from addressbook"); // 列出addressbook表所有人的姓名 while (rset.next ()) System.out.println ("Name is " + rset.getString (1)); // 关闭RseultSet实例 rset.close(); rset = null; // 关闭Statement实例 stmt.close(); stmt = null; } } 程序首先生成了一个Context实例。javax.naming.Context接口定义了名称服务环境(Naming Context)及该环境支持的操作。名称服务环境实际上是由名称和对象间的相互映射组成。程序中初始化名称服务环境的环境工厂(Context Factory)是com.sun.jndi.fscontext.RefFSContextFactory(该类在fscontext.jar中可以找到,由于fscontext.jar中包含的不是标准的API,用户需要从www.javasoft.com中的JNDI专区下载一个名为 fscontext1_2beta3.zip的压缩文件,在该文件中可以找到fscontext.jar)。环境工厂的作用是生成名称服务环境的实例,javax.naming.spi.InitialContextFactory接口定义了环境工厂应该如何初始化名称服务环境。在初始化名称服务环境时还需要定义环境的URL。程序中使用的是"file:JNDI",也就是把环境保存在本地硬盘的JNDI目录下。 初始化了名称服务环境后,就可以把数据源实例注册到名称服务环境中。注册时调用javax.naming.Context.bind()方法,参数为注册名称和注册对象。注册成功后,在JNDI目录下会生成一个.binding文件,该文件记录了当前名称服务环境拥有的名称及对象。 当需要在名称服务环境中查询一个对象时,需要调用javax.naming.Context.lookup()方法,并把查询到的对象显式转化为数据源对象。然后通过该数据源对象进行数据库操作。 在这个例子中,程序和名称服务环境都是在同一台计算机上运行。在实际的应用中,程序可以通过RMI或CORBA向名称服务环境注册或查询对象。例如在一个服务器-客户机结构中,客户机上的应用程序只需要知道数据源对象在服务器名称服务环境中的逻辑名称,就可以通过RMI向服务器查询数据源,然后通过建立与数据库的连接.这样就可以解决本文最开始提出的问题。