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 = 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=value
bind1/ClassName=lld.test.jndi.BindedClass
bind1/RefAddr/0/Encoding=String
bind1/FactoryName=lld.test.jndi.BindedClassFactory
bind1/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等。

原文地址:https://www.cnblogs.com/lnlvinso/p/3818162.html