• jndi学习笔记

    2005-12-31

    版权声明:转载时请以超链接形式标明文章原始出处和作者信息及本声明
    http://hankun.blogbus.com/logs/1774694.html

             这两天想研究明白原来的项目中的很多问题,于是反编译了工程中已经打包了的东西,看看它到底是怎么实现的:遇到了些jndi的东西,我就把sun上的jndi的tutorial 下来看了看,不是很懂,但是还是应该把看过的总结一下。


    对jndi总体的理解: jndi(java naming and directory Interface)它提供了一套使用命名和目录service的接口。用户可以通过它来使用命名和目录服务。就像jdbc一样。jndi包括命名服务和目录服务两部分,其中目录服务包含目录对象directory object,它包含若干属性对象。提供了对属性的很多操作。

    命名和目录服务: 命名和目录服务我们一直在使用,如操作系统的文件系统,它给我们提供对文件的操作,查询,添加删除等功能。DNS服务将url同ip地址绑定在了一起。命名和目录系统的最主要的功能是将name和对象绑定。在它的基础之上还提供更多的功能如lookup,search.而且存储的对象是有一定层次结构的。使用这样的服务我们可以对对象更加有效的管理和操作。

    j2se为jndi提供了5个扩展包:
    javax.naming;为访问命名服务提供的api
    javax.naming.directory;为访问目录服务提供了基本的接口
    javax.naming.event;支持命名和目录服务中的事件通知
    javax.naming.ldap; 支持ldap的包,
    javax.naming.spi;提供了不同命名和目录服务可以挂接他们的实现的方法。


    context: context是一套name-to-object的绑定(bindings),可以理解为层次或目录,它还可已包括下一层subContext。在使用命名和目录服务时获得initial context是对整个名字空间操作的入口。在目录服务中是DirContext.


    简单的使用实例
    1。本实例中使用的service时文件系统service,jdk中没有提供,需要从http://java.sun.com/products/jndi/serviceproviders.html
    下载最新的文件系统服务包(目前使用fscontext-1_2-beta3.zip)将它添加进工程的classpath下。
    2。JNDIStudy.java

    -------------------------------------------------------------

    import javax.naming.*;
    import java.util.Hashtable;

    class JNDIStudy {
        public static void main(String[] args) {

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

     try {
         // Create the initial context
         Context ctx = new InitialContext(env);

         // Get listing of context
         NamingEnumeration bindings = ctx.listBindings("");
         // Go through each item in list
         while (bindings.hasMore()) {
      Binding bd = (Binding)bindings.next();
      System.out.println(bd.getName() + ": " + bd.getObject());
         }
                 //在context下建立两个子上下文,在文件系统中对应目录。
         ctx.createSubcontext("awt");
         ctx.createSubcontext("aaa");
         //给命名改名,在文件系统中就是给目录改名。
                ctx.rename("aaa","bbb");
                //查找名字对应的对象,"E:/dir/svc.txt"对应的对象
                Object obj = ctx.lookup("svc.txt");
                System.out.println("svc.txt is bingiing with " + obj);
         // Close the context when we're done
         ctx.close();
     } catch (NamingException e) {
         System.out.println("List Bindings failed: " + e);
     }
        }
    }

    ---------------------------------------------------------------

    这就是通过jndi来调用service的一个简单的例子。

    在我们的项目中使用jnp: J2EE服务器JBoss包含了一个开源JNDI服务(JNP),它能作为独立服务运行;他提供非常出色的轻量级网络访问JNDI服务。JNP使用记忆在内存中的数据库来存储对象,


    配置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配置文件的方法并且省略了出错处理的代码:

    从配置文件中装载JNDI命名空间

       public void loadJNDI() {
        Context context = new InitialContext();
        ConfigItem[] items = getConfigItems();
        for (int i=0; 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);
        }
      }

    被装载对象XML配置文件示例

      
                  value="1024" />
                  value="768" />
                  value="com.mycompany.converters.HtmlRenderer" />
                  value="com.pdfmonger.PdfRenderer" />
     


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


    收藏到:Del.icio.us




    评论

  • 笔者的这篇文章的部分内容的英文原文,来自于javaworld这个网站,文章为:“ J2EE or J2SE? JNDI works with both"
  • jndi结构包括三个结构?
    a应用层 b实现层 c数据层 djndi api层
    哪位高手知道选?
  • 偷人家东西!垃圾!copy.你还是研究生呢?鄙视你!!!
  • 最后哪些代码你省略了很多,看不懂,麻烦你补充一下
  • 好,好