JNDI 笔记(一) 概述

NDI,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下使用JNDI

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

下面,我将演示一下如何在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代码如下,代码都简单地很,就不多做解释了。

2.1.1 index.jsp

> bind an object </ a > 
 > 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时,如果已经有对象绑定到该键值上,则会抛出异常。

因为只是示例代码,所以我只是绑定了一个最简单的日期对象。

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,

JNDI 笔记(转)相关推荐

  1. JNDI 笔记(一) 概述

    很多地方都会用到JNDI,一大堆的缩写加上一大堆不清不楚的概念描述,使得在看到的时候都不认识,更不要说使用了. JNDI,Java Naming Directory Interface,J2EE的标准 ...

  2. MyBatis-学习笔记10【10.JNDI扩展知识】

    Java后端 学习路线 笔记汇总表[黑马程序员] MyBatis-学习笔记01[01.Mybatis课程介绍及环境搭建][day01] MyBatis-学习笔记02[02.Mybatis入门案例] M ...

  3. Java安全学习笔记--一次对JNDI注入失败的问题排查(手写POC以及rmi)

    目录 前言 恶意类代码: RMI注册中心以及服务端代码: 问题一: 问题二 调试 问题三 总结 前言 之前分析了fastjson的jdbcRowSetImpl利用链之后当时也是手写了所用的代码并测试, ...

  4. Solr笔记三:Solr数据源配置(JNDI、DIH)及定时重做索引

    Solr支持很多种创建索引的方式,包括网页,xml以及数据库,因为我这边做的是企业级的搜索,所以用的是数据库建立索引.其实从数据库建立索引,很大程度上取决于原来的数据库设计. 从数据库建立索引,sol ...

  5. Tomcat 6 部署工程总结,使用JNDI数据源配置

    工程需要用JNDI数据源方式部署到tomcat,参考网上文章后,经过配置测试,摸索出来了.     环境说明: 数据库:Oracle9i Web服务器:tomcat-6.0.33 tomcat启动方式 ...

  6. mybatis 使用jdbc_MyBatis笔记一

    MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis .20 ...

  7. RMI、JNDI、LDAP介绍+log4j漏洞分析

    介绍 本篇主要介绍java的RMI.JNDI.LDAP,在后面会详细分析log4j的jndi注入原理. 什么是RMI RMI全称是Remote Method Invocatioon,也就是远程方法调用 ...

  8. JProfiler学习笔记

    JProfiler学习笔记   一.安装JProfiler        从http://www.ej-technologies.com/下载5.1.2并申请试用序列号   二.主要功能简介 1.内存 ...

  9. J2EE总结--浅识JNDI

    最近一直在对J2EE的笔记进行整理和复习,虽然J2EE视频是看过一遍了,但是当我看自己做的笔记的时候陌生程度还是很大,而真正的对某个概念有所认识的时候是将笔记和以前看过的视频印象进行摩擦,J2EE主要 ...

最新文章

  1. 学python看谁的视频比较好-Python入门视频看哪个好?适合初学者的教学视频推荐...
  2. 每一个div元素分析 php,PHP初入,div知识点整理(特效字体等元素的使用整理)...
  3. Nodejs简介以及Windows上安装Nodejs
  4. Hazelcast入门指南第7部分
  5. 基于beego一键创建RESTFul应用
  6. Python学习笔记之列表切片(六)
  7. 信号方面概念解释(笔记04)
  8. startService和onBinderService混合开发音乐播放器
  9. 手机上有没有学python的软件-三款可以在安卓手机上运行Python代码的软件
  10. 阶段2 JavaWeb+黑马旅游网_15-Maven基础_第2节 maven的安装和仓库种类_05仓库的种类和彼此关系...
  11. 教你让XP等32位操作系统支持4G以上大内存,并且不出错
  12. 概率论————思维导图(上岸必备)(一维随机变量及其分布)
  13. 加拿大 计算机学校排名2015,2015年加拿大大学综合排名
  14. 服务器装系统怎样进bios设置,重装系统怎么进入bios设置界面?进入bios设置界面详细教程!...
  15. 【论文笔记】Image Tampering Localization Using a Dense Fully Convolutional Network
  16. 动态RAM和静态RAM的区别(浅学)
  17. 人物拼图java_JAVA实现拼图游戏
  18. 这里有一份CAD 快捷键指南,请查收~
  19. 关于研发规范化的一些实践和思考
  20. 到底什么是语义分割?

热门文章

  1. php key sort,PHP中的sort(), rsort(),asort(),arsort(),ksort(),krsort()函数
  2. php查询mysql数据库乱码_PHP怎样处理查询MySQL数据库中文乱码?_后端开发
  3. mysql 并行复制原理_MySQL 5.7 并行复制实现原理与调优
  4. java 泛型 泛型接口(Generic Interfaces)类型形参(Type Parameters)
  5. java 正则表达式 分组(group)
  6. Python datetime time
  7. C语言目录和文件操作扩展
  8. Android用外部应用打开文件,Android N 以上使用其他应用打开文件 FileProvider
  9. CVE-2020-16875: Microsoft Exchange远程代码执行漏洞通告
  10. PostgreSQL学习总结(6)—— PostgreSQL 模式(SCHEMA)详解