大多数项目不是属于 J 可以存在于 J2EE 容器之外 Goetz 分析如何在 J2SE 应 他读者分享您关于本文的心 | 2EE 应用程序就是属于 J2SE 应 ,并且有些 J2SE 应用程序可以 用程序中使用某些 J2EE 服务。 得。(您也可以单击文章顶部或 | 用程序。不过,有一些 J2EE 技术 对它们加以利用。本月,Brian 请在附带的讨论论坛上与作者和其 底部的讨论来访问论坛。) |
在大多数情况下,Java 在这一点上是泾渭分明的。 J2EE API,包括 Enterpris 计为协同工作;毕竟,J2EE 需求。像所有框架一样,J2 | 应用程序要么是 J2EE 应用程 J2EE 应用程序需要 J2EE 容器 e JavaBean (EJB)、JTA、JNDI 设计是从多年来数百人开发企 EE API 的主要目的是“不重新 | 序、要么是 J2SE 应用程序,并且 的服务,容器要实现一长串的 、JMS、JCA 和 JMX。J2EE API 设 业应用程序的经验中提取出的公共 发明轮子”。 |
有一些 API 属于 J2EE JDBC、JSP 和 servlet, —大多数 J2EE API 需要全 用程序而非 J2EE 应用程序 新发明轮子呢?J2EE 中是 呢?什么组件可以同时用于 | 规范的一部分,但是可以很容 但是对于大多数 J2EE API,J2E 功能的 J2EE 容器。不过,有一 ,这通常都有很好的理由。为什 否有部分内容可以容易地被 J2S J2EE 和 J2SE 应用程序的组件 | 易地在 J2SE 应用程序中使用,如 E 是一个要么是要么不是的命题— 些服务器应用程序开发为 J2SE 应 么这些应用程序的开发人员必须重 E 应用程序借用来提供同样的优点 呢? |
松散耦合 |
J2EE 的一个主要设计原理是 J2EE 者部署应用程序时而不是在组件开发时定 JNDI 相互查找和查找所需要的资源,如 允许灵活地为工作流程建模、容易分配处 程序也可以从这些技术和原理中受益。 | 应用程序可以松散地耦合——用组件组装,在组装或 义或者改变这些组件的相互连接。J2EE 组件使用 JDBC 和 JMS 连接。JMS 这样的技术鼓励松散耦合, 理任务、可伸缩性和容错性。很多 J2SE 服务器应用 |
像 JDBC、JMS 和 JNDI 这样的 API 服务提供者之间的统一接口。几乎每一个 据库服务器,所以几乎每一个希望利用数 过,对于 JMS 就不是这样了。消息队列 。但是有大量的应用程序可以通过使用消 | 基本上是“中间件”——它们作为应用程序与不同的 数据库服务器都有 JDBC 驱动程序,有大量的免费数 据库的 Java 应用程序都可以容易地做到这一点。不 服务器远没有数据库这样常见,特别是在小型商店中 息队列而极大地受益。 |
Somnifugi JMS |
消息队列是一个功能强 用程序。有一些商业消息队 SpiritWave。就像 JDBC 对 统一的接口访问不同的消息 样的抽象。 | 大的范例,它用于构建健壮的、 列产品,如 WebSphere MQ、Son 于数据库一样,JMS 是消息的中 队列产品,这个接口提供了像 C | 灵活的、松散耦合的、可伸缩的应 ic、Fiorano、JBossMQ 和 间件——它使得应用程序可以通过 onnection、Topic 和Message 这 |
许多 J2SE 应用程序使用某种形式的 作队列、任务管理器等。AWT 和 Swing JavaBean 组件利用监听器支持一种基于 它固有的松散耦合有利于采用灵活的、基 的天然抽象边界。一个附带的好处是,MQ 容易了,因为消息生产者和使用者不一定 的本性是允许并发处理的。 | 消息队列,但是不使用 JMS——而是使用线程池、工 框架使用消息(事件)在模型与视图层之间通信, 主题的消息。消息队列提供了很多结构上的优点—— 于组件的方法,并提供了有助于简化设计和减少互连 范例使得分布式的、可伸缩的和容错的设计变得更 需要运行在同一 JVM 中,大多数生产者/使用者任务 |
J2SE 服务器应用程序 util.concurrent 这样的库 | 的开发人员经常开发他们自己的 为基础构建。通常这么做的理由 | 消息层,或者从零开始,或者以 是: |
MQ 服务器是昂贵的和 样更重量级的功能,构建自 | 重量级的,并且由于我们不需要 己内存中的消息层,只提供所需 | 像持久性、分布式、事务和验证这 要的功能会更容易。 |
虽然这在一般情况下是 要的一些消息功能在以后可 | 正确的,但是应用程序需求通常 能会变得更重要了。 | 会随着时间而增加,在开始时不需 |
面向消息的应用程序的开发人员在开 产品,或者构建自己的更便宜的、更轻量 ——一个基于高性能的 util.concurrent API 的接口。与传统 JMS 提供者相比较 能上。它只限于在一个 JVM 中使用(尽 功能。另一方面,它特别快——它比传统 法使用消息的地方使用它。为了表明 Som 用 JMS 主题取代 Swing/JavaBean 事件 | 发过程的初期就必须做出选择——选择一个商业消息 级的解决方案。Somnifugi JMS 包结合了这两种方式 库的非持久内存中消息队列服务,和一个符合 JMS ,Somnifugi 是相当轻量级的,不管是功能上还是性 管可以取消这种限制),并缺少持久性、事务和验证 JMS 实现快得多,以至于可以在因性能原因可能无 nifugi 到底有多轻量级,在它的分发中包含了几个 框架的例子。 |
增加的灵活性 |
Somnifugi 还提供了另一项重要的优 署应用程序时决定是使用更快的、内存中 的提供者,如 WebSphere MQ。可以将这 需求可能会在项目的开发过程中变化时— 来说这是不太可能做到的。 | 点:现在可以开发使用 JMS 接口的组件,然后在部 的 Somnifugi 提供者还是更重量级的、但是更可靠 种选择推迟到部署时的好处非常巨大——特别是因为 —并提供了代码重用的机会,对于自已开发的消息层 |
在 J2SE 中使用 JNDI |
像 JDBC 和 JMS 一样 JNDI 不像使用 JDBC 那么 放源代码数据库服务器。虽 J2EE 容器的 JNDI,数量 而且还意味着 J2SE 开发人 | ,JNDI 是一种中间件。像 JMS 容易。JDBC 提供者无处不在— 然所有 J2EE 容器都必须包括一 相对就少了。这不仅使在 J2SE 员不太可能接触到 JNDI 并认识 | 一样,在 J2SE 应用程序中使用 —有数十种兼容 JDBC 的商业和开 个 JNDI 提供者,但是对于不属于 应用程序中使用 JNDI 更困难了, 它的优势。 |
根据所使用的 JNDI 提 Java 对象(有一些限制: 存储静态配置数据(整型和 对象,以及无状态的对象( DataSource 对象,而不只 为像授权凭证这样的敏感信 | 供者和应用程序配置,JNDI 可 有些 JNDI 提供者限制存储的对 字符串型)、JDBC DataSource 包括工厂对象)。完整地存储已 是配置数据,比如 JDBC URL, 息不能被应用程序直接使用。 | 能在 JNDI 名称空间中存储任意的 象是可序列化的)。一般用 JNDI 对象、JMS Connection 和 Topic 配置对象,比如 JDBC 还可以增强应用程序的安全性,因 |
J2EE 应用程序使用 JNDI 作为连接 JNDI 寻找其他想要使用的组件,如 EJB 组件之间的互连是在组件的部署描述符中 的特定位置,并保证在部署组件之前组件 | 松散耦合组件之间的“开关板”——J2EE 组件使用 组件,并寻找 JDBC 和 JMS 连接这样的资源。J2EE 声明式地定义的,容器自动将对象绑定到名称空间中 之间的所有资源依赖关系都得到满足。 |
J2SE 应用程序可以以 填充名称空间的工作。但是 发现。 | 类似于 J2EE 应用程序的方式使 好处是相同的——应用程序可以 | 用 JNDI,只是它们必须多做一些 更松散地耦合,组件在运行时彼此 |
免费 JNDI 提供者 |
虽然 JNDI 参考实现不 File System (FSContext 访问并存储文件中的可序列 FSContext JNDI 提供者主 以使用它作为序列化对象的 获得其配置的组件进行单元 | 包括一般性的 JDNI 提供者,但 )。这是一个示例 JNDI 提供者 化对象,还使名称空间的内容可 要是做为编写 JNDI 提供者的一 持久性数据存储,或者是作为“ 测试。 | 是可以下载 Sun 网站提供的 ,它是以源代码的方式提供的,它 以保证跨程序调用的一致性。虽然 个示例,但是简单的应用程序也可 存根” JNDI 提供者,对从 JNDI |
JBoss 开放源代码 J2EE 容器还包括 易地作为单独的 JNDI 提供者运行,不需 JNP,而在本地 JVM 中不会产生 RMI 开 中。 | 一个更一般性的 JNDI 提供者 JNPServer,它可以容 要 JBoss 容器。可以通过 RMI 从远程 JVM 访问 销。它在内部将对象存储到内存中的一个 HashMap |
在 JBoss 发行版的 jn log4j 日志引擎。要使用 清单 1),并安排通过调用 点来启动服务器。访问 JND 件中。 | pserver.jar JAR 文件中可以找 它,必须配置 log4j,创建相应 同一 JVM 或者另一个 JVM 中的 I 名称空间的类文件在 JBoss | 到 JNP JNDI 服务器,它还依赖于 的 jndi.properties 文件(参见 org.jnp.server.Main 的主入口 发行版的 jnpclient.jar JAR 文 |
清单 1. JNPServer 的 jndi.properties |
java.naming.factory.initial=org. | jnp.interfaces.NamingContextFactory |
java.naming.factory. | url.pkgs=org.jboss.naming:or | g.jnp.interfaces |
# Uncomment this lin | e 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 的机制。JBoss 大量使用 J 很容易配置一个只包括所需 托管的 bean)对象,它包 setter。清单 2 显示了描 | Management Extensions,JMX) MX——JBoss 中的几乎所有组件 服务的应用程序。对于每一个组 含生命周期方法(start() 和 s 述一个简单 Web 容器服务的 MB | 是一种管理组件和服务的生命周期 都作为 JMX 服务提供。结果就是 件服务,创建一个名为 MBean ( top())和公开属性的 getter 和 ean 接口: |
清单 2. 简单 Web 容器服务的 MBean 接口 |
public interface WebServerMBean { |
// Lifecycle methods |
void create() throws Exception; |
void start() throws Exception; |
void stop(); |
void destroy(); |
// Getter and setter for list | ener-port property |
int getPort(); |
void setPort(int port); |
// Get the names of loaded We | b applications |
String[] getWebApplications(); |
} |
JBoss 还包括一个 Web 器中的 MBeans、检查它们 还包括一个名为 HtmlAdapt | 应用程序(jmx-console),它 当前的状态、并用浏览器读取和 er 的 Web 应用程序。) | 可以查看当前装载到 JBoss 服务 写入它们的属性。(JMX 参考实现 |
虽然 JMX 是为 J2EE 个免费的 JMX 实现,Sun 件是相当简单的——通常所 组 MBean 并启动它们的 JM JMS 的好处,比如远程属性 编写可以轻易地同时运行在 | 提供的,但是也可以在 J2SE 应 的参考实现和开放源代码 MX4J 要做的就是实现 start() 和sto S “容器”只需约 40 行代码。 检查和操纵(这对于调试及管理 J2SE 和 J2EE 环境中的组件。 | 用程序中容易地使用它。至少有两 。编写一个 MBean 以描述一个组 p() 方法。编写一个简单的装载一 遵循 JMX 标准,不但得到使用 都有好处),而且还可以更容易地 |
结束语 |
虽然 J2EE 和 J2SE 是用于不同工作 种框架服务的“轻量级”和“重量级”实 的较轻量级的实现,如 Somnifugi JMS, 同时又具有在将来需要时,可以容易地迁 | 的不同工具,但是许多开发人员发现自己必须决定各 现,比如消息、配置或者管理。通过使用 J2EE 接口 开发人员可以在短期内得到性能和易于使用的好处, 移到更重量级的解决方案的灵活性。 |