JNDI learning

jndi(java naming and directory Interface)它提供了一套使用命名和目录service的接口, 下面的特征表征了JNDI的架构:
*****************************************************************
 java application
-------------------------------------------------------------------------
 jndi api
-------------------------------------------------------------------------
 jndi naming manager
-------------------------------------------------------------------------
-------------------------------------------------------------------------


       LDAP,NOVELL, File System,  NIS,DNS...
*****************************************************************
如同JDBC(Java Database Connectivity),JNDI并不是一种服务,而是一套接口;它允许应用使用标准API来访问很多不同的目录服务供应商。尽Sun公司提供了适配器,比如LADP、DNS和CORBA(LDAP,NOVELL, File System,  NIS,DNS...JNDI 1.2 Service Providers),以连接已有的目录服务供应商,但是就如同JDK包含JDBC一样,它包含了JNDI接口,但并不包含JNDI服务供应商。然而,您可以选择使用免费或者开源JNDI供应商中的一种到您的J2SE应用中去。

      JNDI是整合J2EE应用的黏合剂。JNDI被设计用来支持具有较高动态组装和部署的那些应用,可以在不用重建整个系统的条件下经常的添加和更新各种组件。命名服务则通过作为一个组件注册中心来帮助组织企业级的应用。J2EE应用一般在如下一些方面使用JNDI:
  # 在一个集中、分级数据库中储存应用配置信息
  # 作为在不同应用组件间共享的活动对象的仓库,这些组件能够运行在不同的JVM或者不同的系统中
  # 作为已有目录服务例如LDAP的接口(通过使用特别的方式来访问外部的服务)
     象J2EE应用一样,更大、更多的动态J2SE应用将得益于由动态目录服务带来的松偶合以及动态绑定特点。

jndi包括命名服务和目录服务两部分,其中目录服务包含目录对象directory object,它包含若干属性对象。提供了对属性的很多操作。象LDAP一样,JNDI也是以树的形式存在的name2value的映射,每个context对应一个目录对象,用户可以通过context查找这个对象。但不要把JNDI当作数据库使用,jndi对象存储在内存中,访问jndi对象与网络性能有关。在基本网络性能的前题下,jndi的效率还是很高的。

jndi树
对象绑定到jndi树上,java对象是树叶,context是节点。 InitialContext是jndi树的根节点(其实jndi并没root节点,这里暂时理解成这个意思。),其他的sub context绑定在根节点下,subcontext可以包含自己的context子节点。

JNDI是一种查找服务,用于查找:
1   web应用环境变量
2   ejb对象和他们的环境变量
3   通过DataSource的数据库连接池
4   JMS目录和连接工厂
5  其他服务


远程绑定对象绑定到远程命名服务的对象必须是序列化的
访问命名服务时,对象是采用复制机制

************************************************************************************************************


从JNDI命名空间中储存和回溯对象是简单和易懂的;首先,获得JNDI的命名上下文(naming context),然后,使用bind()和lookup()方法来储存和回溯对象,就象Listing 1中显示的那样:

Listing 1. Store and retrieve objects from a JNDI namespace

存储

  public void createName() throws NamingException {
    Context context = new InitialContext();
    context.bind("/config/applicationName", "MyApp");
  }

其他存储方法

A
// Set up the environment for creating the initial context
Hashtable env = new Hashtable();
//配置出始化参数 指定服务工厂类
env.put(Context.INITIAL_CONTEXT_FACTORY,  "com.sun.jndi.fscontext.RefFSContextFactory");
//指定服务的url。   "E:/dir"是一个存在的目录,把它当作一个命名空间。
env.put(Context.PROVIDER_URL, "file:E:/dir");    //  file:E:/dir   >>>>>>   t3://localhost:7001
env.put(Context.SECURITY_PRINCIPAL, "system");
env.put(Context.SECURIRY_CRRDENTIALS, "password");
Context ctx = new InitialContext(env);

B
另一个例子使用 Hardcoded  和 Properties类
Properties env = new Properties();
env.setProperty("java.naming.factory.initial", "weblogic.jndi.WLInitialContextFactory");  // 上下文工厂的类名,它是服务提供者给定的类名。
env.setProperty("java.naming.provider.url", "t3://localhost:7001");  //服务提供者所使用的配置信息。
Context ctx = new InitialContext(env);


jndi.properties 
该文件在本地的搜索顺序:a classpath  b java_home/lib
===========================================================================================
从jndi查找

1 Lookup()从jndi树获得对象到本地客户端。
2 通过lookup返回的对象必须映射到他们合适的类型

  public String getName() throws NamingException {
    Context context = new InitialContext();
    return (String) context.lookup("/config/applicationName");
  }



Context ctx = new Context();
Object obj = ctx.lookup("java.naming.factory.initial");  // javax是根context,transaction是第一subcontex, UserTransaction就是band name用于查找对象
WLInitialContextFactory ut = (WLInitialContextFactory) obj;
.......

  Listing 1演示的是最通常的JNDI操作:创建一个JNDI上下文,为该上下文绑定对象,从该上下文中回溯对象。需要注意的是,JNDI命名空间以

及客户端可能驻留在不同的JVM中,因此bind()和lookup()方法的调用可能发生在不同的JVM中。JNDI提供商通过使用一系列的技术,包括序列化,来保证对象能够在不同的JVM之间移动,并且可以回溯为它原来的形式。

  Listing 1的代码片断有几个隐藏的假设:JNDI是如何知道在创建上下文的时候该使用哪个提供商?对于需要安全验证的提供商,信任书又从哪里来呢?一般来说,您可以通过在系统属性中设定JNDI相关的属性,或者把它们设定到jndi.properties文件中来制定提供商以及其它连接是所需要的参数。当然,任何的提供商都不能随意的绑定和回溯对象。例如,一些提供商,比如DNS提供商,对象类型是只读的,而有些提供商却可以提供更加灵活的对象类型。大多数卖方提供的供应商能储存和回溯那些实现了以下任何一个接口的对象:java.io.Serializable, java.rmi.Remote, 或者 javax.naming.Referenceable。

隐藏的JNDI供应商
  具有以上特征的JNDI供应商有相同的地方:它们都通过代理来访问外部的目录服务,比如LADP。然而,这里面没有包含一种重要的JNDI供应商类型:内嵌在J2EE容器中的JNDI供应商,它把目录信息储存在内部的数据库中。当我们讨论在J2EE应用中使用JNDI时,通常指的就是这种容器提供的供应商。


J2EE是如何使用JNDI的?

  J2EE应用是以组件形式组装起来的。组件的配置以及互相之间的连接的方式是在部署的时候指定的;大多数的信息被储存在JNDI的命名空间中。J2EE应用使用JNDI来储存配置信息(比如string和numeric类型的常量),无状态的对象(包括对象工厂),以及EJB的home接口。

  JNDI可以看做是黏合剂,它允许您以组件形式比如servlets、Jsps以及EJBs,构建J2EE应用。在J2EE应用中,每个组件不是通过静态的链接而是通过JNDI查找来找寻其它的组件的。J2EE应用还允许在维护类型和链接安全性时进行部署期的绑定,这是通过每个组件报告一份它将需要的其它组件以及资源列表实现的。部署保证在应用中每次导入都有相关正确的组件类型。J2EE容器提供工具来帮助您正确的完成这项工作。


How can J2SE apps use JNDI?

  如同J2EE应用一样,J2SE应用能够将JNDI作为一个储存了命名配置参数、对象以及对象工厂的仓库。工厂创建模式和JNDI可以很好的配合工作,你能够在JNDI命名空间中只保存工厂对象。J2SE应用能够使用JNDI来替换RMI(远程方法调用)来达到更加强大、功能丰富以及集中化的特点。

  大多数的J2SE应用从配置文件中来获取它们的配置信息,这些配置文件要么是属性文件要么是XML文档。这些配置文件指定了所有的配置信息;一些更加复杂的应用为实例化对象的条件比如类名和构造器参数在配置文件中储存信息。

  使用JNDI来储存常量、对象以及对象工厂比传统的配置存储机制有一些优势。因为大多数的JNDI供应商都是支持网络访问的,您就不必为保证每个分散的应用主机上配置文件的一致性而花费精力。此外,使用反射机制来实例化对象是件凌乱的事情,并且需要比简单的通过JNDI命名空间回溯对象更多的代码(一般是更多的出错恢复代码)。使用JNDI并不能避免从配置信息中实例化对象的需要(通常在应用启动,你获得命名空间的时候),这种复杂程度已经从大多数的应用代码中剥离出去了,这样就能简化从JNDI命名空间中回溯期望的对象的程度。

  另外一个在分布式应用中使用JNDI而不是配置文件的原因是配置文件中的信息可能是敏感的信息,比如访问数据库的密码。将Datasource储存

在JNDI的名称空间中,可以不用为整个应用设置密码就完成对整个应用的数据库连接。(比如,PoolMan连接池,一个广泛被使用的开源项目,就是将Datasource对象储存在JNDI名称空间中的。)

  为了在您的J2SE应用中使用JNDI,您首先需要一个JNDI供应商,因为JDK并没有包含。如果您只是想用JNDI来访问外部的目录比如LDAP,那么

您可以使用由Sun提供的供应商中的一个。但是通常来说,您将希望拥有一个独立的供应商,可以有许多的选项供您选择。


************************************************************************************************
**                        Example                                                                                                                                 **
** 说明:下面的例子是jboss对jdni接口的一种实现,通过它的客户端,可以访问jboss中的jndi服务  **
************************************************************************************************

独立的JNDI供应商

  开放原码J2EE服务器JBoss包含了一个JNDI供应商(JNP),它能作为独立服务运行;他提供非常出色的轻量级网络访问JNDI服务。JNP使用记忆在

内存中的数据库来存储对象,所以命名空间的内容在服务重新启动时将不会保存。您可以非常容易的靠它自己来运行JNP,或者通过配置JBoss容器使只有在JNP服务的时候来启动它。

选择1:配置JNP服务以作为JBoss的一项服务
  JBoss应用服务器建立在JMX(Java管理扩展)框架上;该框架允许将应用服务模块化为JMX mbeans,这样可以独立的启动和管理它们。文件jboss.jcml包含了在容器启动的时候装载的一个mbeans列表。JBoss缺省的配置包含超过50个mbeans,但是如果您配置jboss.jcml文件应该只包含单独的如Listing 2中的配置,然后启动JBoss服务器,那么服务器将只装载JNDI供应商,其它的任何J2EE应用服务将不会被装载:

Listing 2. 仅包含JNDI的jboss.jcml文件

<?xml version="1.0" encoding="UTF-8"?>
<server>
  <mbean code="org.jboss.naming.NamingService"
         name="DefaultDomain:service=Naming">
    <attribute name="Port">1099</attribute>
  </mbean>
</server>

选择2:配置JNP服务器使得它单独运行
  JNP还可以作为一个单独存在的应用服务器。为达到这个目的,您需要下面两个jar配置文件:

  # jnpserver.jar -- 在lib/ext目录
  # log4j.jar -- 广泛被使用的日志工具,来自Apache Jakarta项目;在JBoss的lib/ext目录

  此外,您还需要一个log4j.properties文件;Listing 3显示了一个简单的情况。该文件可以通过如下的途径来访问:

Listing 3. 简单的log4j.properties文件

# Use a ConsoleAppender -- write log data to standard out
log4j.rootLogger=DEBUG, A1
log4j.appender.A1=org.apache.log4j.ConsoleAppender
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
log4j.appender.A1.layout.ConversionPattern=%-4r [%t] %-5p %c %x - %m%n

  为了在运行模式下运行JNP服务器,请确保log4j.jar文件、jnpserver.jar文件以及包含log4j.properties文件的目录都可以在您的classpath找到。然后,运行如下命令启动JNP服务器:

  java org.jnp.server.Main

  您也可以在您应用的JVM中使用org.jnp.server对象来启动JNDI服务。


使用JNDI服务

  一旦JNP服务器运行起来,您可以通过配置jnp-clinent.jar文件包含在classpath中,以及在系统属性或者jndi.properties文件中指定java.naming.provider.url和java.naming.factory.initial属性,以让您的应用使用JNP。Listing 4显示了一个jndi.properties文件的例子:

Listing 4. jndi.properties文件

java.naming.provider.url=jnphost.mycompany.com:1099
java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory
java.naming.factory.url.pkgs=org.jboss.naming

  下面的例子显示了在*应用启动*的时候如何使用在属性文件中定义好的string、integer这些对象值相关的参数来获得JNDI命名空间,以及应用组件回溯这些属性(只有应用程序在程序启动的时候存储好对象,后面应用程序才能回溯这些对象。)。简短来说,Listing 5a假设解析XML配置文件的方法并且省略了出错处理的代码:

Listing 5a. 从配置文件中装载JNDI命名空间

   public void loadJNDI() {
    Context context = new InitialContext();
    ConfigItem[] items = getConfigItems();          //jboss提供 ?
    for (int i=0; i<items.length; i++) {
      Object o=null;

      if (items[i].getType().equals("Integer"))
        o = Integer.decode(items[i].getValue());
      else if (items[i].getType().equals("String"))
        o = items[i].getValue();
      else if (items[i].getType().equals("Object"))
        o = Class.forName(items[i].getValue()).newInstance();

      context.bind(items[i].getName(), o);
    }
  }


Listing 5b. XML配置文件示例

   <config>
    <item name="config/screen/resolutionX" type="Integer"
          value="1024" />
    <item name="config/screen/resolutionY" type="Integer"
          value="768" />
    <item name="converters/html" type="Object"
          value="com.mycompany.converters.HtmlRenderer" />
    <item name="converters/pdf" type="Object"
          value="com.pdfmonger.PdfRenderer" />
  </config>


Listing 5c. 在JNDI中回溯和使用对象

   public void convert(InputStream in, OutputStream out) {
    // Retrieve the converter object from JNDI
    Context context = new InitialContext();
    Renderer renderer = (Renderer) context.lookup("converters/html");

    // Use the converter object
    renderer.convert(in, out);
  }


  正如您看到的,从JNDI中回溯对象是非常简单和易懂的。通过使用JNDI来存储配置信息、无状态对象或者对象工厂,您可以轻松的创建灵活的应用,同时将负责的配置信息包含在一个单一的地方,甚至对于分布式的应用也是可以的。(如果您的组件是通过JNDI命名空间来访问对象的,那么将它们之间的依赖关系文档化到这些组件的Javadoc中。)

JNDI并不是只为了J2EE而存在的

  尽管JNDI客户端接口也是J2SE的一部分,但是大多数的J2SE应用并没有使用JNDI。那些使用JNDI的通常只是利用它来访问外部的目录服务比如

LDAP。然而,J2SE应用还可以使用那些到目前为止只有J2EE应用使用的部署时绑定的特征。随着越来越多的JNDI供应商实现例如JNP的出现,

任何需要命名服务的应用都可以拥有它们了。
************************************************************************************************
 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
资源包主要包含以下内容: ASP项目源码:每个资源包中都包含完整的ASP项目源码,这些源码采用了经典的ASP技术开发,结构清晰、注释详细,帮助用户轻松理解整个项目的逻辑和实现方式。通过这些源码,用户可以学习到ASP的基本语法、服务器端脚本编写方法、数据库操作、用户权限管理等关键技术。 数据库设计文件:为了方便用户更好地理解系统的后台逻辑,每个项目中都附带了完整的数据库设计文件。这些文件通常包括数据库结构图、数据表设计文档,以及示例数据SQL脚本。用户可以通过这些文件快速搭建项目所需的数据库环境,并了解各个数据表之间的关系和作用。 详细的开发文档:每个资源包都附有详细的开发文档,文档内容包括项目背景介绍、功能模块说明、系统流程图、用户界面设计以及关键代码解析等。这些文档为用户提供了深入的学习材料,使得即便是从零开始的开发者也能逐步掌握项目开发的全过程。 项目演示与使用指南:为帮助用户更好地理解和使用这些ASP项目,每个资源包中都包含项目的演示文件和使用指南。演示文件通常以视频或图文形式展示项目的主要功能和操作流程,使用指南则详细说明了如何配置开发环境、部署项目以及常见问题的解决方法。 毕业设计参考:对于正在准备毕业设计的学生来说,这些资源包是绝佳的参考材料。每个项目不仅功能完善、结构清晰,还符合常见的毕业设计要求和标准。通过这些项目,学生可以学习到如何从零开始构建一个完整的Web系统,并积累丰富的项目经验。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值