Java理论与实践: 让J2EE离开容器
副标题#e#
在大大都环境下,Java 应用措施要么是 J2EE 应用措施、要么是 J2SE 应用 措施,而且在这一点上是泾渭理解的。J2EE 应用措施需要 J2EE 容器的处事, 容器要实现一长串的 J2EE API,包罗 Enterprise JavaBean (EJB)、JTA、JNDI 、JMS、JCA 和 JMX。J2EE API 设计为协同事情;究竟,J2EE 设计是从多年来 数百人开拓企业应用措施的履历中提取出的民众需求。像所有框架一样,J2EE API 的主要目标是“不从头发现轮子”。
有一些 API 属于 J2EE 类型的一部门,可是可以很容易地在 J2SE 应用措施 中利用,如 JDBC、JSP 和 servlet,可是对付大大都 J2EE API,J2EE 是一个 要么是要么不是的命题–大大都 J2EE API 需要全成果的 J2EE 容器。不外,有 一些处事器应用措施开拓为 J2SE 应用措施而非 J2EE 应用措施,这凡是都有很 好的来由。为什么这些应用措施的开拓人员必需从头发现轮子呢?J2EE 中是否 有部门内容可以容易地被 J2SE 应用措施借用来提供同样的利益呢?什么组件可 以同时用于 J2EE 和 J2SE 应用措施的组件呢?
松散耦合
J2EE 的一个主要设计道理是 J2EE 应用措施可以松散地耦合–用组件组装, 在组装可能陈设应用措施时而不是在组件开拓时界说可能改变这些组件的彼此连 接。J2EE 组件利用 JNDI 彼此查找和查找所需要的资源,如 JDBC 和 JMS 毗连 。JMS 这样的技能勉励松散耦合,答允机动地为事情流程建模、容易分派处理惩罚任 务、可伸缩性和容错性。许多 J2SE 处事器应用措施也可以从这些技能和道理中 受益。
像 JDBC、JMS 和 JNDI 这样的 API 根基上是“中间件”–它们作为应用程 序与差异的处事提供者之间的统一接口。险些每一个数据库处事器都有 JDBC 驱 动措施,有大量的免费数据库处事器,所以险些每一个但愿操作数据库的 Java 应用措施都可以容易地做到这一点。不外,对付 JMS 就不是这样了。动静行列 处事器远没有数据库这样常见,出格是在小型商店中。可是有大量的应用措施可 以通过利用动静行列而极大地受益。
Somnifugi JMS
动静行列是一个成果强大的典型,它用于构建结实的、机动的、松散耦合的 、可伸缩的应用措施。有一些贸易动静行列产物,如 WebSphere MQ、Sonic、 Fiorano、JBossMQ 和 SpiritWave。就像 JDBC 对付数据库一样,JMS 是动静的 中间件–它使得应用措施可以通过统一的接口会见差异的动静行列产物,这个接 口提供了像 Connection 、 Topic 和 Message 这样的抽象。
很多 J2SE 应用措施利用某种形式的动静行列,可是不利用 JMS–而是利用 线程池、事情行列、任务打点器等。AWT 和 Swing 框架利用动静(事件)在模 型与视图层之间通信,JavaBean 组件操作监听器支持一种基于主题的动静。消 息行列提供了许多布局上的利益–它固有的松散耦合有利于回收机动的、基于组 件的要领,并提供了有助于简化设计和淘汰互连的天然抽象界线。一个附带的好 处是,MQ 典型使得漫衍式的、可伸缩的和容错的设计变得更容易了,因为动静 出产者和利用者不必然需要运行在同一 JVM 中,大大都出产者/利用者任务的本 性是答允并发处理惩罚的。
J2SE 处事器应用措施的开拓人员常常开拓他们本身的动静层,可能从零开始 ,可能以 util.concurrent 这样的库为基本构建。凡是这么做的来由是:
MQ 处事器是昂贵的和重量级的,而且由于我们不需要像耐久性、漫衍式、事 务和验证这样更重量级的成果,构建本身内存中的动静层,只提供所需要的成果 会更容易。
固然这在一般环境下是正确的,可是应用措施需求凡是会跟着时间而增加, 在开始时不需要的一些动静成果在今后大概会变得更重要了。
面向动静的应用措施的开拓人员在开拓进程的初期就必需做出选择–选择一 个贸易动静产物,可能构建本身的更自制的、更轻量级的办理方案。Somnifugi JMS 包团结了这两种方法–一个基于高机能的 util.concurrent 库的非耐久内 存中动静行列处事,和一个切合 JMS API 的接口。与传统 JMS 提供者对较量, Somnifugi 是相当轻量级的,不管是成果上照旧机能上。它只限于在一个 JVM 中利用(尽量可以打消这种限制),并缺少耐久性、事务和验证成果。另一方面 ,它出格快–它比传统 JMS 实现快得多,以至于可以在因机能原因大概无法使 用动静的处所利用它。为了表白 Somnifugi 到底有多轻量级,在它的分发中包 含了几个用 JMS 主题代替 Swing/JavaBean 事件框架的例子。
增加的机动性
Somnifugi 还提供了另一项重要的利益:此刻可以开拓利用 JMS 接口的组件 ,然后在陈设应用措施时抉择是利用更快的、内存中的 Somnifugi 提供者照旧 更重量级的、可是更靠得住的提供者,如 WebSphere MQ。可以将这种选择推迟到 陈设时的长处很是庞大–出格是因为需求大概会在项目标开拓进程中变革时–并 提供了代码重用的时机,对付自已开拓的动静层来说这是不太大概做到的。
#p#副标题#e#
在 J2SE 中利用 JNDI
#p#分页标题#e#
像 JDBC 和 JMS 一样,JNDI 是一种中间件。像 JMS 一样,在 J2SE 应用程 序中利用 JNDI 不像利用 JDBC 那么容易。JDBC 提供者无处不在–有数十种兼 容 JDBC 的贸易和开放源代码数据库处事器。固然所有 J2EE 容器都必需包罗一 个 JNDI 提供者,可是对付不属于 J2EE 容器的 JNDI,数量相对就少了。这不 仅使在 J2SE 应用措施中利用 JNDI 更坚苦了,并且还意味着 J2SE 开拓人员不 太大概打仗到 JNDI 并认识它的优势。
按照所利用的 JNDI 提供者和应用措施设置,JNDI 大概在 JNDI 名称空间中 存储任意的 Java 工具(有一些限制:有些 JNDI 提供者限制存储的工具是可序 列化的)。一般用 JNDI 存储静态设置数据(整型和字符串型)、JDBC DataSource 工具、JMS Connection 和 Topic 工具,以及无状态的工具(包罗 工场工具)。完整地存储已设置工具,好比 JDBC DataSource 工具,而不可是 设置数据,好比 JDBC URL,还可以加强应用措施的安详性,因为像授权凭证这 样的敏感信息不能被应用措施直接利用。
J2EE 应用措施利用 JNDI 作为毗连松散耦合组件之间的“开关板”–J2EE 组件利用 JNDI 寻找其他想要利用的组件,如 EJB 组件,并寻找 JDBC 和 JMS 毗连这样的资源。J2EE 组件之间的互连是在组件的陈设描写符中声明式地界说 的,容器自动将工具绑定到名称空间中的特定位置,并担保在陈设组件之前组件 之间的所有资源依赖干系都获得满意。
J2SE 应用措施可以以雷同于 J2EE 应用措施的方法利用 JNDI,只是它们必 须多做一些填充名称空间的事情。可是长处是沟通的–应用措施可以更松散地耦 合,组件在运行时互相发明。
免费 JNDI 提供者
固然 JNDI 参考实现不包罗一般性的 JDNI 提供者,可是可以下载 Sun 网站 提供的 File System (FSContext)。这是一个示例 JNDI 提供者,它是以源代 码的方法提供的,它会见并存储文件中的可序列化工具,还使名称空间的内容可 以担保跨措施挪用的一致性。固然 FSContext JNDI 提供者主要是做为编写 JNDI 提供者的一个示例,可是简朴的应用措施也可以利用它作为序列化工具的 耐久性数据存储,可能是作为“存根” JNDI 提供者,对从 JNDI 得到其设置的 组件举办单位测试。
JBoss 开放源代码 J2EE 容器还包罗一个更一般性的 JNDI 提供者 JNPServer,它可以容易地作为单独的 JNDI 提供者运行,不需要 JBoss 容器。 可以通过 RMI 从长途 JVM 会见 JNP,而在当地 JVM 中不会发生 RMI 开销。它 在内部将工具存储到内存中的一个 HashMap 中。
在 JBoss 刊行版的 jnpserver.jarJAR 文件中可以找到 JNP JNDI 处事器, 它还依赖于 log4j 日志引擎。要利用它,必需设置 log4j,建设相应的 jndi.properties文件(拜见清单 1),并布置通过挪用同一 JVM 可能另一个 JVM 中的 org.jnp.server.Main 的主进口点来启动处事器。会见 JNDI 名称空 间的类文件在 JBoss 刊行版的 jnpclient.jarJAR 文件中。
清单 1. JNPServer 的 jndi.properties
java.naming.factory.initial=org.jnp.interfaces.NamingContextF actory
java.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfaces
# Uncomment this line only if the JNDI server is to run in another JVM;
# otherwise, local JNDI requests will go over RMI
#java.naming.provider.url=localhost
Java 打点扩展(JMX)
Java 打点扩展(Java Management Extensions,JMX)是一种打点组件和服 务的生命周期的机制。JBoss 大量利用 JMX–JBoss 中的险些所有组件都作为 JMX 处事提供。功效就是很容易设置一个只包罗所需处事的应用措施。对付每一 个组件处事,建设一个名为 MBean (托管的 bean)工具,它包括生命周期要领 ( start() 和 stop() )和果真属性的 getter 和 setter。清单 2 显示了描 述一个简朴 Web 容器处事的 MBean 接口:
清单 2. 简朴 Web 容器处事的 MBean 接口
public interface WebServerMBean {
// Lifecycle methods
void create() throws Exception;
void start() throws Exception;
void stop();
void destroy();
// Getter and setter for listener-port property
int getPort();
void setPort(int port);
// Get the names of loaded Web applications
String[] getWebApplications();
}
#p#分页标题#e#
JBoss 还包罗一个 Web 应用措施( jmx-console ),它可以查察当前装载 到 JBoss 处事器中的 MBeans、查抄它们当前的状态、并用欣赏器读取和写入它 们的属性。(JMX 参考实现还包罗一个名为 HtmlAdapter 的 Web 应用措施。)
固然 JMX 是为 J2EE 提供的,可是也可以在 J2SE 应用措施中容易地利用它 。至少有两个免费的 JMX 实现,Sun 的参考实现和开放源代码 MX4J。编写一个 MBean 以描写一个组件是相当简朴的–凡是所要做的就是实现 start() 和 stop() 要领。编写一个简朴的装载一组 MBean 并启动它们的 JMS “容器”只 需约 40 行代码。遵循 JMX 尺度,不单获得利用 JMS 的长处,好比长途属性检 查和哄骗(这对付调试及打点都有长处),并且还可以更容易地编写可以等闲地 同时运行在 J2SE 和 J2EE 情况中的组件。
竣事语
固然 J2EE 和 J2SE 是用于差异事情的差异东西,可是很多开拓人员发明自 己必需抉择各类框架处事的“轻量级”和“重量级”实现,好比动静、设置可能 打点。通过利用 J2EE 接口的较轻量级的实现,如 Somnifugi JMS,开拓人员可 以在短期内获得机能和易于利用的长处,同时又具有在未来需要时,可以容易地 迁移到更重量级的办理方案的机动性。