JNDI作为J2EE的13的规范之一,在J2EE中起着举足轻重的作用。这几天通过对JDNI的学习对JDNI有了初步的了解,然而对JDNI在J2EE中扮演的角色与价值还是特别的抽象。尽管有着很多的迷惑与不解,但仍旧需要对JDNI做个总结。
JDNI(java 命名和目录接口),被称为是一个访问目录和命名服务器的API.百度一下JDNI,大概的意思是:JNDI主要提供应用程序所需要资源上命名与目录服务。在Java EE环境中,JNDI扮演了一个很重要的角色,它提供了一个接口让用户在不知道资源所在位置的情形下,取得该资源服务。就好比网络磁盘驱动器的功能一样。如果有人事先将另一台机器上的磁盘驱动器接到用户的机器上,用户在使用的时候根本就分辨不出现在的驱动器是存在本端,还是在另一端的机器上,用户只需取得资源来用,根本就不知道资源在什么地方。通过解释大概可以了解到JDNI是一种规范,只要满足JDNI规范的资源,我们就可以使用该资源提供的服务而不用去管该资源是何种资源、资源存放的位置。这就好像是通过接口将两个模块之间解耦的意思。
任何计算机系统中最基本的设施就是命名服务,含义是名称、和名称相关的对象,以及如何使用名称找到这些对象。当您使用几乎所有的程序和系统时,总是需要将为这个或那个对象命名。例如,当您使用电子邮件系统,必须提供接收方的名称。如果要访问电脑中的文件,您必须提供名称。命名服务允许您使用名称查询相应对象。
命名服务的主要功能是将对象名称映射成人类可以识别的名称,例如地址,标识符或计算机程序使用的对象。
例如,网络命名服务将计算机名称映射成IP地址:
www.sun.com ==> 192.9.48.5.
文件系统将文件名映射成文件引用,程序可以使用引用访问文件内容。
目录对象表示电脑环境中的对象。例如,使用目录对象表示打印机、人、电脑或网络。目录对象包含对象表示的属性。
目录是一系列目录对象的集合。目录服务是提供创建、添加、删除和修改目录中对象关联属性操作的服务。服务使用自己的接口进行访问。
目录访问的例子:网络信息服务(NIS)、NIS是一个Unix文件系统中的目录服务,用来保存系统相关的信息,例如关联的机器、网络、打印机和用户、Sun Java目录服务、Sun Java目录服务是基于LDAP的普遍意义上的目录服务、Novell目录服务(NDS)、NDS是Novell的目录路服务,提供一些网络服务的信息,例如文件和打印机服务。
J2EE 规范把职责委托给多个开发角色:组件提供者(Component Provider)、应用程序组装者(Application Assembler)、部署人员(Deployer)和系统管理员(System Administrator)。(在许多公司中,组件提供者和组件组装者的角色是融合在一起的,部署人员和系统管理员的角色是融合在一起的。)在真正了解 J2EE 中的 JNDI 角色之前,掌握 J2EE 角色的作用非常重要。
这个角色负责创建 J2EE 组件,J2EE 组件可以是 Web 应用程序、企业级 JavaBean(EJB)组件,或者是应用程序客户机(例如基于 Swing 的 GUI 客户机应用程序)。组件提供者包括:HTML 设计师、文档编程人员以及其他开发人员角色。大多数 J2EE 开发人员在组件提供者这一角色上耗费了相当多的时间。
这个角色将多个 J2EE 模块捆绑成一个彼此结合的、可以部署的整体:企业归档(EAR)文件。应用程序组装者要选择组件,分清它们之间的交互方式,配置它们的安全性和事务属性,并把应用程序打包到 EAR 文件中。许多 IDE,例如 WebSphere® Studio、IDEA、JBuilder、WebLogic Workshop 和其他 IDE,都可以帮助应用程序组装者以交互方式配置 EAR 文件。
这个角色负责部署,这意味着将 EAR 安装到 J2EE 容器(应用服务器)中,然后配置资源(例如数据库连接池),把应用程序需要的资源绑定到应用服务器中的特定资源上,并启动应用程序。
系统管理员(System Administrator)
这个角色负责保证容器需要的资源可用于容器。
假设有一个企业应用程序,该应用程序包含一个 Web 应用程序,还有一个负责业务逻辑和持久性的 EJB 组件。开发这个应用程序的组件供应商可能有许多,但是在许多情况下,可以由一个人来承担全部职责。组件可以包含数据传输对象(一个 JAR 文件)、EJB 接口(另一个 JAR 文件)、EJB 实现本身(另一个 JAR 文件),以及用户界面组件 —— servlet、JSP、HTML 页面和其他静态 Web 内容。用户界面组件被进一步打包成 Web 应用程序,其中包含 servlet 类、JSP 文件、静态内容,以及其他必需组件的 JAR(包括 EJB 接口)。
这听起来好像用到的组件太多了,几乎超出了人的想像范围,尤其是在考虑构建一个典型的 Web 应用程序需要使用多少个 JAR 文件的时候。但是,重要的是认识到在这里必须小心地管理依赖性。接口和传输对象是 Web 应用程序和 EJB 实现可以依赖的对象,但是依赖性的方向应该是相同的;还要避免产生循环依赖。J2EE 组件(例如 WAR 文件和 EJB JAR 文件)必须在它们的部署单元之外声明它们在资源上的依赖性。
Connection conn=null; try { Class.forName("com.mysql.jdbc.Driver", true, Thread.currentThread().getContextClassLoader()); conn=DriverManager.getConnection("jdbc:mysql://dbserver?user=dolly&password=dagger"); /* use the connection here */ c.close(); } catch(Exception e) { e.printStackTrace(); } finally { if(conn!=null) { try { conn.close(); } catch(SQLException e) {} } }
最经典的JDBC使用方式无非就是:
1. 加载数据库驱动程序
2. 创建数据库连接
3. 执行SQL语句
4. 得到结果集
5. 对结果集做相应的处理(增,删,改,查)
6. 关闭资源:这里释放的是DB中的资源
Connection conn=null; try { Context ctx=new InitialContext(); Object datasourceRef=ctx.lookup("java:comp/env/jdbc/mydatasource"); DataSource ds=(Datasource)datasourceRef; Connection c=ds.getConnection(); /* use the connection */ c.close(); } catch(Exception e) { e.printStackTrace(); } finally { if(conn!=null) { try { conn.close(); } catch(SQLException e) { } } }
使用JNDI得到数据源与JDBC的经典使用方法不同的是JDBC经典使用方法更倾向于使用反射机制的硬编码实现,而JNDI方式像是有一种东西在对数据源进行管理,当我们用的时候按照人家提供的方法去使用即可,这种方式更倾向于软编码。
从本质上来说,JNDI与JDBC相比较加载驱动的步骤好像没有了,其实是将加载驱动的步骤向下移动了,这样使得两个模块之间的耦合度大大降低。而底层模块向上层模块只提供数据源连接的引用使得上层模块在功能上更相对独立、更稳定。JNDI获得数据源的方式就像读取一串字符就可以获得数据源对象,其实从字符串到数据源对象的映射以及它的查找方式就是通过JNDI来实现的,即Java Naming and Directory Interface。
当然,J2EE 中的资源并不局限于 JDBC 数据源。引用的类型有很多,其中包括资源引用(已经讨论过)、环境实体和 EJB 引用。特别是 EJB 引用,它暴露了 JNDI 在 J2EE 中的另外一项关键角色:查找其他应用程序组件。
在 J2EE 中,JNDI 是把 J2EE 应用程序合在一起的粘合剂,但还没有紧到无法让人很容易地把它们分开并重新装配。JNDI 提供的间接寻址允许跨企业交付可伸缩的、功能强大且很灵活的应用程序。这是 J2EE 的承诺,而且经过一些计划和预先考虑,这个承诺是完全可以实现的。实际上,它要比许多人想像的容易得多。J2EE 规范要求所有 J2EE 容器都要提供 JNDI 规范的实现。JNDI 在 J2EE 中的角色就是“交换机” —— J2EE 组件在运行时间接地查找其他组件、资源或服务的通用机制。在多数情况下,提供 JNDI 供应者的容器可以充当有限的数据存储,这样管理员就可以设置应用程序的执行属性,并让其他应用程序引用这些属性(Java 管理扩展(Java Management Extensions,JMX)也可以用作这个目的)。JNDI 在 J2EE 应用程序中的主要角色就是提供间接层,这样组件就可以发现所需要的资源,而不用了解这些间接性。
假设应用程序是由若干个小组件构成,而明确的角色划分有益我们前期对程序的开发,更有益我们后期对应用程序的组装、部署和管理。假设前期我们已经按照一定的准则将符合某以应用程序的各个组件开发完毕,而后期的各个组件之间的组合可以分为Web 应用程序中的外部 EJB 引用(立即绑定),即将需要的一些外部资源或组件直接引用到程序中和外部资源的后绑定,即将一些外部资源或组件通过某一方式间接在程序需要的时候再加进去。而立即绑定和后期绑定的区别就在于立即绑定是我们提前提供给程序所需要的一切资源或外部组件,后期绑定是我们给应用程序提供一个寻找资源的特殊功能,当程序需要时让程序按照一定的条件去寻找自己所需要的资源。JDNI规范相当于为后期绑定的寻找资源的特殊功能提供了一个接口。JDNI对后期绑定的支持,更有利于我们在后期对某些资源和组件的替换,实现分布式部署和统一管理。