利用ServiceLocator模式改进JNDI实践

J2EE应用系统是打了“分布式”的标签的,所以客户端需要定位业务层的组件和服务,常见的比如有:EJB Home接口、EJB LocalHome接口、JMS消息列队或主题、JMS消息列队工厂等等,当然还有再普通不过的JAVA对象了,那么对这些分布在不同位置的组件和服务,客户端是如何进行寻址的呢?这就是JNDI的任务了...

JNDI(The Java Naming and Directory Interface,Java命名和目录接口)是一组在Java应用中访问命名和目录服务的API。如同其它很多Java技术一样(例如 JDBC),JDNI是provider-based的技术,暴露了一个API和一个服务供应接口(SPI)。这意味着任何基于名字的技术都能通过 JNDI而提供服务,只要JNDI支持这项技术。JNDI目前所支持的技术包括LDAP、CORBA Common Object Service(COS)名字服务、RMI、NDS、DNS、Windows注册表等等。JDNI通过绑定的概念将对象和名称联系起来。就像在一个文件系统中,文件名被绑定给文件;在DNS中,一个IP地址绑定一个URL;在目录服务中,一个对象名被绑定给一个对象实体。

在J2EE应用中,业务层组件(比如EJB组件)和集成层组件(比如JDBC数据源和JMS组件)通常都要在一个中央注册表中注册。客户端使用JNDI API来与这个注册表交互,获得一个初始化上下文(InitialContext)对象,该对象中装载着组件的名称/对象绑定信息。客户端通过它就可以 lookup我们需要的组件和服务了,但是这样可能会相当的复杂,因为这可能要包括重复使用初始化上下文(InitialContext)对象、寻址操作、强制类型转换操作以及对底层异常和超时的处理操作。

想一想,我们是不是在这样不停地重复我们自己呢?当我们粘贴复制到手都发麻的时候,有没有考虑如果现在要对其进行一点改动,我们又该怎么作?我猜想你一定会责怪自己为什么才发现呢, 还要在从头粘贴复制,噢,天呢!

应用系统客户端需要从这种复杂性中隔离出来。不然,在多种不同的客户端中就会有重复的JNDI代码,因为所有访问一个由JNDI管理的服务/组件的客户端都要执行同样的寻址。创建一个JNDI InitialContext对象,执行服务组件的寻址可能是一种代价很高的操作,如果反复执行这样的操作,可能会引起系统性能的恶化。另外一个问题是,JDNI是provider-based的技术,InitialContext和JNDI注册表中注册的其他context工厂都是厂商提供实现的。如果应用系统客户端直接访问以上的对象的这些特殊实现,那么会给应用引入厂商依赖性,使代码难以移植。

所以我们需要一种统一的、透明的方式定位业务组件和业务服务。J2EE核心模式里面的ServiceLocator模式就是这个问题的最优解,使用服务定位器实现、封装对服务/组件的寻址。应用系统客户端可以通过服务定位器实现重用,降低代码的复杂性,提供唯一的控制点,并且提供缓存机制(Cache),能够改善系统的性能。

下面通过一个定位EJB服务的例子来看一下怎么来实现ServiceLocator,对于其他服务和组件的定位就是大同小异的了。

import java.util.*;    
import javax.naming.*;    
import java.rmi.RemoteException;    
import javax.ejb.*;    
import javax.rmi.PortableRemoteObject;    
import java.io.*;    public class ServiceLocator {    private static ServiceLocator _instance;    private InitialContext context = null;    private Map cache;    static {    try{    _instance=new ServiceLocator();    } catch(ServiceLocatorException se) {    System.err.println(se);    se.printStackTrace(System.err);        }    }    private ServiceLocator() throws ServiceLocatorException {    try {    context = new InitialContext();    cache=Collection.synchronizedMap(new HashMap());    } catch(NamingException ne) {    throw new ServiceLocatorException(ne);    } catch(Exception e) {    throw new ServiceLocatorException(ne);    }    }    public static ServiceLocator getInstance()     throws ServiceLocatorException {    return _instance;    }    public EJBLocalHome getLocalHome(String jndiHomeName)    throws ServiceLocatorException {    EJBLocalHome localHome = null;    try {    if(cache.containsKey(jndiHomeName)) {    localHome = (EJBLocalHome)cache.get(jndiHomeName);    } else {    localHome = (EJBLocalHome)context,lookup(jndiName);    cache.put(jndiName, localHome);     }    } catch(NamingException nex) {    throw new ServiceLocatorException(ne);    } catch(Exception ex) {    throw new ServiceLocatorException(ne);    }    return localHome;              }     public EJBHome getRemoteHome(String jndiHomeName, Class homeClassName)    throws ServiceLocatorException {    EJBHome remoteHome = null;    try {    if(cache.containsKey(jndiHomeName)) {    remoteHome = (EJBHome)cache.get(jndiHomeName);    } else {    Object objref = context,lookup(jndiName);    Object obj = PortableRemoteObject. narrow(objref, homeClassName);    remoteHome = (EJBHome)obj;    cache.put(jndiName, remoteHome);     }    } catch(NamingException nex) {    throw new ServiceLocatorException(ne);    } catch(Exception ex) {    throw new ServiceLocatorException(ne);    }    return remoteHome;              }     
}    
我们看到了ServiceLocator的核心采用了单子模式,利用ServiceLocator模式对JDNI的使用的进行改进,可以抽象系统的复杂性,向客户端隐藏了JDNI寻址的复杂性;可以为客户端提供统一的服务访问方式,这种统一减少了开发和维护的工作量,我们终于可以免除粘贴复制了;提高了系统的网络性能和客户端性能。
好了,现在就开始重构我们的JNDI代码吧!


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/497873.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

数据革命在危机中诞生 援助组织尝试灵活方法拨开战争迷雾

无国界医生组织在安曼为叙利亚提供支持。图片来源:Neil Brandvold来源:科学网概要:每当战争、飓风或其他灾害肆虐时,援助组织面临的最大问题之一就是缺乏可靠的数据。当Issam Salim(化名)讲述他进行的手术时…

德勤2018TMT八大预测:移动互联网迎来二次革命

来源:智东西概要:数万手机AR应用上市,AI芯片打入旗舰手机,数据中心ML芯片多样化,移动数字经济继续开挂。2017年,很多传统TMT巨头面临增长缓趋,于是考虑重资产化追求规模效应,开拓、转…

oracle 中 start tran,The value (30) of MAXTRANS parameter ignored

The value (30) of MAXTRANS parameter ignored在客户的数据库系统中(Oracle 10.2.0.3),当使用expdp备份时就出现如下错误,非常准时。可以看到,这个错误就是由于备份时创建备份主表(Master Table)产生的:Sat Mar 7 02:40:01 2009T…

JNDI概述

JNDI是 Java 命名与目录接口(Java Naming and Directory Interface),在J2EE规范中是重要的规范之一,不少专家认为,没有透彻理解JNDI的意义和作用,就没有真正掌握J2EE特别是EJB的知识。那么,JNDI…

北京出台自动驾驶新规:自动驾驶车辆须配备司机应急

来源:人民日报概要:在中国境内注册的独立法人单位,因进行自动驾驶相关科研、定型试验,可申请临时上路行驶。记者今天从北京市交通委获悉,北京市交通委联合市公安交管局、市经济信息委等部门,制定发布了加快…

oracle简单序列,-30天下载

如何使用Oracle序列:Oracle序列(sequence)是一种数据库项,能够生成一个整数序列。通常用于填充数字类型的主键列。1、创建序列:CREATE SEQUENCE sequence_name[START WITH start_num][INCREMENT BY increment_num][{MAXVALUE maximum_num|NOM…

JNDI配置原理详解

最近写书,写到JNDI,到处查资料,发现所有的中文资料都对JNDI解释一通,配置代码也是copy的,调了半天也没调通,最后到SUN的网站参考了一下他的JNDI tutorial,终于基本上彻底明白了和多数java服务一…

【未来研究】城市云脑是互联网云脑的节点,城市云脑之间如何互补与支撑

作者: 互联网进化论作者 ,计算机博士 刘锋前言:本文是未来智能实验室的研究文章,重点探讨了基于类脑架构的智慧城市建设不应局限在城市内部,而是在互联网大背景下,不同城市之间也会发生智慧建设的协同效应。本文从城市…

oracle 数据掩码,oracle格式掩码

to char 是把日期或数字转换为字符串to date 是把字符串转换为数据库中得日期类型? 转换函数? TO_CHAR使用TO_CHAR函数处理数字TO_CHAR(number, 格式)TO_CHAR(salary,’$99,999.99’);使用TO_CHAR函数处理日期TO_CHAR(date,’格式’);? TO_NUMBER使用TO_NUMBER函数将字符转换…

JNDI全攻略

名词解释jndi是Java 命名和目录接口(Java Naming and Directory Interface,JNDI)的简称.从一开始就一直是 Java 2 平台企业版(JEE)的核心技术之一。在JMS,JMail,JDBC,EJB等技术中,就大量应用的这…

北京大学纳家勇治研究组在《美国国家科学院院刊》发文阐明时序记忆的神经机制

来源: 北京大学心理与认知科学学院官网概要:记忆是核心认知功能之一,使得人和动物能够根据经验改变自己的行为模式。近日,《美国国家科学院院刊》(Proceedings of the National Academy of Sciences of the United Sta…

oracle nvl2函数延伸,Oracle中replace、translate、nvl2 函数详解

简要比较:replace:字符串级别的代替如:SELECT REPLACE(acdd,cd,ef) FROM dual; →aefdtranslate:字符级别的代替如:SELECT TRANSLATE(acdd,cd,ef) FROM dual; →aeff分别详解:replace:语法:REPL…

管道( Pipeline )模型--示例

类图 时序图 阀门接口 /*** 阀门接口* author administrator**/ public interface Valve {public String getName();public void invoke( Context context ); }基本阀门 /*** 基础阀门* author administrator**/ public class BasicValve implements Valve{private String name…

一文告诉你,NIPS 2017有多火爆 | 附PPT、视频、代码大总结

原文来源:Medium、GitHub作者:TarasSereda「雷克世界」编译:嗯~阿童木呀、KABUDA今年的NIPS是一场盛大的、极富教育意义和探索精神的、魅力十足且人数众多的会议。第一步,登记排队量子计算机Tutorials深度学习:实践与趋…

不入oracle数据库,Oracle数据库之操作符及函数

一、操作符:1、分类:算术、比较、逻辑、集合、连接;2、算术操作符:执行数值计算;--工资加1000select empno,ename,job,sal1000 from emp;3、比较操作符:--比较运算符(between and包头不包尾)select * from …

Facebook面部识别新突破:可识别未标记照片中用户

来源:凤凰科技据科技博客TechCrunch报道,Facebook公司希望用户了解和掌控人们上传的照片,即便用户没有在照片中被标记出来。周二,Facebook推出了一项新的面部识别功能:照片检查(Photo Review)。…

oracle cronb,利用Crontab实现对Oracle数据库的定时备份

假设数据库的拥有者为oracle,数据库的用户为scott,其口令为trigger,Oracle数据库的参数$ORACLE_HOME为/usr/oracle,$ORACLE_SID为oracle1,则实现步骤如下:1、建立实现备份的shell在/usr/oracle中用vi命令建…

德扑 AI 之父解答 Libratus 的13个疑问:没有用到任何深度学习,DL 远非 AI 的全部

来源: AI科技评论概要:卡耐基梅隆大学计算机系在读博士生 Noam Brown 和计算机系教授 Tuomas Sandholm 来到 reddit 的机器学习分版,和网友们一起来了一场「你问我答」(ask me anything)。卡耐基梅隆大学计算机系在读博…

oracle导入错误1401,都是crosscheck惹的祸,备份归档失败

备份是大事,有的时候睡觉都惊醒,忘备份了如果备份不细检查备份环节就更可怕了RMAN> list archivelog all;List of Archived Log CopiesKey Thrd Seq S Low Time Name------- ---- ------- - --------- ----1224 2 107 X 25-DEC-07 /home/oracle/archive/…

Web.XML配置详细说明

1 定义头和根元素 部署描述符文件就像所有XML文件一样,必须以一个XML头开始。这个头声明可以使用的XML版本并给出文件的字符编码。 DOCYTPE声明必须立即出现在此头之后。这个声明告诉服务器适用的servlet规范的版本(如2.2或2.3)并指定管理此…