首页 > 代码库 > JNDI

JNDI

     下面的例子是使用Sun自带的RefFSContextFactory来存储JNDI信息,可以将RefFSContextFactory想象为一个大的HashMap,里面存储了很多对象的信息,需要时只需要从HashMap获取对象即可。

     本例包括4个类,说明如下:

  • BindedClass:自定义的实现Referenceable接口的类
  • BindedClassFactory:工厂类,能够把一个Reference对象转换为BindedClass对象
  • Bind:测试类,用于在JNDI中绑定对象
  • Loopup:测试类,用于从JNDI中获取对象

    首先需要引入fscontext.jar和providerutil.jar,这是进行测试的前提。

package jndi;
import javax.naming.NamingException;import javax.naming.Reference;import javax.naming.Referenceable;import javax.naming.StringRefAddr;public class BindedClass implements Referenceable {	public String value;	public BindedClass() {	}	@Override	public Reference getReference() throws NamingException {		Reference r = new Reference(this.getClass().getName(), BindedClassFactory.class.getName(), null);		r.add(new StringRefAddr("value", this.getValue()));		return r;	}	public String getValue() {		return value;	}	public void setValue(String value) {		this.value = http://www.mamicode.com/value;>

  BindedClass类是要存储的类,需要实现Referenceable接口的Reference getReference()方法。该Reference指定了创建BindedClass对象的工厂--BindedClassFactory。

package jndi;import java.util.Hashtable;import javax.naming.Context;import javax.naming.Name;import javax.naming.Reference;import javax.naming.spi.ObjectFactory;public class BindedClassFactory implements ObjectFactory {	@Override	public Object getObjectInstance(Object obj, Name name, Context nameCtx, Hashtable<?, ?> environment) throws Exception {		if (obj instanceof Reference) {			Reference ref = (Reference) obj;			String val = (String) ref.get("value").getContent();			BindedClass o = new BindedClass();			o.setValue(val);			return o;		}		return null;	}}

  BindedClassFactory类将一个Reference对象转换为所需求的BindedClass对象,是创建BindedClass对象具体的类。

package jndi;import java.util.Properties;import javax.naming.Context;import javax.naming.directory.DirContext;import javax.naming.directory.InitialDirContext;public class Bind {	public static void main(String[] args) throws Exception {		Properties ps = new Properties();		ps.setProperty(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.fscontext.RefFSContextFactory");		ps.setProperty(Context.PROVIDER_URL, "file:JNDI_REF");		DirContext ctx = new InitialDirContext(ps);		String key = "bind1";		BindedClass b = new BindedClass();		b.setValue("abcdefg");		ctx.rebind(key, b);		System.out.println("Binded successfully!");		ctx.close();	}}

  Bind类用于绑定对象,ps.setProperty(Context.PROVIDER_URL, "file:JNDI_REF");这就要求工程下面有一个名为JNDI_REF的文件夹,其下有一个后缀为.bindings的文件,记录了所绑定对象的信息。

package jndi;import java.util.Properties;import javax.naming.Context;import javax.naming.directory.DirContext;import javax.naming.directory.InitialDirContext;public class Lookup {	public static void main(String[] args) throws Exception {		Properties ps = new Properties();		ps.setProperty(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.fscontext.RefFSContextFactory");		ps.setProperty(Context.PROVIDER_URL, "file:JNDI_REF");		DirContext ctx = new InitialDirContext(ps);		String key = "bind1";		BindedClass o = (BindedClass) ctx.lookup(key);		System.out.println(o.getValue());		ctx.close();	}}

  Lookup类用于获取所绑定的对象。Bind类中将对象绑定至bind1,这里就查找bind1获取BindedClass对象。

    先运行Bind类再运行Lookup类,就可以看到成功的获取到了BindedClass对象。

    工程下面有一个名为JNDI_REF的文件夹,其下有一个后缀为.bindings的文件,记录的内容如下:

bind1/RefAddr/0/Type=valuebind1/ClassName=lld.test.jndi.BindedClassbind1/RefAddr/0/Encoding=Stringbind1/FactoryName=lld.test.jndi.BindedClassFactorybind1/RefAddr/0/Content=abcdefg

  可以看到该文件记录了绑定类的ClassName,创建绑定类的工厂FactoryName,以及一个类型为String,名为value的属性,可以在创建对象时直接给对象的属性赋值。

    

    数据库的数据源DataSource都实现了Referenceable接口,因此可以通过JNDI来直接获取数据库的数据源,而不必使用JDBC。

    下面是使用JNDI获取MySQL数据连接的例子,需要引入MySQL driver.jar。MysqlDataSource位于MySQL驱动的jar包中。

package jndi;import java.sql.Connection;import java.sql.ResultSet;import java.sql.SQLException;import java.sql.Statement;import java.util.Hashtable;import javax.naming.Context;import javax.naming.InitialContext;import javax.naming.NamingException;import javax.sql.DataSource;import com.mysql.jdbc.jdbc2.optional.MysqlDataSource;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_REF");			ctx = new InitialContext(env);		} catch (NamingException ne) {			ne.printStackTrace();		}		try {			 bind(ctx, "jdbc/chidb");			lookup(ctx, "jdbc/chidb");		} catch (NamingException e) {			// TODO Auto-generated catch block			e.printStackTrace();		}	}	static void bind(Context ctx, String ln) throws NamingException, SQLException {		// 创建一个DataSource实例		MysqlDataSource ods = new MysqlDataSource();		ods.setURL("jdbc:mysql://172.16.131.181:13306/NNM5?autoReconnect=true");//需要改为实际的数据库		ods.setServerName("Chicago");		ods.setDatabaseName("NNM5");		ods.setPortNumber(13306);		ods.setUser("root");		ods.setPassword("OSSDB123");		// 把DataSource实例注册到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中查询DataSource实例		System.out.println("Doing a lookup with the logical name : " + ln);		DataSource ods = (DataSource) ctx.lookup(ln);		System.out.println("Successful lookup");		// 从查询到的DataSource实例中获取数据库连接		Connection conn = ods.getConnection();		// 进行数据库操作		getUserName(conn);		// 关闭连接		conn.close();		conn = null;	}	static void getUserName(Connection conn) throws SQLException {		// 生成一个Statement实例		Statement stmt = conn.createStatement();		ResultSet rset = stmt.executeQuery("select propname from rc_properties");		while (rset.next())			System.out.println("Name is " + rset.getString(1));		rset.close();		rset = null;		stmt.close();		stmt = null;	}}

  

     还可以使用其他软件作为JNDI服务器,如WebLogic,tomcat等。