一、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实现,如:

应用程序

一个JSP/Servlet应用程序。通过JNDI接口使用DataSource服务,如:

Context initContext = new InitialContext();

Context envContext = (Context)initContext.lookup("java:/comp/env");

DataSource ds = (DataSource)envContext.lookup("jdbc/MyDB");

二、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.");

else

System.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;

else

state=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 env = new Hashtable();

env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.fscontext.RefFSContextFactory");

env.put(Context.PROVIDER_URL, "file:/c:/sample"); //fscontext的初始目录,我们需要在c:\下创建sample目录。

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 dbservice

String 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

db.setProperty(i, ss[i]);

ctx.rebind(props.getProperty("DBServiceName"), db);

}

//inject logservice

s=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;start

LogServiceName=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();

}

}

}

分享到:

2010-11-24 23:10

浏览 758

评论

mysql jndi 实例_自己收藏-JNDI应用实例相关推荐

  1. rds 主从实例_探索Amazon RDS数据库实例和漏洞

    Amazon Web Services(AWS)是构成Amazon云计算平台的远程计算服务的集合. 其中两项服务是: Amazon Simple Storage Service(S3),这是一种在线文 ...

  2. aws 删除ec2实例_如何在AWS EC2实例上部署Spring Boot应用程序

    aws 删除ec2实例 你好朋友, 在本教程中,我们将看到如何在AWS EC2实例上部署Spring Boot应用程序. 这是我们将要执行的步骤. 1.使用Spring Boot Initialise ...

  3. mysql++编程规范_建议收藏 - 专业的MySQL开发规范

    为了项目的稳定,代码的高效,管理的便捷,在开发团队内部会制定各种各样的规范 这里分享一份我们定义的MySQL开发规范,欢迎交流拍砖 数据库对象命名规范 数据库对象 命名规范的对象是指数据库SCHEMA ...

  4. mysql布隆过滤器_布隆过滤器及其使用实例

    1.什么是布隆过滤器 本质上布隆过滤器是一种数据结构,比较巧妙的概率型数据结构(probabilistic data structure),特点是高效地插入和查询,可以用来告诉你 "某样东西 ...

  5. codesys 串口通讯实例_常见的PLC程序实例,车库自动门的PLC控制!

    点击箭头处"工业之家",选择"关注公众号"! PLC控制车库自动门实例 车库自动门控制 (1)明确系统控制要求 系统要求车库门在车辆进出时能自动打开关闭,车库门 ...

  6. gan pytorch 实例_重新思考一阶段实例分割(Rethinking Single Shot Instance Segmentation)

    点击上方"CVer",选择加"星标"或"置顶" 重磅干货,第一时间送达 作者:谢恩泽 https://zhuanlan.zhihu.com/ ...

  7. java对象实例_深入理解Java对象实例生成的例子!(转)

    深入理解Java对象实例生成的例子!(转)[@more@]代码如下: class A { public int Avar; public A() { System.out.println(" ...

  8. guice 实例_使用Google Guice消除实例之间的歧义

    guice 实例 如果接口有多个实现,则Google guice提供了一种精巧的方法来选择目标实现. 我的示例基于Josh Long ( @starbuxman )的出色文章,内容涉及Spring提供 ...

  9. 亚马逊ec2 删除实例_学习使用Amazon EC2实例部署php应用程序

    亚马逊ec2 删除实例 Learn about the Deployment of Web application using AWS 了解有关使用AWS部署Web应用程序的信息 Amazon EC2 ...

最新文章

  1. linux基础命令介绍十四:定时任务
  2. cython安装、使用
  3. Linux下把目录拷贝到全部同名目录的脚本
  4. Windwos 08R2_DNS+AD安装图文
  5. C语言 比较字符串的大小关系
  6. MacBook如何设置自动纠正拼写和自动大写字词的首字母
  7. Python中的解决中文字符编码的问题
  8. (95)分频器设计(偶数分频)
  9. 苹果:iPhone 12定价很合适,首批预订秒光说明用户认可
  10. DELL服务器如何使用iDRAC安装操作系统
  11. mysql的唯一索引UNIQUE
  12. iOS uuchart 用法
  13. Vmware ESXi应用之如何使用母盘模板部署虚拟机
  14. 免费资源下载:超酷超全的PSD按钮资源
  15. C语言入门教程(一)
  16. 大话IT第十期:由Windows 8引发的Wintel内讧
  17. AlphaGo人肉臂黄士杰:我的使命完成 阿尔法狗项目结束 | 重磅
  18. 在2.5亿个整数中找出不重复的整数,注,内存不足以容纳这2.5亿个整数
  19. python调用python脚本
  20. AOP注解和切入点表达式

热门文章

  1. 嵌入式组态软件HMImaker(绿色版人机界面组态软件)
  2. Unicode,ANSI,UTF-8的故事
  3. MapReduce的模式、算法和用例
  4. VC++中对话框数据交换【十全十美】
  5. JavaScript的类的实现
  6. .NET3.5 GDI+ 图形操作2
  7. 《写给大家看的设计书》封面设计基本要求
  8. Python案例篇:爬取分析大型招聘网站Python岗
  9. java取得泛型,Java取得泛型类型
  10. java web 课程设计_关于Javaweb课程设计的心得体会.doc