JNDI 笔记(转)

JNDI 笔记(转)

JNDI 笔记(一) 概述html

JNDI,Java Naming Directory Interface,J2EE的标准之一,全部的J2EE容器都必须提供一个JNDI的服务,可是,我一直都没用过,至少是没有刻意地去用过。由于,我也曾经把数据源配置在Tomcat的JNDI服务中,但那时,我也只是刚刚涉足JAVA,有人告诉我应该这么干而已。后来,我开始使用自定义的数据库链接配置文件,就再也没有跟JNDI打过交道了,直到今天。

如今之因此又想看一下,只是由于以为这是J2EE的重要标准之一,若是不懂得的话,彷佛有点说不过去。

JNDI的主要功能能够这样描述,它使用一张哈希表存储对象(大多数的J2EE容器也的确是这样作的),而后,开发人员可使用键值——也就是一个字符串——来获取这个对象。这里就包括取JNDI的两个最主要操做,bind和lookup。bind操做负责往哈希表里存对象,存对象的时候要定义好对象的键值字符串,lookup则根据这个键值字符串往外取对象。

JNDI的命称可能会让人产生混淆,彷佛以为这是一个用来操做目录的,事实上,我更愿意把这个目录理解成为JNDI存放对象时使用的格式,也就是说,JNDI以目录的方式存储对象的属性。例如,用户经过JNDI存储一个汽车对象,那么,汽车就是根目录,汽车的轮子、引擎之类的子对象就算是子目录,而属性,好比说汽车的牌子、重量之类,就算是汽车目录下的文件。

JNDI的功能既然就是根据一个字符串键值就能够取得一个想要获得的对象,我一开始就以为这不是跟COM或CORBA同样吗?SUN也是有野心的企业啊,JNDI应该就是它要努力推行的JAVA下的分布式开发的标准吧。

JNDI的出现应该就是为了分步式开发服务的,有人负责开发这种分布式对象,有人只须要使用这些分布式对象就能够了,这两组人没必要属于同一个公司,并且这种开发一般应该是不并行的,也没必要是会了同一个项目服务。就若是数据源对象,它放在JNDI中,只要想要用的人,直接经过JNDI服务取来用就能够了,至于当初是谁把它放进JNDI中的,仍是不用操这份心了吧。而我一直没有使用JNDI,也就是这个缘由,项目中的全部对象都在我控制之下,我不去使用别人的对象,也没打算把个人对象贡献出来给别人使用,那天然也就不必去跟JNDI打交道。我以为是否使用JNDI,这应该是关键缘由,至于什么方便性、安全性之类的考虑,应该不是JNDI的主要目的,就如同你能够用JAVA来作网站,但JAVA并非专门用来作网站的。

可能有人以为这种功能跟IoC也很象,这个我倒不以为,虽然对于对象的使用人员来讲的确是这种感受,且不说IoC须要为对象定义接口,而JNDI并没有此限制,先说这里有一个使用环境问题,我以为IoC是用来解决并行开发问题的,也就是说IoC主要是用于明确设计人员与实现/使用人员的分工,不管是设计的,仍是使用的,一般是一个项目组里的人,使用IoC,可使得设计人员专一于设计,加快设计速度。所以,IoC的用途要比JNDI普遍的多,如今大型系统中,不使用IoC的,几稀矣。


JNDI 笔记(二) J2EE下使用JNDIjava

在J2EE环境下使用JNDI是很是简单的事,由于全部的J2EE容器都要实现JNDI服务,因此,在J2EE环境下使用JNDI,与使用Hashtable也没有什么太大区别。只有一点限制,那就是绑定对象时,对象所属的类必须实现java.io.Serializable接口,这一点也实在一点也不困难,几乎全部用到的Java类都实现了这个接口,对于自定义的类,在接口实现列表里把这个接口加进去也就是了。web

下面,我将演示一下如何在J2EE环境下使用JNDI,为了保证代码的通用性,我不使用struts之类的框架,而是直接使用标准JSP和Servlet实现。我将该项目的名称定为jndi_test数据库

要使用JNDI,须要先到SUN的网站上去下载jndi.jar。安全

 2.1 JSP

本项目包括5个JSP,功能说明以下:服务器

  • index.jsp:首页
  • bind.jsp:用于在JNDI中绑定对象
  • bind_result.jsp:绑定对象后的返回页面
  • lookup.jsp:用于在JNDI中检索对象
  • lookup_result.jsp:用于显示检索对象

本节中用到的JSP代码以下,代码都简单地很,就很少作解释了。app

2.1.1 index.jsp

<% @ page language="java" contentType="text/html; charset=GB18030"
    pageEncoding
="GB18030"
%>
<! DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd" >
< html >
< head >
< meta  http-equiv ="Content-Type"  content ="text/html; charset=GB18030" >
< title > JNDI Test </ title >
</ head >
< body >
< href ="bind.jsp"  target ="_blank" > bind.jsp </ a >
< br  />
< href ="lookup.jsp"  target ="_blank" > lookup.jsp </ a >
</ body >
</ html >

2.1.2 bind.jsp

<% @ page language="java" contentType="text/html; charset=GB18030"
    pageEncoding
="GB18030"
%>
<! DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd" >
< html >
< head >
< meta  http-equiv ="Content-Type"  content ="text/html; charset=GB18030" >
< title > JNDI Test - Bind </ title >
</ head >
< body >
< href ="bind.do" > bind an object </ a >
</ body >
</ html >

2.1.3 bind_result.jsp

<% @ page language="java" contentType="text/html; charset=GB18030"
    pageEncoding
="GB18030"
%>
<! DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd" >
< html >
< head >
< meta  http-equiv ="Content-Type"  content ="text/html; charset=GB18030" >
< title > JNDI Test - Bind result </ title >
</ head >
< body >
< p > Binded successfully! </ p >
</ body >
</ html >

2.1.4 lookup.jsp

<% @ page language="java" contentType="text/html; charset=GB18030"
    pageEncoding
="GB18030"
%>
<! DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd" >
< html >
< head >
< meta  http-equiv ="Content-Type"  content ="text/html; charset=GB18030" >
< title > JNDI Test - lookup </ title >
</ head >
< body >
< href ="lookup.do" > lookup the binded object </ a >
</ body >
</ html >

2.1.5 lookup_result.jsp

<% @ page language="java" contentType="text/html; charset=GB18030"
    pageEncoding
="GB18030"
%>
<! DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd" >
< html >
< head >
< meta  http-equiv ="Content-Type"  content ="text/html; charset=GB18030" >
< title > JNDI Test - Lookup result </ title >
</ head >
< body >
<%
    
Object o = request.getAttribute("found_jndi_obj");
    out.println(o);
%>
</ body >
</ html >

2.2 Servlet

本例包括两个Servlet,功能说明以下:框架

  • BindServlet:用于在JNDI服务中绑定一个对象
  • LookupServlet:用于在JNDI服务中取出一个对象

2.2.1 BindServlet.java

package  lld.test.jndi;

import  java.io.IOException;
import  java.util.Date;

import  javax.naming.Context;
import  javax.naming.InitialContext;
import  javax.servlet.RequestDispatcher;
import  javax.servlet.ServletContext;
import  javax.servlet.ServletException;
import  javax.servlet.http. * ;

public   class  BindServlet  extends  HttpServlet
{

    
private static final long serialVersionUID = 5219969790998794367L;

    @Override
    
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
            
throws ServletException, IOException
    
{
        
this.doPost(req, resp);
    }


    @Override
    
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
            
throws ServletException, IOException
    
{
        
try
        
{
            Context jndi_ctx 
= new InitialContext();
            String key 
= "jndi_object";
            jndi_ctx.rebind(key, 
new Date());
        }
catch(Exception ex)
        
{
            ex.printStackTrace();
        }

        
        ServletContext context 
= this.getServletContext();
        RequestDispatcher dispatcher 
= context.getRequestDispatcher("/bind_result.jsp");
        dispatcher.forward(req, resp);
    }

    
}

使用rebind而不是bind绑定对象是由于,使用bind时,若是已经有对象绑定到该键值上,则会抛出异常。jsp

由于只是示例代码,因此我只是绑定了一个最简单的日期对象。分布式

2.2.2 LookupServlet.java

package  lld.test.jndi;

import  java.io.IOException;

import  javax.naming.Context;
import  javax.naming.InitialContext;
import  javax.servlet.RequestDispatcher;
import  javax.servlet.ServletContext;
import  javax.servlet.ServletException;
import  javax.servlet.http.HttpServlet;
import  javax.servlet.http.HttpServletRequest;
import  javax.servlet.http.HttpServletResponse;

public   class  LookupServlet  extends  HttpServlet
{
    
private static final long serialVersionUID = 6677219828267184673L;

    @Override
    
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
            
throws ServletException, IOException
    
{
        
this.doPost(req, resp);
    }


    @Override
    
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
            
throws ServletException, IOException
    
{
        
try
        
{
            Context jndi_ctx 
= new InitialContext();
            String key 
= "jndi_object";
            Object o 
= jndi_ctx.lookup(key);
            req.setAttribute(
"found_jndi_obj", o);
        }
catch(Exception ex)
        
{
            ex.printStackTrace();
        }

        
        ServletContext context 
= this.getServletContext();
        RequestDispatcher dispatcher 
= context.getRequestDispatcher("/lookup_result.jsp");
        dispatcher.forward(req, resp);
    }

    
}

2.3 web.xml

在web.xml中,加入了servlet映射

<? xml version="1.0" encoding="UTF-8" ?>
< web-app  id ="WebApp_ID"  version ="2.4"  xmlns ="http://java.sun.com/xml/ns/j2ee"  xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance"  xsi:schemaLocation ="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd" >
    
< display-name > jndi_test </ display-name >
    
    
< servlet >
        
< servlet-name > BindServlet </ servlet-name >
        
< servlet-class > lld.test.jndi.BindServlet </ servlet-class >
    
</ servlet >
    
< servlet-mapping >
        
< servlet-name > BindServlet </ servlet-name >
        
< url-pattern > /bind.do </ url-pattern >
    
</ servlet-mapping >
    
    
< servlet >
        
< servlet-name > LookupServlet </ servlet-name >
        
< servlet-class > lld.test.jndi.LookupServlet </ servlet-class >
    
</ servlet >
    
    
< servlet-mapping >
        
< servlet-name > LookupServlet </ servlet-name >
        
< url-pattern > /lookup.do </ url-pattern >
    
</ servlet-mapping >
    
    
< welcome-file-list >
        
< welcome-file > index.jsp </ welcome-file >
    
</ welcome-file-list >
</ web-app >

OK,全部的代码都在这里了,部署到Tomcat下运行便可。


JNDI 笔记(三) J2SE下使用JNDI

在J2SE下使用JNDI下就显得困难一些,首先,咱们没有单独的JNDI服务器能够用,JBoss提供了一个免费的JNP服务,经过配置能够做为单独的JNDI服务器启用。不过这里就不这么麻烦了,如何使用JBOSS做为JNDI服务器,之后将单独撰文讲述,这里我使用sun提供的com.sun.jndi.fscontext.RefFSContextFactory做为JNDI服务器,其实这是使用文件系统来存储JNDI对象。至于如何存储后文还将专门描述。

为了在J2SE下使用JNDI,咱们首先获得sun的网站上下载3个包,jndi.jar、fscontext.jar和providerutil.jar,前者提供了JNDI服务的接口,后二者是咱们要使用的文件系统做为JNDI服务器的支持包。

使用RefFSContextFactory,要求绑定的对象必须实现javax.naming.Referencable接口,不然在绑定时将报以下错误:

Can only bind References or Referenceable objects

各个JDBC驱动提供商提供的DataSource类都实现了Referencable接口,能够直接使用。不过本着学习的态度,我仍是在这里演示一下如何实现Referencable接口。

这个如何实现将在后文结合代码详细介绍。本例包括4个类,说明以下:

  • BindedClass:自定义的实现Referenceable接口的类
  • BindedClassFactory:工厂类,可以把一个Reference对象转换为BindedClass对象
  • Bind:测试类,用于在JNDI中绑定对象
  • Loopup:测试类,用于从JNDI中获取对象

3.1 BindedClass和BindedClassFactory

3.1.1 BindedClass

package  lld.test.jndi;

import  javax.naming.NamingException;
import  javax.naming.Reference;
import  javax.naming.Referenceable;
import  javax.naming.StringRefAddr;

public   class  BindedClass  implements  Referenceable 
{
    
public String value; 
    
    
public BindedClass()
    
{
    }

    
    @Override
    
public Reference getReference() throws NamingException
    
{
        Reference r 
= new Reference(this.getClass().getName(), BindedClassFactory.class.getName(), null);
        r.add(
new StringRefAddr("value"this.getValue()));
        
return r;
    }


    
public String getValue()
    
{
        
return value;
    }


    
public void setValue(String value)
    
{
        
this.value = value;
    }


}

3.1.2 BindedClassFactory

package  lld.test.jndi;

import  java.util.Hashtable;

import  javax.naming. * ;
import  javax.naming.spi. * ;

public   class  BindedClassFactory  implements  ObjectFactory
{
    @Override
    
public Object getObjectInstance(Object obj, Name name, Context nameCtx,
            Hashtable
<??> environment) throws Exception
    
{
        
if(obj instanceof Reference)
        
{
            Reference ref 
= (Reference)obj;
            String val 
= (String)ref.get("value").getContent();
            BindedClass o 
= new BindedClass();
            o.setValue(val);
            
return o;
            
        }

        
return null;
    }

}

3.1.3 代码解释

Referenable接口只有一个方法,就是getReference(),返回一个Reference对象,BindedClass只设了一个示例成员变量Value,存储一个字符串值,在建立Refernce对象时,要指定它引用的类名以及建立该类的工厂对象,JNDI Context在绑定该对象时就会将这些信息都存到文件中,未来从JNDI中取对象时可就全靠工厂对象根据文件中的内容重建BindedClass对象了。我这里提早把绑定后生成的文件内容说一下,你们会更有一个直观的印象,其内容以下所示:

bind1/RefAddr/0/Type=value
bind1/ClassName=lld.test.jndi.BindedClass
bind1/RefAddr/0/Encoding=String
bind1/FactoryName=lld.test.jndi.BindedClassFactory
bind1/RefAddr/0/Content=abcdefg

你们看到了,前面在BindedClass.getReference()方法中使用了以下语句:

r.add(new StringRefAddr("value", this.getValue()));

就是定义要将这些信息存储到JNDI中呢,至于最后的“bind1/RefAddr/0/Content=abcdefg”,那是由于我在后面的示例Bind.java中将其值设成了“abcdefg”而已,呵呵。而BindedClassFactory.getObjectInstance()方法中

String val = (String)ref.get("value").getContent();

就是用来取到存储的值呢。

3.2 Bind.java

本例用来绑定一个BindedClass对象
package  lld.test.jndi;

import  java.util.Properties;

import  javax.naming.Context;
import  javax.naming.directory.DirContext;
import  javax.naming.directory.InitialDirContext;

public   class  Bind
{
    
public static void main(String[] args) throws Exception
    
{
        Properties ps 
= new Properties();
        ps.setProperty(Context.INITIAL_CONTEXT_FACTORY, 
"com.sun.jndi.fscontext.RefFSContextFactory");
        ps.setProperty(Context.PROVIDER_URL, 
"file:JNDI_REF");
        DirContext ctx 
= new InitialDirContext(ps);
        String key 
= "bind1";

        BindedClass b 
= new BindedClass();
        b.setValue(
"abcdefg");
        ctx.rebind(key, b);

        System.out.println(
"Binded successfully!");
        ctx.close();
    }

}

3.3 Lookup.java

本例用来从JNDI中获取绑定的BindedClass对象

package  lld.test.jndi;

import  java.util.Properties;

import  javax.naming.Context;
import  javax.naming.directory.DirContext;
import  javax.naming.directory.InitialDirContext;

public   class  Lookup
{
    
public static void main(String[] args) throws Exception
    
{
        Properties ps 
= new Properties();
        ps.setProperty(Context.INITIAL_CONTEXT_FACTORY, 
"com.sun.jndi.fscontext.RefFSContextFactory");
        ps.setProperty(Context.PROVIDER_URL, 
"file:JNDI_REF");
        DirContext ctx 
= new InitialDirContext(ps);
        String key 
= "bind1";
        BindedClass o 
= (BindedClass)ctx.lookup(key);
        System.out.println(o.getValue());    
        
        ctx.close();
    }


}



相关文章
相关标签/搜索