1 / 53

第七讲 JNDI 技术

第七讲 JNDI 技术. Java 命名和目录服务接口. 本讲内容. JNDI 概述 JNDI 的体系结构 JNDI 包和类 命名服务的应用编程 实例. 1 . JNDI 概述. 为什么需要 JNDI?

galia
Download Presentation

第七讲 JNDI 技术

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 第七讲 JNDI技术 Java命名和目录服务接口

  2. 本讲内容 • JNDI概述 • JNDI的体系结构 • JNDI包和类 • 命名服务的应用编程 • 实例

  3. 1. JNDI概述 • 为什么需要JNDI? • Applications must be able to access resources and external information in their operational environment without knowledge of how the external information is named and organized in that environment. The JNDI naming context and Java language annotations provide this capability. [Java EE specification]

  4. 1. JNDI概述(续) • 应用程序必须能在不知道外部信息是如何命名和组织在其运行环境中的情况下来存取资源和外部信息,JNDI命名上下文和Java语言的注释提供了这种能力 • JNDI和注释(Annotation)是存取外部资源和信息的机制

  5. 1. JNDI概述(续) • The Application Assembler and Deployer should be able to customize the behavior of an application’s business logic without accessing the application’s source code. Typically this will involve specification of parameter values, connection to external resources, and so on. Deployment descriptors provide this capability • 部署描述符( Deployment descriptors )是定制应用程序逻辑行为的机制

  6. 1. JNDI概述(续) • 应用程序在运行环境中查找的资源(如数据源、Servlet、EJB)和外部信息必须在命名服务中注册,否则无法找到 • 用一个有意义的文本名与对象关联。通过分布式系统的命名和目录服务能够对分布式系统中的资源(文件、分布式对象、服务)进行方便的访问和管理

  7. 1. JNDI概述(续) • JNDI是Java EE中的核心技术之一,它允许组件定位其他组件和资源,提供了企业级应用所需要的资源和外部信息的注册、存储以及获取组件等功能,许多J2EE组件的使用需要JNDI 的支持 • 在JMS、JMail、JDBC、EJB等技术中,大量应用这种技术 • 例如,要定位JDBC资源,企业bean调用JNDI的lookup方法,lookup方法传递一个JNDI名称参数,返回相关的对象

  8. 1. JNDI概述(续) • 访问对象的基本方式 凭借对象名称 (name)与对象体(object) 的绑定(binding),使用者通过上下文(context)来存取欲使用的对象 命名服务系统示例 • RMI注册表 远程对象名—远程对象 • DNS 主机名称「dhu.edu.cn」—IP Address「202.120.144.2」 • 文件系统 文件名或路径—文件句柄

  9. 1. JNDI概述(续) • 目录服务 目录服务是命名服务的扩充,也是凭借名称 与对象 的绑定来存取欲使用的对象。但允许对象拥有属性 (attributes)以记录额外的信息。于是,使用者可以通过名称来查看(look up)对象并获得该对象的属性信息,或是利用属性作为搜寻的过滤条件 (search filter) • 目录服务是命名服务,命名服务不需要是目录服务

  10. 1. JNDI概述(续) • 例如:电话公司的电话服务系统,记录每个单位登记的电话号码。对于单位对象,有地址等属性可利用 对象 属性名 属性值

  11. 1. JNDI概述(续) • 什么是目录? • 目录类似于一个数据库,它通常包含一些基于属性(名-值结构)的描述性信息 • 由于目录中的信息被读的频率比写的频率高许多,所以目录没有复杂的事务和回滚机制

  12. 1. JNDI概述(续) • 目录与数据库的区别(目录服务的特殊性) • 检索功能强大,而增、删、改等数据库更新功能则较弱,更新只是简单的更改操作。因为目录服务器是专门为那些检索频率多于更新频率的数据服务而设计的 • 对大量的信息查找或信息检索,目录应该快速给出应答 • 为提高性能和可靠性,并降低应答时间,分布式的目录信息要在广阔的网络范围内进行复制。复制点之间,暂时的不一致是难免的,只要最终能同步即可

  13. 1. JNDI概述(续) • 目前使用Directory较著名的应用系统与架构 • Novell公司的 NDS(Novell Directory Services) • Sun公司的NIS(Network Information Service) • 即将成为网络上一个新标准的 LDAP(Lightweight Directory Access Protocol)

  14. 1. JNDI概述(续) • 名称 • 名称—描述对象的名称字符串 一个名称空间中所有的命名必须遵循相应的规则—该名称空间的命名惯例,如DNS的命名惯例 • 原子名字:不可再分的名字 • 混合名字(Compound Name):按照命名约定组成的零个或多个原子名字序列 • 复合名字(Composite Name):跨越多个命名系统的名字,由多个部分组成,每个部分处于不同的命名空间

  15. 1. JNDI概述(续) • 绑定(binding) JNDI命名服务有一组将原子名字与对象关联在一起的绑定 • 上下文(Context) JNDI提供了一个命名上下文对象,即一组名称到对象绑定,被绑定在一个上下文中的名称是对象的JNDI名称,所有的命名操作相对于一个上下文。其状态是不同原子名字到对象的绑定集合,其操作有解析名字、绑定名字、解绑定名字、列举绑定名字、注销名字、重新命名对象等

  16. 1. JNDI概述(续) • 命名系统 • 一个具有相同类型(有相同命名约定)的上下文对象的集合 • 命名系统的主要功能是从名字映射到对象,对象可以是任何类型 • 一个目录系统用于表现一个计算机环境中各种信息的特殊类型的对象。一个目录对象和它的属性相关联,属性表现为一个标识符和一个值的集合 • 名称空间 一个命名/目录系统中名字的集合

  17. 1. JNDI概述(续) • 目录的属性与子上下文 • 一个上下文内部可以具有另一个上下文,称为子上下文,与文件系统中的目录非常相象,这种分层结构可以更好地组织信息 • 子上下文仅在目录服务中有效,而在命名服务中无效,因为命名服务未安排在类似分层树的结构中 • 对于支持子上下文的命名服务,Context类也提供创建和销毁子上下文的方法

  18. 1. JNDI概述(续) • 为避免与JNDI名称空间中的其他企业资源的名称冲突,并且避免可移植性问题,J2EE应用程序中的所有名称应该以字符串java:comp/env开始

  19. 本讲内容 • JNDI概述 • JNDI的体系结构 • JNDI包和类 • 命名服务的应用编程 • 实例

  20. 2. JNDI的体系结构 • Java Naming and Directory Interface™ 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.

  21. 2. JNDI的体系结构(续) • JNDI包含一组API和一组SPI(Service Provider Interface) • Java程序通过JNDI API 存取各种naming和directory 服务

  22. 2. JNDI的体系结构(续) JDBC对每个数据库有独立的驱动程序,JNDI的思想是提供一个通用的接口。底层的名字服务实现可以是各种类型,JNDI通过SPI实现代码屏蔽了各种名字和目录服务实现的区别 …… LDAP 服务器 RMI服务 CosNaning 服务

  23. 本讲内容 • JNDI概述 • JNDI的体系结构 • JNDI包和类 • 命名服务的应用编程 • 实例

  24. 3. JNDI的包和类 • JNDI由若干个独立的包组成 • 基础包—javax.naming 从中获得JNDI核心概念的定义 • 服务提供程序包—javax.naming.spi • 特定服务提供程序的实际实现存放在独立的包中 javax.naming.directory javax.naming.event javax.naming.ldap

  25. 3. JNDI的包和类(续) • 基础包javax.naming包含命名服务的类 (classes)和存取接口(interfaces for accessing) • 其中Context接口让用户定义对象在名称空间中的「相对位置」,naming服务以context为接口,提供查看、绑定、对象更名(renaming objects)等功能 • InitialContext提供naming或directory服务的一个起始位置。因为在JNDI的世界中没有绝对的root观念,所有的动作都建立在context上;有了起始位置,使用者才能借助它对其context上的对象进行存取 • NamingException api则为JNDI定义的一组类,负责捕获 (catch)所有发生在naming或directory 服务里的异常 (exceptions)

  26. 3. JNDI的包和类(续) • javax.naming.directory 包由javax.naming扩充而来,提供存取directory服务的功能——建立在naming 服务之上,增加对directory中的对象检索其属性(retrieve attributes)和通过指定属性为条件来搜寻(search)等功能。其中 • DirContext api提供对象在directory内context的接口,与Context api的运作方式类似,但更进一步定义了查询和更新directory中对象属性的方法(methods)

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

  28. 4.命名服务的应用编程 • 命名服务的应用编程 类似于数据库编程,需要在用户代码和数据库之间建立连接

  29. 5.实例 • 要求 • 命令行参数作为名字来查找一个对象 • 使用文件系统的服务提供者,用户向程序提供的名字必须是一个文件名 • 用户不了解服务提供者的细节 • 步骤 1.引入JNDI类Context、InitialContext、NamingException 2.创建初始上下文空间 3.通过上下文查找对象 Object obj=ctx.lookup() 4.捕获异常

  30. 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"); //指明Serviceprovider是文件系统 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); } } }

  31. String name=args[0]; Hashtable env=new Hashtable(11); env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.fscontext.RefFSContextFactory"); //指明Serviceprovider是文件系统. try { Context ctx = new InitialContext(env); Object obj=ctx.lookup(name); System.out.println(name+“ is bound to: "+obj); ctx.close(); }

  32. 使用系统属性 • JNDI使用大量的系统属性定义自身的行为。比如属性名javax.naming.factory.initial是服务提供程序提供的InitialContext实现工厂 • 为了方便,属性中的一些以在Context接口中的常量方式存在。例如,使用代码(不是命令行)初始化工厂,使用下列语句将服务提供程序设置为Sun的文件系统实现(传统方法): System.setProperty(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.fscontext.RefFSContextFactory");

  33. 使用系统属性(续) • 在一些情况下,可能希望JNDI有几个不同的服务提供程序。企业级的安全环境不允许到处任意设置系统属性 • 为了克服系统属性限制,需要使用一套新的InitialContext对象的构造函数,修订后的构造函数使用Hashtable做参数

  34. 输出 • C:\j2sdk1.4.0\bin\jndi_example>java Lookup /temp • /temp is bound to: com.sun.jndi.fscontext.RefFSContext@87816d

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

  36. 命名操作 • 命名操作 • 查找一个对象 • 列出命名空间的内容 • 增加、改写和删除一个绑定 • 重命名一个对象 • 创建并析构一个子命名空间

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

  38. 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); } } }

  39. 查找一个对象(续) • 运行环境与结果 • 环境 C:\temp\tutorial\abc.txt • 结果 执行语句System.out.println(f);C:\temp\tutorial\abc.txt

  40. 列出命名空间的内容 • 使用context.lookup()函数,可以查找单一对象,也可以列举整个上下文 • 例中使用Context.list(),返回NameClassPair的一个枚举类型的集合。每个NameClassPair由对象的名字和它的类名组成

  41. 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); } } }

  42. 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

  43. 增加、改写和删除一个绑定 • 上下文空间接口中,包含了增加、改写和删除一个绑定的方法 • 绑定的对象必须是引用对象和可引用的对象。如果下例中的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

  44. 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); } } }

  45. 正确例子 • 创建可引用的类Car.class • 之前,通过实现接口ObjectFactory 创建CarFactory

  46. 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; } }

  47. 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; } }

  48. 创建并析构一个子命名空间 • 在上下文空间的接口中,包含了创建并析构子空间(在file system中相当于子文件夹)的方法。 语句为: Context result=ctx.createSubcontext(“”); ctx.destroySubcontext(“”);

  49. 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); } } }

  50. 运行结果 在C:/temp/tutorial中新建文件夹new

More Related