JNDI学习笔记五

2 JNDI的体系结构

nEE.2.6.9 Java Naming and Directory Interface™

(JNDI)The JNDI API is the standard API for naming and directory access. The JNDI API has two parts: an application-level interface used by the application components to access naming and directory services and a service provider interface to attach a provider of a naming and directory service.

nJNDI包含一组API和一组SPI(Service Provider Interface)。

clip_image001

JDBC对每个数据库有独立的驱动程序,JNDI的思想是提供一个通用的接口。底层的名字服务实现可以是各种类型,JNDI通过SPI实现代码屏蔽了各种名字和目录服务实现的区别。

nJava 程序通过JNDI API 存取各种naming和 directory服务。

3 JNDI的包和类

nJNDI 由若干个独立的包组成

n基础包—javax.naming

从中获得JNDI核心概念的定义。

n服务提供程序包—javax.naming.spi

n特定服务提供程序的实际实现存放在独立的包中

javax.naming.directory、 javax.naming.event和javax.naming.ldap 。

n基础包javax.naming包含命名服务的类 (classes)和存取接口(interfaces for accessing)

n其中 Context接口让用户定义对象在名称空间中的「相对位置」。 naming服务以context为接口,提供查看、绑定、对象更名(renaming objects)等功能。

n InitialContext提供naming或 directory服务的一个起始位置。因为在JNDI的世界中没有绝对的root观念,所有的动作都建立在context上;有了起始位置,使用者才能借助它对其 context上的对象进行存取。

nNamingExceptionapi则为JNDI定义的一组类,负责捕获 (catch)所有发生在 naming或directory 服务里的异常 (exceptions)。

njavax.naming.directory 包由 javax.naming扩充而来,提供存取 directory服务的功能——建立在naming 服务之上,增加对directory中的对象检索其属性( retrieve attributes)和通过指定属性为条件来搜寻(search)等功能。其中

n DirContext api提供对象在directory内context的接口,与 Context api的运作方式类似,但更进一步定义了查询和更新directory中对象属性的方法( methods)。

njavax.naming.spi 让系统开发者为特定的naming或 directory系统来撰写使用JNDI的应用程式,例如在 Plug-ins、Java Object Support及 Multiple Naming Systems(Federation)等方面的应用。

3命名服务的应用编程

n命名服务的应用编程

类似于数据库编程,需要在用户代码和数据库之间建立连接。

命名的例子

n要求:

n命令行参数作为名字来查找一个对象;

n使用文件系统的服务提供者,用户向程序提供的名字必须是一个文件名;

n用户不了解服务提供者的细节。

n步骤

1.引入JNDI类 Context、InitialContext、NamingException

2.创建初始上下文空间

3.通过上下文查找对象 Object obj=ctx.lookup();

3.捕获异常

import javax.naming.Context;

import javax.naming.InitialContext;

import javax.naming.NamingException;

import java.util.Hashtable;

public class Lookup {

public static void main(String[] args) {

if(args.length!=1)

{

System.err.println("usage: ");

System.exit(-1); }

String name=args[0];

Hashtable env=new Hashtable(11);

env.put(Context.INITIAL_CONTEXT_FACTORY,"com.sun.jndi.fscontext.RefFSContextFactory");

//指明Service provider是文件系统.

try {

Context ctx = new InitialContext(env);

Object obj=ctx.lookup(name);

System.out.println(name+ " is bound to: "+obj);

ctx.close();

} catch (NamingException e) { System.err.println("problem look "+":"+e);

}

}

}

String name=args[0];

Hashtable env=new Hashtable(11);

env.put(Context.INITIAL_CONTEXT_FACTORY,

"com.sun.jndi.fscontext.RefFSContextFactory");

//指明Service provider是文件系统.
try {

Context ctx = new InitialContext(env);

Object obj=ctx.lookup(name);

System.out.println(name+“ is bound to: "+obj);

ctx.close();

}

使用系统属性

nJNDI使用大量的系统属性定义自身的行为。比如属性名javax.naming.factory.initial是服务提供程序提供的InitialContext实现工厂。

n为了方便,属性中的一些以在Context接口中的常量方式存在。例如,使用代码(不是命令行)初始化工厂,使用下列语句将服务提供程序设置为Sun的文件系统实现(传统方法):

System.setProperty(Context.INITIAL_CONTEXT_FACTORY,

"com.sun.jndi.fscontext.RefFSContextFactory");

在一些情况下,可能希望JNDI有几个不同的服务提供程序。企业级的安全环境不允许到处任意设置系统属性。

为了克服系统属性限制,需要使用一套新的InitialContext对象的构造函数。修订后的构造函数使用Hashtable做参数。

n C:/j2sdk1.4.0/bin/jndi_example>java Lookup /temp

n/temp is bound to:com.sun.jndi.fscontext.RefFSContext@87816d

运行条件

为了运行程序你要到[url]http://java.sun.com/products/jndi/downloads/index.html[/url]下载JNDI的相关包,然后把两个jar:fscontext.jar和providerutil.jar加入到CLASSPATH中。
Context ctx = new InitialContext();是以文件系统为初始上下文,这样一来你可以把String name = "C:/aaa.txt“;换成你系统中的任意目录和文件的路径名.

命名操作

n命名操作

n1.查找一个对象

n2.列出命名空间的内容

n3.增加、改写和删除一个绑定

n4.重命名一个对象

n5.创建并析构一个子命名空间

n1.查找一个对象

n通过命名服务查找一个对象,用context.lookup()函数。参数为对象的名字,返回对象,其类型由底层命名系统和对象本身关联的数据共同决定。一个命名系统中可能包含多种类型的对象。

import javax.naming.NamingException;

import java.io.File;

import java.util.Hashtable;

import javax.naming.Context;

import javax.naming.InitialContext;

public class Lookup {

public static void main(String[] args) {

Hashtable env=new Hashtable(11); env.put(Context.INITIAL_CONTEXT_FACTORY,"com.sun.jndi.fscontext.RefFSContextFactory");

env.put(Context.PROVIDER_URL,"file:/temp/tutorial");

try {

Context ctx = new InitialContext(env);

File f=(File)ctx.lookup("abc.txt");

System.out.println(f);

ctx.close();

} catch (NamingException e) { System.err.println("Lookup failed: "+e);

}

}

}

查找一个对象

n运行环境与结果

n环境 C:/temp/tutorial/abc.txt

n结果

执行语句System.out.println(f); C:/temp/tutorial/abc.txt

2.列出命名空间的内容

n使用context.lookup()函数,可以查找单一对象,也可以列举整个上下文。

n例中使用Context.list(),返回NameClassPair的一个枚举类型的集合。每个NameClassPair由对象的名字和它的类名组成。

import java.util.Hashtable;

import javax.naming.Context;

import javax.naming.InitialContext;

import javax.naming.NamingException;

import javax.naming.NamingEnumeration;

import javax.naming.NameClassPair;

public class List {

public static void main(String[] args) {

Hashtable env=new Hashtable(11);

env.put(Context.INITIAL_CONTEXT_FACTORY,"com.sun.jndi.fscontext.RefFSContextFactory");

env.put(Context.PROVIDER_URL,“file:/”); //操作相对程序运行的盘的根目录

try {

Context ctx = new InitialContext(env);

NamingEnumeration list =ctx.list("temp");

while(list.hasMore()) {

NameClassPair ne=(NameClassPair)list.next();

System.out.println(ne);

}

ctx.close();

} catch (NamingException e) { System.err.println("List failed: "+e);

}

}

}

C:/j2sdk1.4.0/bin/jndi_example>java List

ext42338: javax.naming.Context

lpt$vpn.zip: java.io.File

sysclean_1053_p167.com: java.io.File

sysclean.log: java.io.File

tutorial: javax.naming.Context

3.增加、改写和删除一个绑定

n上下文空间接口中,包含了增加、改写和删除一个绑定的方法。

n绑定的对象必须是引用对象和可引用的对象。如果下例中的Car是普通类,则不能运行,而抛出如下异常。

Lookup failed: javax.naming.OperationNotSupportedException: Can only bind References or Referenceable objects

相应技术 see

http://java.sun.com/products/jndi/tutorial/basics/naming/bind.html

import javax.naming.NamingException;

import java.io.File;

import java.util.Hashtable;

import javax.naming.Context;

import javax.naming.InitialContext;

public class Bind{

public static void main(String[] args) {

Hashtable env=new Hashtable(11); env.put(Context.INITIAL_CONTEXT_FACTORY,"com.sun.jndi.fscontext.RefFSContextFactory");

env.put(Context.PROVIDER_URL,"file:/temp/tutorial");

try {

Context ctx = new InitialContext(env);

Car car=new Car("taxi");

ctx.bind("favorite",car);

Object obj=ctx.lookup("favorite");

System.out.println(obj);

ctx.close();

} catch (NamingException e) { System.err.println("Lookup failed: "+e);

}

}

}

正确例子

n创建可引用的类 Car.class;

n之前,通过实现接口ObjectFactory 创建CarFactory 。

import javax.naming.*;

import javax.naming.spi.ObjectFactory;

import java.util.Hashtable;

/**

* This is an object factory that when given a reference for a Car

* object, will create an instance of the corresponding Car.

*/

public class CarFactory implements ObjectFactory {

public CarFactory() { }

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(Car.class.getName())) {

RefAddr addr = ref.get("car");

if (addr != null) {

return new Car((String)addr.getContent());

}

}

}

return null;

}

import javax.naming.*;

public class Car implements Referenceable {

String car;

public Car(String c) {car=c;}

public Reference getReference() throws NamingException {

return new Reference(

Car.class.getName(),new StringRefAddr("car",car),CarFactory.class.getName(),null);

}

public String toString() {

return car;

}

}

4.创建并析构一个子命名空间

n在上下文空间的接口中,包含了创建并析构子空间(在file system中相当于子文件夹)的方法。语句为:

Context result=ctx.createSubcontext(“”);

ctx.destroySubcontext(“”);

import java.util.Hashtable;

import java.io.File;

import javax.naming.*;

public class Create {

public static void main(String[] args) {

Hashtable env=new Hashtable(11); env.put(Context.INITIAL_CONTEXT_FACTORY,"com.sun.jndi.fscontext.RefFSContextFactory");

env.put(Context.PROVIDER_URL,"file:/temp/tutorial");

try {

Context ctx = new InitialContext(env);

Context result=ctx.createSubcontext("new");

NamingEnumeration list =ctx.list("");

while(list.hasMore()) {

NameClassPair ne=(NameClassPair)list.next();

System.out.println(ne);

}

ctx.close();

} catch (NamingException e) { System.err.println("List failed: "+e);

}

}

}

运行结果

在C:/temp/tutorial中新建文件夹new。

import java.util.Hashtable;

import java.io.File;

import javax.naming.*;

public class Destroy {

public static void main(String[] args) {

Hashtable env=new Hashtable(11);

env.put(Context.INITIAL_CONTEXT_FACTORY,"com.sun.jndi.fscontext.RefFSContextFactory");

env.put(Context.PROVIDER_URL,"file:/temp/tutorial");

try {

Context ctx = new InitialContext(env);

ctx.destroySubcontext("new");

NamingEnumeration list =ctx.list("");

while(list.hasMore()) {

NameClassPair ne=(NameClassPair)list.next();

System.out.println(ne);

}

ctx.close();

} catch (NamingException e) { System.err.println("List failed: "+e);

}

}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值