下面的例子是使用Sun自带的RefFSContextFactory来存储JNDI信息,可以将RefFSContextFactory想象为一个大的HashMap,里面存储了很多对象的信息,需要时只需要从HashMap获取对象即可。
本例包括4个类,说明如下:
首先需要引入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等。
原文地址:http://www.cnblogs.com/lnlvinso/p/3818162.html