一、JNDI在Java EE中的应用
JNDI 技术是Java EE规范中的一个重要“幕后”角色,它为Java EE容器、组件提供者和应用程序之间提供了桥梁作用:Java EE容器同时扮演JNDI提供者角色,组件提供者将某个服务的具体实现部署到容器上,应用程序通过标准的JNDI接口就可以从容器上发现并使用服务,而不用关心服务的具体实现是什么,它的具体位置在哪里。

下面以一个常见的J2EE应用场景来看四种角色(组件接口、容器、组件提供者、应用程序)是如何围绕JNDI来发挥作用的:
组件接口
数据源DataSource是一种很常见的服务。我们通常将组件接口绑定到容器的Context上供客户调用。

Java EE容器

Tomcat是一种常见的Java EE容器,其他的还有JBoss,WebLogic,它们同时也实现了JNDI提供者规范。容器通常提供一个JNDI注入场所供加入组件的具体实现,比如 Tomcat中的Server.xml配置文件。

组件提供者
众多数据库厂商提供了DataSource的实现,比如OracleDataSource,MySQLDataSource,XXXDataSource 等。我们将该实现的部署到容器中:将一系列jar加入classpath中,在Server.xml中配置DataSource实现,如:
<Resource name="jdbc/MyDB" auth="Container" type="javax.sql.DataSource" ..../>

应用程序
一个JSP/Servlet应用程序。通过JNDI接口使用 DataSource服务,如:
Context initContext = new InitialContext();
Context envContext  = (Context)initContext.lookup("java:/comp/env");
DataSource ds = (DataSource)envContext.lookup("jdbc/MyDB");

关于在Tomcat中如何配置DataSource,可以参考文档:http://tomcat.apache.org/tomcat-5.5-doc/jndi-datasource-examples-howto.html。
关于在Tomcat中如何配置其他JNDI服务,可以参考文档:http://tomcat.apache.org/tomcat-5.5-doc/jndi-resources-howto.html。

二、 JNDI实例演练:在Java SE中使用JNDI
要在Java EE中环境中提供一个独立的实例不太容易。下面以一个独立的Java SE应用来演练JNDI的使用过程。在该应用中,我们使用JNDI来使用两种假想的服务:数据库服务DBService和日志服务LogService。

1、指定JNDI提供者
要使用JNDI,首先要配置JNDI提供者。在我们的 Java SE应用中,没有Java EE容器充当JNDI提供者,因此我们要指定其他的JNDI提供者。在我们的例子里,我们使用SUN的文件系统服务提供者File System Service Provider。由于SUN的文件系统服务提供者并没有包含在JDK中,我们需要从SUN网站上下载:http://java.sun.com/products/jndi/downloads/index.html。它包含两个jar文件:fscontext.jar和providerutil.jar。我们将这两个文件加入项目的类路径中。

2、定义服务接口
首先,我们在服务接口package(xyz.service)中定义服务接口:DBService和LogService,分别表示数据库服务和日志服务。

♦ 数据库服务接口 DBService.java

package xyz.service;public interface DBService {String getLocation(); //获取数据库位置String getState(); //获取数据库状态void accessDB(); //访问数据库void setProperty(int index,String property); //设置数据库信息
}

♦日志服务接口 LogService.java

package xyz.service;public interface LogService {void log(String message); //记录日志
}

3、组件提供者实现服务接口

接下来,我们在组件提供者package(xyz.serviceprovider)中提供DBService和LogService的实现:SimpleDBService和SimpleLogService。为了让服务能够在JNDI环境中使用,根据JNDI规范,我们同时定义两个对象工厂类SimpleDBServiceFactory和SimpleLogServiceFactory,分别用来创建服务实例。

♦ 数据库服务接口实现  SimpleDBService.java

package xyz.serviceprovider;import javax.naming.NamingException;
import javax.naming.Reference;
import javax.naming.Referenceable;
import javax.naming.StringRefAddr;import xyz.service.DBService;// 为了将数据库服务实例加入JNDI的Context中,我们需要实现Referenceable接口,并实现RetReference方法。
// 关于Reference和Referenceable,请参考上一篇:Java技术回顾之JNDI:JNDI API
public class SimpleDBService implements Referenceable, DBService {private String location = "mydb//local:8421/defaultdb";// 数据库服务属性之一:数据库位置private String state = "start"; // 数据库服务属性之二:数据库状态public Reference getReference() throws NamingException {// Reference是对象的引用,Context中存放的是Reference,为了从Reference中还原出对象实例,// 我们需要添加RefAddr,它们是创建对象实例的线索。在我们的// SimpleDBService中,location和state是这样两个线索。Reference ref = new Reference(getClass().getName(),SimpleDBServiceFactory.class.getName(), null);ref.add(new StringRefAddr("location", location));ref.add(new StringRefAddr("state", state));return ref;}public void accessDB() {if (state.equals("start"))System.out.println("we are accessing DB.");elseSystem.out.println("DB is not start.");}public String getLocation() {return location;}public String getState() {return state;}public void setProperty(int index, String property) {if (index == 0)location = property;elsestate = property;}
}

♦数据库服务对象工厂类 SimpleDBServiceFactory.java

package xyz.serviceprovider;import java.util.Hashtable;import javax.naming.Context;
import javax.naming.Name;
import javax.naming.Reference;
import javax.naming.spi.ObjectFactory;// 数据库服务对象工厂类被JNDI提供者调用来创建数据库服务实例,对使用JNDI的客户不可见。
public class SimpleDBServiceFactory implements ObjectFactory {// 根据Reference中存储的信息创建出SimpleDBService实例public Object getObjectInstance(Object obj, Name name, Context ctx, Hashtable<?, ?> env) throws Exception {if (obj instanceof Reference) {Reference ref = (Reference) obj;String location = (String) ref.get("location").getContent();String state = (String) ref.get("state").getContent();SimpleDBService db = new SimpleDBService();db.setProperty(0, location);db.setProperty(1, state);return db;}return null;}
}

♦ 日志服务接口实现 SimpleLogService.java

package xyz.serviceprovider;import java.text.SimpleDateFormat;
import java.util.Date;import javax.naming.NamingException;
import javax.naming.Reference;
import javax.naming.Referenceable;import xyz.service.LogService;public class SimpleLogService implements Referenceable, LogService {private SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");// SimpleLogService没有任何属性,通过 SimpleLogService类名创建出来的SimpleLogService实例都是一样的,// 因此这里无需添加RefAddr了。public Reference getReference() throws NamingException {return new Reference(getClass().getName(),SimpleLogServiceFactory.class.getName(), null);}public void log(String message) {String date = sdf.format(new Date());System.out.println(date + ":" + message);}
}

♦日志服务对象工厂类 SimpleLogServiceFactory.java

package xyz.serviceprovider;import java.util.Hashtable;import javax.naming.Context;
import javax.naming.Name;
import javax.naming.Reference;
import javax.naming.spi.ObjectFactory;public class SimpleLogServiceFactory implements ObjectFactory {public Object getObjectInstance(Object obj, Name name, Context ctx,Hashtable<?, ?> env) throws Exception {if (obj instanceof Reference) {return new SimpleLogService();}return null;}
}

 4、 JNDI容器和JNDI客户端
最后,我们在JNDI应用package(xyz.jndi)中实现一个JNDI容器 JNDIContainer和一个JNDI客户端应用JNDIClient。
JNDIContainer在内部使用文件系统服务提供者 fscontext来提供命名和目录服务,配置文件JNDIContainer.properties是服务注入场所,供配置DBService和 LogService实现。

♦JNDI容器类 JNDIContainer.java

package xyz.jndi;import java.io.InputStream;
import java.util.Hashtable;
import java.util.Properties;import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;import xyz.service.DBService;
import xyz.service.LogService;public class JNDIContainer {private Context ctx = null;public void init() throws Exception {// 初始化JNDI提供者。Hashtable<Object,Object> env = new Hashtable<Object,Object>();env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.fscontext.RefFSContextFactory");env.put(Context.PROVIDER_URL, "file:/d:/works"); // fscontext的初始目录,我们需要在d:\下创建works目录。ctx = new InitialContext(env);loadServices();}// 从配置文件 JNDIContainer.properties中读取DBService和LogService实现,绑定到Context中。private void loadServices() throws Exception {InputStream in = getClass().getResourceAsStream("JNDIContainer.properties");Properties props = new Properties();props.load(in);// inject dbserviceString s = props.getProperty("DBServiceClass");Object obj = Class.forName(s).newInstance();if (obj instanceof DBService) {DBService db = (DBService) obj;String[] ss = props.getProperty("DBServiceProperty").split(";");for (int i = 0; i < ss.length; i++)db.setProperty(i, ss[i]);ctx.rebind(props.getProperty("DBServiceName"), db);}// inject logservices = props.getProperty("LogServiceClass");obj = Class.forName(s).newInstance();if (obj instanceof LogService) {LogService log = (LogService) obj;ctx.rebind(props.getProperty("LogServiceName"), log);}}public void close() throws NamingException {ctx.close();}public Context getContext() {return ctx;}
}

♦JNDI 容器配置文件 JNDIContainer.properties

//和 JNDIContainer.java文件位于同一目录
DBServiceName=DBService
DBServiceClass=xyz.serviceprovider.SimpleDBService
DBServiceProperty=mydb//192.168.1.2:8421/testdb;startLogServiceName=LogService
LogServiceClass=xyz.serviceprovider.SimpleLogService

♦JNDI 客户端 JNDIClient.java

package xyz.jndi;import javax.naming.Context;import xyz.service.DBService;
import xyz.service.LogService;public class JNDIClient {public static void main(String[] args) {try {JNDIContainer container = new JNDIContainer();container.init();// JNDI客户端使用标准JNDI接口访问命名服务。Context ctx = container.getContext();DBService db = (DBService) ctx.lookup("DBService");System.out.println("db location is:" + db.getLocation()+ ",state is:" + db.getState());db.accessDB();LogService ls = (LogService) ctx.lookup("LogService");ls.log("this is a log message.");container.close();} catch (Exception e) {e.printStackTrace();}}
}

Java技术回顾之JNDI--实例相关推荐

  1. Java技术回顾之JNDI--JNDI API

    JNDI的用途: 1)你可以用jndi来得到object类的属性 Attribute attr =directory.getAttributes(personName).get("email ...

  2. Java技术回顾之JNDI--命名和目录服务基本概念

    命名服务的相关概念: Naming Service 命名服务 命名服务将名称和对象进行关联,提供通过名称找到对象的操作. 例如:DNS系统将计算机名和IP地址进行关联.文件系统将文件名和文件句柄进行关 ...

  3. mysql jndi 实例_自己收藏-JNDI应用实例

    一.JNDI在Java EE中的应用 JNDI技术是Java EE规范中的一个重要"幕后"角色,它为Java EE容器.组件提供者和应用程序之间提供了桥梁作用:Java EE容器同 ...

  4. java技术详解_Java反射技术详解及实例解析

    前言 相信很多人都知道反射可以说是Java中最强大的技术了,它可以做的事情太多太多,很多优秀的开源框架都是通过反射完成的,比如最初的很多注解框架,后来因为java反射影响性能,所以被运行时注解APT替 ...

  5. 深入掌握Java技术 EJB调用原理分析

      深入掌握Java技术 EJB调用原理分析     一个远程对象至少要包括4个class文件:远程对象:远程对象的接口:实现远程接口的对象的stub:对象的skeleton这4个class文件. 在 ...

  6. Tomcat系列之Java技术详解

    一.概述 1.前言 在前面几篇博客中,我们和大家说了负载均衡器服务器.Web服务器.反向代理服务器.缓存服务器,从这篇博客开始我们和大家说说应用程序服务器,对于上述内容不了解的博友可以去参考一下我们前 ...

  7. 《Java 技术体系》之一:Java 技术体系概览

    Java 编程语言诞生以来,围绕它建设而成的生态系统日益庞大而复杂: 它的热度经二十多年仍然不减,如今在互联网行业尤其流行. 本系列以 Java 8 (JDK 8) 为主要研究对象. TIOBE 编程 ...

  8. Tomcat(一) Tomcat是什么:Tomcat与Java技术 Tomcat与Web应用 以及 Tomcat基本框架及相关配置

    Tomcat(一) Tomcat是什么: Tomcat与Java技术 Tomcat与Web应用 以及 Tomcat基本框架及相关配置 Tomcat是一个被广泛使用的Java WEB应用服务器,我们有必 ...

  9. Java这十年 - Java技术本纪 (3)

    Java技术本纪 Java虚拟机的  10    年 文/曹晓刚 Java虚拟机的起源与构造 当我们说到"Java"这个词的时候,指的是四个相互关联的概念:Java语言.Java ...

最新文章

  1. 脉脉上发匿名消息,拼多多员工被开除了!
  2. Linux C编程--操作文件结束和错误的判断方法(函数)
  3. 数据结构之权值(在吊挂中的实际应用)
  4. python建立数据库并序列化_python之数据的序列化
  5. javascript的对象创建模式---命名空间模式
  6. linux mv 保持目录结构_(三)Linux系统目录结构
  7. 找到MVC框架中前端URL与后端同步的解决方案
  8. Elasticsearch拼音和ik分词器的结合应用
  9. mybatis plugins_[Mybatis]-[基础支持层]-插件-多个插件执行顺序
  10. c#中 utm坐标转换经纬度坐标
  11. java 操作rtsp/rtmp视频流生成
  12. 如何下载衡水市卫星地图高清版大图
  13. EXCEL的各种“空”的区别:blank,““ , 0 ,以及 VBA里的各种空值:empty,null,nothing 等
  14. codeforces 884B Japanese Crosswords Strike Back
  15. 以太坊性能优化:分片技术、雷电网络、Casper-下一代以太坊共识协议
  16. Android Studio使用签名打包发布APP(安卓生成apk文件)
  17. windows 沙盒,隔离应用
  18. 【区块链论文整理】VLDB篇
  19. php sku 代码编写,php – 在单个产品页面中显示SKU下的自定义字段值
  20. ADR4540ARZ小秘密

热门文章

  1. 论文浅尝 | 用图网络做小样本学习
  2. python中模块、函数与各个模块之间的调用
  3. 玩转算法之面试第十章-贪心算法
  4. 2018届校招面经精选
  5. 中文电子病例命名实体识别项目
  6. 二叉树介绍与代码实现
  7. 【HAOI2010】工厂选址题解
  8. Linux 笔记 - 第九章 Linux 中软件的安装
  9. SSL-ZYC 溜冰
  10. FastLeaderElection