命名服务的操作
1、寻找一个对象
为了从命名服务中找到一个对象,你可以使用 Context.lookup() 方法,只要传递给它你要寻找的对象的名字就可以。例如,在当前的
命名服务中,有一个对象的名字是“report.txt”,为了找到这个对象,你可以使用
Object obj = ctx.lookup("report.txt");
lookup 返回的对象类型,依据你的实际情况来看。命名系统里可以保存各种类型的对象,在这个例子中,“report.txt”返回的对象
因该是文件系统的一个对象(java.io.File) ,你可以进行强制转换:
- import java.io.File;
- ...
- File f = (File)ctx.lookup("report.txt");
下面是这个例子的完整代码:
- import javax.naming.*;
- import java.io.File;
- import java.util.Hashtable;
- /**
- * Demonstrates how to look up an object.
- *
- * usage: java Lookup
- */
- class Lookup {
- public static void main(String[] args) {
- // Set up the environment for creating the initial context
- Hashtable env = new Hashtable(11);
- env.put(Context.INITIAL_CONTEXT_FACTORY,
- "com.sun.jndi.fscontext.RefFSContextFactory");
- env.put(Context.PROVIDER_URL, "file:/tmp/tutorial");
- try {
- // Create the initial context
- Context ctx = new InitialContext(env);
- // Perform lookup and cast to target type
- File f = (File) ctx.lookup("report.txt");
- System.out.println(f);
- // Close the context when we're done
- ctx.close();
- } catch (NamingException e) {
- System.out.println("Lookup failed: " + e);
- }
- }
- }
2、显示内容上下文列表
使用 Context.lookup() 方法,你可以得到指定的对象,实际上你还可以通过其他方法来得到内容上下文里的全部对象的列表。你可以
通过2个方法来实现这个目的,其中一个返回绑定(binding)的列表,另一个仅仅返回“名字--类名”成对的列表。
2.1、Context.List() 方法
Context.List() 方法返回一个 NameClassPair 类的对象的枚举,枚举中的每一个 NameClassPair 对象,都是由对象的名字和对象的类
名组成的。下面的代码片段,演示了“awt”目录的内容上下文的列表。
- NamingEnumeration list = ctx.list("awt");
- while (list.hasMore()) {
- NameClassPair nc = (NameClassPair)list.next();
- System.out.println(nc);
- }
输出结果就是:
# java List
accessibility: javax.naming.Context
color: javax.naming.Context
datatransfer: javax.naming.Context
dnd: javax.naming.Context
event: javax.naming.Context
font: javax.naming.Context
geom: javax.naming.Context
im: javax.naming.Context
image: javax.naming.Context
peer: javax.naming.Context
print: javax.naming.Context
swing: javax.naming.Context
2.2、Context.listBindings() 方法
Context.listBindings() 方法返回一个 Bingding 类的对象的枚举,Binding 类是 NameClassPair 类的之类。一个 Binding 对象,不仅仅包含对象的名字,对象的类名,还包含一个对象。下慢的代码片段演示了这个方法的功能:
- NamingEnumeration bindings = ctx.listBindings("awt");
- while (bindings.hasMore()) {
- Binding bd = (Binding)bindings.next();
- System.out.println(bd.getName() + ": " + bd.getObject());
- }
输出结果:
# java ListBindings
accessibility: com.sun.jndi.fscontext.RefFSContext@1dacd52e
color: com.sun.jndi.fscontext.RefFSContext@1dacd551
datatransfer: com.sun.jndi.fscontext.RefFSContext@1dacd584
dnd: com.sun.jndi.fscontext.RefFSContext@1dacd5b6
event: com.sun.jndi.fscontext.RefFSContext@1dacd5e8
font: com.sun.jndi.fscontext.RefFSContext@1dacd61b
geom: com.sun.jndi.fscontext.RefFSContext@1dacd64d
im: com.sun.jndi.fscontext.RefFSContext@1dacd62a
image: com.sun.jndi.fscontext.RefFSContext@1dacd65c
peer: com.sun.jndi.fscontext.RefFSContext@1dacd68f
print: com.sun.jndi.fscontext.RefFSContext@1dacd6c1
swing: com.sun.jndi.fscontext.RefFSContext@1dacd6f3
2.3、如何停止一个枚举的循环
NamingEnumeration 类可以以三种方式来终止循环:自然的,显示的,异常方式。
a) 当 NamingEnumeration.hasMore() 返回 false,枚举就自动终止了。
b) 可以使用 NamingEnumeration.close() 来强行终止一个循环,但是记得要释放其中的资源。
c) 如果你抛出一个 NamingException ,那么循环也会被终止。
不管枚举是如何被终止的,一旦它被终止了,那么就不要再使用这个变量。否则会发生不确定的错误。
2.4、为什么我们会需要这2个方法?
list() 方法是为浏览器风格的应用而准备的,因为这种应用一般仅仅要求现实对象的名字。例如,浏览器
会显示一个内容上下文里的全部对象的名字,然后让用户去选择,以进行下一步操作。一般这样的应用没必要
访问内容上下文里的具体对象。
listBindings() 方法是为一些会操作内容上下文里的对象的应用而准备的。例如,一个后台程序可能会查看
某一个目录里的全部文件的状态。或者一个打印机管理程序会重新启动全部的打印机。为了执行类似的操作,
应用程序必须得到内容上下文里的具体对象,因此,用这个方法就显得特别有效了。
这两个方法,你可以根据实际的情况来选择使用。
3、添加、修改、删除一个绑定(Binding)
Context 借口有一些针对binding的操作方法:adding, replacing, 和 removing。
3.1、增加一个binding
Context.bind() 方法可以给内容上下文增加一个binding,可以给传入两个参数:一个是对象的名字,另一个
是对象。
- // Create the object to be bound
- Fruit fruit = new Fruit("orange");
- // Perform the bind
- ctx.bind("favorite", fruit);
下面用代码演示了这个方法的使用:
- FruitFactory.java :
- import javax.naming.*;
- import javax.naming.spi.ObjectFactory;
- import java.util.Hashtable;
- /**
- * This is an object factory that when given a reference for a Fruit
- * object, will create an instance of the corresponding Fruit.
- */
- public class FruitFactory implements ObjectFactory {
- public FruitFactory() {
- }
- public Object getObjectInstance(Object obj, Name name, Context ctx,
- Hashtable env) throws Exception {
- if (obj instanceof Reference) {
- Reference ref = (Reference)obj;
- if (ref.getClassName().equals(Fruit.class.getName())) {
- RefAddr addr = ref.get("fruit");
- if (addr != null) {
- return new Fruit((String)addr.getContent());
- }
- }
- }
- return null;
- }
- }
- Fruit.java:
- import javax.naming.*;
- /**
- * This class is used by the Bind example.
- * It is a referenceable class that can be stored by service
- * providers like the LDAP and file system providers.
- */
- public class Fruit implements Referenceable {
- String fruit;
- public Fruit(String f) {
- fruit = f;
- }
- public Reference getReference() throws NamingException {
- return new Reference(
- Fruit.class.getName(),
- new StringRefAddr("fruit", fruit),
- FruitFactory.class.getName(),
- null); // factory location
- }
- public String toString() {
- return fruit;
- }
- }
- main class:
- import javax.naming.*;
- import java.io.File;
- import java.util.Hashtable;
- /**
- * Demonstrates how to add a binding to a context.
- * (Use Rebind example to overwrite binding; use Unbind to remove binding.)
- *
- * usage: java Bind
- */
- class Bind {
- public static void main(String[] args) {
- // Set up the environment for creating the initial context
- Hashtable env = new Hashtable(11);
- env.put(Context.INITIAL_CONTEXT_FACTORY,
- "com.sun.jndi.fscontext.RefFSContextFactory");
- env.put(Context.PROVIDER_URL, "file:/tmp/tutorial");
- try {
- // Create the initial context
- Context ctx = new InitialContext(env);
- // Create the object to be bound
- Fruit fruit = new Fruit("orange");
- // Perform the bind
- ctx.bind("favorite", fruit);
- // Check that it is bound
- Object obj = ctx.lookup("favorite");
- System.out.println(obj);
- // Close the context when we're done
- ctx.close();
- } catch (NamingException e) {
- System.out.println("Operation failed: " + e);
- }
- }
- }
如果你运行两次这个例子,那么会遇到一个错误:NameAlreadyBoundException。这是因为在内容上下文里
不能有重复名字的对象。如果你想运行两次,那么就需要使用 rebind() 方法。
3.2、增加或替换一个binding
rebind()方法是用来增加或者替换一个binding。参数和 bind() 方法一样,不同的是,如果内容上下文里
已经存在了同名的对象,那么就会用新的对象把旧的对象替换掉。
- // Create the object to be bound
- Fruit fruit = new Fruit("lemon");
- // Perform the bind
- ctx.rebind("favorite", fruit);
3.3、删除一个binding
你可以使用 unbind() 方法来删除一个绑定。
- // Remove the binding
- ctx.unbind("favorite");
4、重新命名一个对象
你可以使用 Context.rename() 方法来重新命名一个对象。
- // Rename to old_report.txt
- ctx.rename("report.txt", "old_report.txt");
5、创建和删除一个子内容上下文
Context 接口里有两个方法可以创建和删除子内容上下文。如果是对于文件系统来说,那就是创建和删除一个
子目录。
5.1、创建一个内容上下文
你可以使用 createSubcontext() 方法来创建一个子内容上下文。
- // Create the context
- Context result = ctx.createSubcontext("new");
下面是一个例子:
- import javax.naming.*;
- import java.io.File;
- import java.util.Hashtable;
- /**
- * Demonstrates how to create a new subcontext called "new".
- * (Run Destroy after this to remove the subcontext).
- *
- * usage: java Create
- */
- class Create {
- public static void main(String[] args) {
- // Set up the environment for creating the initial context
- Hashtable env = new Hashtable(11);
- env.put(Context.INITIAL_CONTEXT_FACTORY,
- "com.sun.jndi.fscontext.RefFSContextFactory");
- env.put(Context.PROVIDER_URL, "file:/tmp/tutorial");
- try {
- // Create the initial context
- Context ctx = new InitialContext(env);
- // Create the context
- Context result = ctx.createSubcontext("new");
- // Check that it was created by listing its parent
- NamingEnumeration list = ctx.list("");
- // Go through each item in list
- while (list.hasMore()) {
- NameClassPair nc = (NameClassPair)list.next();
- System.out.println(nc);
- }
- // Close the context when we're done
- ctx.close();
- } catch (NamingException e) {
- System.out.println("Create failed: " + e);
- }
- }
- }
5.2、删除一个上下文
你可以使用 destroySubcontext() 来删除一个内容上下文。
- // Destroy the context
- ctx.destroySubcontext("new");
下面是一个例子:
- import javax.naming.*;
- import java.io.File;
- import java.util.Hashtable;
- /**
- * Demonstrates how to destroy a subcontext called "new".
- * (Run this after running Create)
- *
- * usage: java Destroy
- */
- class Destroy {
- public static void main(String[] args) {
- // Set up the environment for creating the initial context
- Hashtable env = new Hashtable(11);
- env.put(Context.INITIAL_CONTEXT_FACTORY,
- "com.sun.jndi.fscontext.RefFSContextFactory");
- env.put(Context.PROVIDER_URL, "file:/tmp/tutorial");
- try {
- // Create the initial context
- Context ctx = new InitialContext(env);
- // Destroy the context
- ctx.destroySubcontext("new");
- // Check that it has been destroyed by listing its parent
- NamingEnumeration list = ctx.list("");
- // Go through each item in list
- while (list.hasMore()) {
- NameClassPair nc = (NameClassPair)list.next();
- System.out.println(nc);
- }
- // Close the context when we're done
- ctx.close();
- } catch (NamingException e) {
- System.out.println("destroy failed: " + e);
- }
- }
- }