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);

}

}

}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章