1、环境属性
在之前的文档里,我们已经学会如何去初始化一个内容上下文,例如:
这个例子中的 Hashtable,就是一个环境属性,或者简单的说是“环境”。
这个章节里,我们要介绍的就是这个“环境属性”,看看他们是如何发挥作用的,以及如何使用的等等。
JNDI其实只是一个接口,为了访问一个命名/目录服务,你必须依赖特定的SPI。这就需要进行一些配置,
你得告诉JNDI,你需要的SPI是什么。
下面是一些不同种类的环境属性:
a> 标准的
b> 描述服务的
c> 描述特性的
d> 描述提供者的。
下面是标准的环境属性:
1.1、环境属性
配置环境属性可以通过两种方式:一个是把一个Hashtable传递给InitialContext的构造函数,另一个
是用一个 .properties 文件。
一些JNDI的环境属性还可以通过系统变量或者Applet参数来设置。
1.1.1、应用程序资源文件(.properties文件)
你可以在 .properties文件 里指定JNDI的配置。这个文件的名字应该是 jndi.properties。例如下面
就是一个 jndi.properties的例子:
java.naming.factory.object=com.sun.jndi.ldap.AttrsToCorba:com.wiz.from.Person
java.naming.factory.state=com.sun.jndi.ldap.CorbaToAttrs:com.wiz.from.Person
java.naming.factory.control=com.sun.jndi.ldap.ResponseControlFactory
java.naming.factory.initial=com.sun.jndi.ldap.LdapCtxFactory
java.naming.provider.url=ldap://localhost:389/o=jnditutorial
com.sun.jndi.ldap.netscape.schemaBugs=true
首先,应用程序会从classpath 里面载入 jndi.properties,如果没有发现,那么会载入JAVA_HOME/lib/
jndi.properties。
注意:如果你使用这种方式配置JNDI,那么当找不到装个文件的时候,会抛出异常。
当然,我们初始化内容上下文的用法也需要修改一下:
1.1.2、通过系统变量设置JNDI
我们可以使用如下的方式来实现这个功能:
# java -Djava.naming.factory.initial=com.sun.jndi.ldap.LdapCtxFactory \
-Djava.naming.provider.url=ldap://localhost:389/o=jnditutorial \
List
1.1.3、Applet的方式设置JDNI
看这个例子:
同时初始内容上下文也需要修改:
1.2、内容上下文环境的探讨
我们已经知道可以通过三种方式来设置JDNI的属性。但是,如果我们同时使用了两种方式会
怎么样呢?看看下面的例子:
我们同时配置一个jndi.properties在classpath里:
java.naming.factory.object=com.sun.jndi.ldap.AttrsToCorba:com.wiz.from.Person
java.naming.factory.state=com.sun.jndi.ldap.CorbaToAttrs:com.wiz.from.Person
java.naming.factory.control=com.sun.jndi.ldap.ResponseControlFactory
java.naming.factory.initial=com.sun.jndi.ldap.LdapCtxFactory
java.naming.provider.url=ldap://localhost:389/o=jnditutorial
com.sun.jndi.ldap.netscape.schemaBugs=true
然后看看运行的结果:
com.sun.jndi.ldap.netscape.schemaBugs=true
java.naming.factory.object=foo.bar.ObjFactory:com.sun.jndi.ldap.AttrsToCorba:com.wiz.from.Person
java.naming.factory.initial=com.sun.jndi.fscontext.FSContextFactory
foo=bar
java.naming.provider.url=file:/
java.naming.factory.state=com.sun.jndi.ldap.CorbaToAttrs:com.wiz.from.Person
java.naming.factory.control=com.sun.jndi.ldap.ResponseControlFactory
下面来分析一下这个结果:
a> 在 Hashtable 里的“foo”项,和在文件里的 “com.sun.jndi.ldap.netscape.schemaBugs”,
都出现在结果里。
b> “java.naming.factory.object” 项是两者的组合。
c> 其他的属性如“java.naming.factory.initial” 都是用的 Hashtable里的。
是不是有些混乱?如果我们要使用多个SPI该怎么办?没关系,我们在下一个小结里介绍这个问题。
1.3、定制使用SPI
你可以通过一个SPI的属性文件,来为某一个SPI进行单独的设置。这个文件也是 .properties 文件。
SPI的属性文件应该类似下面:
前缀/jndiprovider.properties
这个前缀是什么呢?就是这个SPI实现的内容上下文类(Context)的包的结构。
例如,我们要使用的是 com.sun.jndi.ldap.LdapCtx 这个内容上下文,那么对应于它的属性配置
文件就应该是:"com/sun/jndi/ldap/jndiprovider.properties"。
一个应用可以使用多个这样的属性配置文件。
那么我们为什么要使用属性配置文件?
有两个原因。第一,我们可以单独的配置某一个命名/服务系统。第二,部署的时候会有用。例如,
你可以单独配置一个针对LDAP的属性,而不用去修改 jndi.properties,或者增加系统变量。
但是,我们也并不是可以在SPI属性配置文件里设置全部的属性,我们可以设置的属性如下:
java.naming.factory.object
java.naming.factory.state
java.naming.factory.control
java.naming.factory.url.pkgs
不过并不象 jndi.properties 或者 那个Hastable,SPI属性配置文件里的属性不会自动载入到环境
里,只有SPI调用了下列方法时才会这样做:
NamingManager.getObjectInstance(Object, Name, Context, Hashtable)
DirectoryManager.getObjectInstance(Object, Name, Context, Hashtable, Attributes)
NamingManager.getStateToBind(Object, Name, Context, Hashtable)
DirectoryManager.getStateToBind(Object, Name, Context, Hashtable, Attributes)
ControlFactory.getControlInstance(Control, Context, Hashtable)
例如,假设我们使用一个LDAP服务,它的实现类是com.sun.jndi.ldap.LdapCtx,当这个类调用
DirectoryManager.getObjectInstance() 方法时,JNDI将会从com/sun/jndi/ldap/jndiprovider.properties
里找到“java.naming.factory.object”项,然后把它追加到环境里已经定义的项里(例如那个Hashtable
或者 jndi.properties)。