地址:http://lincoln.iteye.com/blog/87712 JNDI是JAVAEE 平台技术中最重要的基础支撑技术之一。他为各种Java对象进行命名,并采用目录层次结构管理它们,借助于JNDI API能够操控各种JAVA对象。实际上,JAVAEE5 引入各种Annotation注释(比如,@EJB,@Resource)底层采用JNDI API查找 JavaEE 容器受管资源(比如,EJB3.0组件,JDBC DataSource,JMS ConnectionFactory),并注入到那些应用了Annotation注释的JavaEE组件 (比如,Servlet,JSF后端Bean,EJB3.0组件)中。
Spring2.0针对JNDI API的使用提供了JNDI集成,org.springframework.jndi包就是见证。在Spring 1.x使能应用中,JndiObjectFactoryBean是Spring开发者使用最频繁的工厂Bean,而JndiTemplate模板的使用也非常频繁。自从Spirng 2.0开始,<jndi-lookup/>内容模式被引入到JNDI集成工作中。此后,<jidi-lookup/>便代替了JnidObjectFactoryBean的地位,当然JndiObjectFactoryBean是<jndi-lookup/>底层采用的工厂Bean。
本章从介绍JNDI背景知识及实例入手,进而进入到Spring提供的JNDI集成支持中。随后,Spring2.0引入的<jndi-lookup/>内容模式被介绍到。
背景知识及示例
现有的企业当中,存在各式各样的命名和目录服务。何谓命名和目录服务?命名和目录服务是同过名字,目录形式来管理系统中的对象,无力设备等内容的一种服务。比如,微软活动目录(AD)、OpenDAP服务器。为了通过应用操纵它们,开发者需要借助于响应的客户端API或客户软件
在JNDI出现之前,开发者只能够通过专有方式操作命名和目录服务,这无疑加大了开发者的学习负担。甚至,企业的实现环境都是异构的,哪怕是同一种目录服务器都会因为运行的操作系统的不同而提供多套客户端API。
JNDI,即Java命名目录服务接口(Java Naming and Directory Interface),它能够对命名和目录服务器进行CRUD操作,这同JDBC与RDBMS的关系类似。只要命名和目录服务器厂商提供对应的JNDI实现,开发者便能够一致地通过接口操纵它们,从而避免了与厂商绑定的风险。
类似于DNS,JNDI能够讲对象赋予有意义的名字。在DNS中,通过逻辑能够实现对IP地址的映射。在JNDI中,通过预先绑定的名字能够找到目标服务或者对象。比如,借助于JNDI,我们能通过“java.:/AgileSpringDS”名字获得javax.sql.DataSource对象。这些都是通过Java命名系统获得的。JNDI在Java SE/Java EE中起到了很重要的作用,正如DNS在当今的因特网中的地位一样,而且会越来越重要。比如,Web服务的兴起、SOA架构的兴起,会使得JNDI在应用中扮演关键角色。
通常,Java EE应用服务器(比如,GlassFish,JBoss)都会提供命名或目录服务实现(或称为服务提供者)。BEA WebLogic内部采用了LDAP服务器完成登录用户的认证。同样地,在Java SE环境开发中也可以使用本地JNDI服务提供者(而不是由Java EE服务器提供的)。通过http://java.sun.com/products/jidi/serviceproviders.html,开发者能够浏览到很多JNDI服务提供者。这里,我们以 File System提供者为例。如果开发者熟悉IBM WebSphere MQ,则应该知道他的JNDI实现这是在File System基础之上开发的。打开Eclipse filesystemjndidemo项目,来分析如下代码。
Java代码
Hashtable<String,String> env = new Hashtable<String,string>(2);
//设定上下文工厂
Env.put(Context.INITIAL_CONTEXT_FACTORY,”com.sun.jndi.fscontext.RefFSContextFactroy”);
//设置文件系统路径(注意,开发者需要依据自身的机器修改”file:d://eclipse”)
Env.put(Context.PROVIDER_URL,”file:d://eclipse”);
Context initCtx = null;
Try{
//获得初始化上下文
initCtx = new initialContext(env);
//借助于JNDI,查找文件
Object fc =initCtx.lookup(“eclipse.ini”);
Log.info(fc);
}
Catch(NamingException ne){
//处理命名异常
Log.error(“NamingException”,ne);
}
Finally{
Try{
//关闭上下文
initCtx.close();
}catch(NamingException ne){;}
}
Hashtable<String,String> env = new Hashtable<String,string>(2);
//设定上下文工厂
Env.put(Context.INITIAL_CONTEXT_FACTORY,”com.sun.jndi.fscontext.RefFSContextFactroy”);
//设置文件系统路径(注意,开发者需要依据自身的机器修改”file:d://eclipse”)
Env.put(Context.PROVIDER_URL,”file:d://eclipse”);
Context initCtx = null;
Try{
//获得初始化上下文
initCtx = new initialContext(env);
//借助于JNDI,查找文件
Object fc =initCtx.lookup(“eclipse.ini”);
Log.info(fc);
}
Catch(NamingException ne){
//处理命名异常
Log.error(“NamingException”,ne);
}
Finally{
Try{
//关闭上下文
initCtx.close();
}catch(NamingException ne){;}
}
上述代码先构造env,然后传给InitialContext.此时,”file:d://eclipse”成了JNDI树的根,eclipse目录下的所有文件和目录都成为了树的成员。在查找到eclipse.ini后,需要关闭相应的InitialContext。整个过程需要处理NamingException异常。
用户可以将应用对象存储在命名和目录服务提供者中,并供JNDI应用访问。比如,开发者可以将数据源存储在命名和目录服务器中;通过JNDI能够获得JTA事务管理其(存储在JavaEE 应用服务器提供的命名和目录服务器中)。
实例仅仅展示了JNDI的冰山一角。在实际企业应用中,JNDI的使用更多地发生于Web,EJB,Ear应用场合。比如,在JSF受管组件中访问EJB3.0组件,借助于JNDI访问JMS Topic及ConnectionFactory。在这些场合中,JNDI的使用非常复杂。如果直接通过JNDI API操控目标资源,开发者要处理很多与实际业务无关的开发内容,具体如下:第一,要负责InitialContext的创建、关闭工作;第二,要负责异常处理;第三,要考虑JNDI树上查找目标资源的实际;第四,查找到目标资源后,开发者还要考虑缓存策略(运行时是否需要重新去JNDI树上获取资源,否则他会持有过期资源);第五,要区别对待开发时和生产环境的JNDI处理。考虑到这些对开发者的不利因素,Spring对JNDI提供了全方位的支持,这也是Spring驱动敏捷开发的又一举措。
通过将JNDI查找操作定义在Spring配置文件中,应用能够操作到相关的JNDI对象,开发者再也不用对JNDI进行硬编码。最为重要的一点是,应用对这些JNDI对象的依赖都是通过IoC容器注入的,因此开发者不用关注具体对象是从哪里来。甚至,Spring2.0对于Java EE资源(包括JNDI)的配置做了许多简化工作,比如引入<jee:jndi-lookup/>内容模式。 为了简化 JNDI API 的使用,Spring 2.0框架专门提供了org.springframework.jndi包。其中,JndiTemplateEditor类继承于PropertyEditorSupport类,供实现JndiTemplate对象的属性编辑器使用,即开发者能够通过字符串方式实现对JndiTemplate值得设置(或者在IDE中编辑它)。
通常,开发者可以通过如下4种方式对JNDI资源进行CRUD操作。
1. 单独使用JndiObjectFactroyBean:这种方式最常见(Spring1.x)。这是负责查找JNDI对象的FactroyBean。
2. 同时使用JndiObjectTargetSource和ProxyFactoryBean:这种组合使用较少,因为这同上述单独使用JndiObjectFactoryBean的效果一样,而且在配置上也没有占有优势。
3. 使用JndiTemplate:辅助类,类似于JdbcTemplate,以简化对JNDI的CRUD操作。如果用户需要进行高级自定义工作,则还可以使用JndiCallback回调接口。
4. Spring2.0引入的<jndi-lookup/>内容模式。
单独使用JndiObjectFactoryBean
为了展示JndiObjectFactoryBean的功力,我们来使用JBoss应用服务器提供的JNDI服务。通过JBoss的JMX控制台应用,开发者能够获得全局JNDI名。
我们以消息队列“queue/testQueue”为例,并结合Jbossjndidemo项目进行阐述。
Java代码
<bean id="tq"
class="org.springframework.jndi.JndiObjectFactoryBean">
<!-- 指定JNDI模板 -->
<property name="jndiTemplate" ref="jndiTemplate" />
<!-- 指定JNDI名字 -->
<property name="jndiName" value="queue/testQueue" />
<!-- 是否缓存查找到的Java对象 -->
<property name="cache" value="true"></property>
<!-- 启动时是否去JNDI树查找目标资源(即,由jndiName指定的) -->
<property name="lookupOnStartup" value="true"></property>
<!-- 是否为资源引用 -->
<property name="resourceRef" value="false"></property>
</bean>
<bean id="jndiTemplate"
class="org.springframework.jndi.JndiTemplate">
<!-- 具体的属性与厂商提供的产品有关 -->
<property name="environment">
<props>
<prop key="java.naming.factory.initial">
org.jnp.interfaces.NamingContextFactory
</prop>
<prop key="java.naming.provider.url">
jnp://localhost:1099
</prop>
<prop key="java.naming.factory.url.pkgs">
org.jboss.naming:org.jnp.interfaces
</prop>
</props>
</property>
</bean>
<bean id="tq"
class="org.springframework.jndi.JndiObjectFactoryBean">
<!-- 指定JNDI模板 -->
<property name="jndiTemplate" ref="jndiTemplate" />
<!-- 指定JNDI名字 -->
<property name="jndiName" value="queue/testQueue" />
<!-- 是否缓存查找到的Java对象 -->
<property name="cache" value="true"></property>
<!-- 启动时是否去JNDI树查找目标资源(即,由jndiName指定的) -->
<property name="lookupOnStartup" value="true"></property>
<!-- 是否为资源引用 -->
<property name="resourceRef" value="false"></property>
</bean>
<bean id="jndiTemplate"
class="org.springframework.jndi.JndiTemplate">
<!-- 具体的属性与厂商提供的产品有关 -->
<property name="environment">
<props>
<prop key="java.naming.factory.initial">
org.jnp.interfaces.NamingContextFactory
</prop>
<prop key="java.naming.provider.url">
jnp://localhost:1099
</prop>
<prop key="java.naming.factory.url.pkgs">
org.jboss.naming:org.jnp.interfaces
</prop>
</props>
</property>
</bean>Spring2.0引入的jndi-lookup内容模式
自从Spring2.0开始,便引入了XML Schema来管理BeanFactory、ApplicationContext的配置。无论是语义,还是表达、复用能力,XML Schema都强于DTD。使用XML Schema定义新的数据类型非常方便,当然,要掌握XML Schema还是要费一番功夫的。在RDBMS领域,存在很多O/R Mapping技术,比如Hibernate、JPA、TopLink、Kodo JDO等。在XML领域,也存在很多O/X Mapping技术,比如XML Beans、JAXB、Castor等。借助于它们,应用操作XML文档会很方便。
Spring引入的jee内容模式中含有jndi-lookup数据类型,使用它能够大大简化JNDI的配置。开发者只需要调整Spring XML配置文件,而应用本身不需要做任何修改。相应的内容模式如下,它定义了jndi-lookup的结构和语义。
Jndi-name: 待查找的JNDI名,必填项
Resource-ref:是否是资源引用,可选项。如果是,则需要在web.xml和厂商特定的部署描述符中进行映射。默认取值为false。
Cache:是否缓存查找到的JNDI对象,可选项。默认取值为true
Expected-type:期待的JNDI对象类型,可选项
Lookup-on-startup:是否在启动时去JNDI上查找对象,可选项。默认取值为true
Proxy-interface:代理接口,可选项。配合cache和lookup-on-startup使用
Environment:JNDI环境信息,可选项。如果有多项值对需要给出,则要遵循属性文件的格式。
接下来,我们将重点放在DTD(Spring1.x)到XML Schema(Spring2.0)的移植上。开发者只需要将jee命名空间(spring-jee-2.0.xsd)导入到spring配置文件中,便可以使用到它,具体如下。
Java代码
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jee="http://www.springframework.org/schema/jee"
xsi:schemaLocation=
"http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/jee
http://www.springframework.org/schema/jee/spring-jee-2.0.xsd">
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jee="http://www.springframework.org/schema/jee"
xsi:schemaLocation=
"http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/jee
http://www.springframework.org/schema/jee/spring-jee-2.0.xsd">
研究这一新特性,示例配置如下,开发者再也看不到JndiObjectFactoryBean、JndiObjectTargetSource的影子,而且配置清晰。
Java代码
<jee:jndi-lookup id="tq" jndi-name="queue/testQueue"
cache="false"
expected-type="javax.jms.Queue"
lookup-on-startup="true"
proxy-interface="javax.jms.Queue"
resource-ref="false">
<jee:environment >
java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory
java.naming.provider.url=jnp://localhost:1099
java.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfaces
</jee:environment>
</jee:jndi-lookup>
<jee:jndi-lookup id="tq" jndi-name="queue/testQueue"
cache="false"
expected-type="javax.jms.Queue"
lookup-on-startup="true"
proxy-interface="javax.jms.Queue"
resource-ref="false">
<jee:environment >
java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory
java.naming.provider.url=jnp://localhost:1099
java.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfaces
</jee:environment>
</jee:jndi-lookup>由于该示例运行在web容器之外,因此配置看起来稍微有一点复杂。如果应用运行在web容器之中,而且与本地JNDI服务交互,则不用提供environment属性。下面给出的两个版本都是合法的。
Java代码
<jee:jndi-lookup id="tq" jndi-name="queue/testQueue"/>
<jee:jndi-lookup id="tq" jndi-name="queue/testQueue"/>
Java代码
<jee:jndi-lookup id="tq" jndi-name="queue/testQueue"
cache="false"
expected-type="javax.jms.Queue"
lookup-on-startup="true"
proxy-interface="javax.jms.Queue"
resource-ref="false"/>
<jee:jndi-lookup id="tq" jndi-name="queue/testQueue"
cache="false"
expected-type="javax.jms.Queue"
lookup-on-startup="true"
proxy-interface="javax.jms.Queue"
resource-ref="false"/>最后要指出的是Spring2.0兼容Spring1.x的所有配置。
分享到:
相关推荐
### Spring2.0与Spring2.5及以上版本的jar包区别及spring jar包详解 #### 概述 Spring框架作为一款流行的Java应用开发框架,在不同的版本之间,其提供的功能、性能以及兼容性等方面都有所差异。本文将重点介绍...
- **与J2EE的深度集成**:Spring 2.0与J2EE环境紧密结合,支持EJB、JNDI、JTA等技术,同时提供了一种轻量级替代方案,使得开发者可以在没有J2EE服务器的情况下开发和部署应用。 - **SOA(面向服务架构)集成**:...
Spring可以与Java EE的许多技术无缝集成,如JNDI、EJB、JMS、JTA等,它提供了一种轻量级替代方案,避免了过度使用企业级Java组件带来的复杂性。 六、Spring Boot Spring Boot是基于Spring框架的快速开发工具,它...
本篇将详细讲解如何将Spring 3.0.5与JPA 2.0(基于Hibernate 3.6)进行集成,以构建高效、灵活的应用程序。 首先,让我们了解Spring 3.0.5的核心特性。Spring 3.0引入了若干改进和新特性,包括对JSR-303(Bean ...
- **JNDI 查找**:如果JBPM服务在应用服务器中以 JNDI 方式暴露,Spring 可以通过 JNDI 查找来获取这些服务。 - **Spring AOP 集成**:可以利用 Spring 的 AOP 功能来拦截流程中的关键操作,例如在任务分配、流程...
2. Spring 2.0 的新特性 2.1. 简介 2.2. 控制反转(IoC)容器 2.2.1. 更简单的XML配置 2.2.2. 新的bean作用域 2.2.3. 可扩展的XML编写 2.3. 面向切面编程(AOP) 2.3.1. 更加简单的AOP XML配置 2.3.2. 对@AspectJ 切面的...
6.4.3 在Spring 2.0里声明事务 6.4.4 定义注释驱动事务 6.5 小结 第7章 保护Spring 7.1 Spring Security介绍 7.2 验证用户身份 7.2.1 配置Provider Manager 7.2.2 根据数据库验证身份 7.2.3 根据LDAP仓库...
Spring 还提供了对 Java EE 环境的支持,如 JNDI 查找、EJB 集成等。例如,可以通过 `<jee:jndi-lookup>` 元素进行 JNDI 查找: ```xml <jee:jndi-lookup id="dataSource" jndi-name="java:comp/env/jdbc/myDS" ...
无论是独立运行的应用还是集成到更大系统中的组件,Spring都能够提供一致的支持和服务。 #### 二、Spring核心容器 Spring的核心容器是框架的基础,它支持依赖注入(DI)模式,用于管理和配置应用程序中的对象。...
Spring2.0引入了核心容器、数据访问/集成、Web、AOP和测试等模块,为Java应用提供了强大的支持。 将这三个框架整合在一起,首先需要确保所有必需的jar包都已包含。Struts2、Hibernate和Spring的jar包包括了各自的...
6.4.3在spring2.0里声明事务 6.4.4定义注释驱动事务 6.5小结 第7章保护spring 7.1springsecurity介绍 7.2验证用户身份 7.2.1配置providermanager 7.2.2根据数据库验证身份 7.2.3根据ldap仓库进行身份验证 ...
6.4.3 在Spring 2.0里声明事务 6.4.4 定义注释驱动事务 6.5 小结 第7章 保护Spring 7.1 Spring Security介绍 7.2 验证用户身份 7.2.1 配置Provider Manager 7.2.2 根据数据库验证身份 7.2.3 根据LDAP仓库...
1. **JNDI Template**: 在配置过程中,使用了Spring的`JNDI Template`来查找JNDI环境中的资源。这通常用于获取外部系统的配置信息,例如数据库连接信息等。 2. **locatorFactorySelector**: 这个变量用来决定如何...
Spring从2.0版本开始,就包含了对JOTM的支持,通过`org.springframework.transaction.jta.JotmFactoryBean`,开发者可以方便地在Spring应用中集成JOTM,创建本地事务管理实例。 集成JOTM并使用JTA事务的步骤如下: ...
使用这样的库,开发者可以更容易地在自己的项目中集成和使用JNDI DirContextSource。 总的来说,JNDI DirContextSource是Java开发者与目录服务交互的关键工具,特别是在开源社区中,它极大地简化了目录操作并提高了...
总结来说,这个例子展示了如何在Spring环境中集成和使用JBPM,以实现流程的自动化和管理。通过Spring的依赖注入和事务管理,我们可以更方便地控制和调试流程,同时保持代码的简洁性和可维护性。这种整合方式在实际...
Acegi Security在Spring Security 2.0版本之前被广泛使用,它为Web应用程序提供了细粒度的安全控制功能。通过Acegi Security,开发者可以轻松地实现基于角色的安全性,确保只有经过验证的用户才能访问特定资源。 ##...
- **易于测试**:使得单元测试更加简单,无需使用单例模式或 JNDI 查找机制。 - **松耦合**:通过最小的代价和最少的侵入性实现了组件间的松耦合。 - **初始化支持**:IoC 容器支持懒加载和饿汉式初始化,可以...
1. **Spring2.0压缩包目录结构** - **aspectj**:包含了使用AspectJ进行AOP编程的相关源码和测试程序。 - **dist**:存放Spring的发布包,包括不同模块的jar包。 - **docs**:提供了Spring的API文档、参考指南、...