Java规范之JNDI(Java命名与⽬录接⼝)
JNDI(Java Naming and Directory Interface)- Java命名和⽬录接⼝,是⼀组在Java应⽤中访问命名和⽬录服务的API。为开发⼈员提供了查和访问各种命名和⽬录服务的通⽤、统⼀的接⼝,类似JDBC都是构建在抽象层上。
命名服务将名称和对象联系起来,可以⽤名称访问对象。⽬录服务是⼀种命名服务,在这种服务⾥,对象不但有名称还有属性。
⼀、命名服务与⽬录服务
命名服务:作为⼀种基础设施出现在众多的计算机系统,其意义在于提供根据名称关联对象和通过对象匹配相应的命名服务。命名服务允许你通过名称到⼀个与之对应的对象。例如在Internet上的域名服务(domain namingservice,DNS)就是提供将域名映射到IP地址的命名服务,在打开⽹站时⼀般都是在浏览器中输⼊名字,通过DNS到相应的IP地址,然后打开。
⽬录服务:是⼀种特殊类型的数据库,与SQLServer、Access、Oracle等关系数据库管理系统相反,构造⽬录服务的⽬的是为了处理基于⾏为的事务,并且使⽤⼀种关系信息模型。
⽬录服务将命名服务的概念进⼀步引申为提供具有层次结构的信息库,这⼀信息库除了包含⼀对⼀的关系
外,还有信息的层次结构。对⽬录服务⽽⾔,这种层次结构通常⽤于优化搜索操作,并且也可以按实际情况进⾏分布或者跨⽹络复制。
⽬录服务是命名服务,命名服务不需要是⽬录服务。
命名和⽬录服务把标识符和资源关联起来。
⼆、JNDI基础知识
1. 什么是JNDI
JNDI⽤于定位查服务对象,内部是以⼀种树状的⽬录结构,如下图:
我们只需将服务端的相关参数传给JNDI API就可以了,具体调⽤过程由SPI来完成。
2. 使⽤JNDI有哪些好处?
JNDI将⼀些关键信息放到内存中,可以提⾼访问效率;通过jndi可以达到解耦的⽬的,是连接不同对象的有利纽带。
3. 什么时候使⽤JNDI?
JNDI是⼀种查服务,⽤于查:
web应⽤环境变量、EJBs和他们的环境变量、通过DataSource的数据库连接池、JMS⽬标和连接⼯⼚、其他服务
4. 使⽤JNDI的注意事项
不要将JNDI当做数据库使⽤、JNDI对象存储在内存中、访问JNDI对象与⽹络性能有关
5. JNDI的常⽤⽅法有哪些?
使⽤bind、rebind⽅法进⾏绑定使⽤unbind⽅法解除绑定
使⽤lookup⽅法查
使⽤InitialContext⽅法初始化,可以包含参数,不包含参数的时候使⽤默认值
java设置环境变量的方法代码远程绑定对象必须是序列化的,访问命名服务是,对象采⽤的是复制机制,也就是值的复制
如果使⽤本地对象,使⽤的是变量的引⽤
三、JNDI架构
JNDI架构与JDBI架构⾮常类似。JNDI架构提供了⼀组标准命名系统的API。在应⽤程序中,我们实际上只是⽤以上⼏个包的种类。具体调⽤类以及通信过程对⽤户来说是透明的。JNDI API提供了访问不同JNDI服务的⼀个标准的统⼀实现,其具体实现可由不同的Service Provider来完成。
中间层为命名管理层。其功能应该由JNDI SPI来完成。
最下层为JNDI SPI API及其具体实现。
四、JNDI程序包
javax.naming:命名操作
javax.naming.direcotry:⽬录操作
javax.naming.event:在命名⽬录服务器中请求事件通知
javax.naming.ldap:提供LDAP⽀持
javax.naming.spi:允许动态插⼊不同实现
利⽤JNDI的命名与服务功能来满⾜企业级API对命名与服务的访问,诸如EJB、JMS、JDBC 2.0以及IIO
P上的RMI通过JNDI来使⽤CORBA的命名服务
五、JNDI环境变量
环境变量相应的常量说明
java.naming.factory.initial Context.INITIAL_CONTEXT_FACTORY Context Factory
类名,由服务提供商
给出。
java.naming.provider.url Context.PROVIDE_URL初始化地址。java.naming.security.principal Context.SECURITY_PRINCIPAL服务使⽤者信息。java.dentials Context.SECURITY_CREDENTIAL⼝令。
六、使⽤⽰例
1. 连接服务
从服务器端连接到JNDI:默认当前,返回⼀个context
//创建⼀个InitialContext
context ctx= new InitialContext();
从任何⼀个地反连接到jndi:需要先设置环境
//创建Environment对象
weblogic.jndi.Enviroment env = new weblogic.jndi.Enviroment();
//填写Environment
//weblogic server的位置
env.setProviderurl("t3://127.0.0.1:7011");
env.setSecurityPrincipal("System");
//安全信息
env.setSecurityCredenttials("PassWord");
/
/使⽤Environment对象创建InitialContext
context ctx =InitialContext();
使⽤hash类链接jndi
Hashtble env = new Hashtble();
Env.put(Context.INITIAL_CONTEXT_FACTORY,"weblogic.jndi.WLInitialContextFactory");
Env.put(Context.PROVIDER_URL,"T3://LOCALHOST:7001");
Evn.put(Context.SECURITY_PRINCIPAL,"system");
Env.put(Cotext.SECURIRY_CRRDENTIALS,"PassWord");
//此处有三种构造函数
Context ctx = new InitialContext(env);
使⽤Hardcoded名和Properties类
Properties env = new Properties();
env.setProperty("java.naming.factory.initial","weblogic.jndi.WLInitialContextFactory");
env.setProperty("java.naming.provider.url","t3:192.2.256.102:7001");
env.setproperty("java.naming.securiry.principal","system");
env.setProperty("java.dentials","PaSsWoRd");
Context ctx = new InitialContext(env);
2. 使⽤默认值
jndi.properties⽂件为所有的Initial Contexts设置默认属性,且⽂件的的搜索次序为:CLASSPATH其次是$JAVA_HOME/lib/
Java.naming.factory.initial = weblogic.jndi.WLInitialContextFactory;
Java.naming.provider.url=t3://localhost:7001;
Java.naming.security.principal =system;
Java.dentials =password;
//没有参数,使⽤这些默认值
Context ctx = new InitialContext();
3.创建⼀个⽤于绑定对象的新Subcontext
//创建Environment对象
Context ctx =InitialContext();//⾸先必须获得存在的Subcontext或InitialContext
//填写Environment
Context subcontext =ateSubcontext("newSbucontext");//在当前的Context下创建新的bind("boundObject",object);//绑定⼀个对象
//当结束时经常关闭访问的资源
subcontext.close();
ctx.close();
4.查对象
从JNDI查对象,反序列化后,使⽤事务(多分⽀的事务),Lookup()从JNDI树获得对象。
import javax.naming.*;
try {
Context ic = new Context();
Object obj;
// 查对象
obj = ic.lookup("ansaction.UserTransaction");
// 反序列化和事务
UserTransaction ut = (UserTransaction)obj;
ut.begin();
/
/ 分⽀事务
ic.close();
} catch(NamingException e){
//
}
5.远程绑定对象
在客户端使⽤的时候需要反序列化,传送到服务端的时候是序列化的。
public static Context getInitialContext() throws NamingException{
Environment env = new Environment();
env.setProviderUrl("t3://localhost:7001");
env.setSecurityPrincipal("system");
env.setSecurityCredendtials("weblogic");
Context context = InitialContext();
return context;
}
//获得initial contex
Context ctx = getInitialContext();
//创建名为Bank的对象
Bank myBank = new Bank();
//把对象绑定到JNDI树
ctx.close();
6. un-bind
public static Context getInitialContext() throws NamingException{
Environment env = new Environment();
env.setProviderUrl("t3://localhost:7001");
env.setSecurityPrincipal("system");
env.setSecurityCredendtials("weblogic");
Context context = InitialContext();
return context;
}
//获得initial contex
Context ctx = getInitialContext();
/
/创建名为Bank的对象
Bank myBank = new Bank();
//解除绑定
ctx.unbind("theBank");
ctx.close();
7. 对象改名
8. 获取属性
String dn = "uid=me, dc=mycompany, dc=com, ou=customer, o=ExampleApp";
Context user = (Context)ctx.lookup(dn);
//获得所有属性
Attributes attrs = Attributes("");
Attribute test= attrs .get("test");
Object testValue= ();
9. 修改属性
public void updateAddress(String dn,String address, String country, String phone) {
BasicAttributes mod_attrs = new BasicAttributes();
if(address != null)
mod_attrs.put("address", address);
if(country != null)
mod_attrs.put("c", country);
if(phone != null)
mod_attrs.put("phonenumber", phone);
if(mod_attrs.size() != 0)
difyAttributes(dn, DirContext.REPLACE_ATTRIBUTE, mod_attrs);
}
10.使⽤jndi可能的异常
AuthenticationException
CommunicationException
InvalidNameException
NameNotFoundException
NoInitialcontextException
七、总结
JNDI的思想是提供⼀个通⽤的接⼝。底层的名字服务时限可以是各种类型,JNDI通过SPI时限代码屏蔽了各种名字和⽬录服务实现的区别。
JNDI可以解决数据共享,分布式应⽤,紧耦合的问题,所以可以应⽤在⼀些⽐较⼤的软件开发中,分布式系统中或者是⽐较重视后期维护和升级的项⽬中
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论