大多數項目不是屬於 J2EE 應用程序就是屬於 J2SE 應用程序。不過,有一些 J2EE 技術可以存在於 J2EE 容器之外,並且有些 J2SE 應用程序可以對它們加以利用。本月,Brian Goetz 分析如何在 J2SE 應用程序中使用某些 J2EE 服務。在大多數情況下,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 中,大多數生產者/使用者任務的本性是允許並發處理的。大多數項目不是屬於 J2EE 應用程序就是屬於 J2SE 應用程序。不過,有一些 J2EE 技術可以存在於 J2EE 容器之外,並且有些 J2SE 應用程序可以對它們加以利用。本月,Brian Goetz 分析如何在 J2SE 應用程序中使用某些 J2EE 服務。在大多數情況下,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 中,大多數生產者/使用者任務的本性是允許並發處理的。在 JBoss 發行版的 jnpserver.jar JAR 文件中可以找到 JNP JNDI 服務器,它還依賴於 log4j 日志引擎。要使用它,必須配置 log4j,創建相應的 jndi.propertIEs 文件(參見清單 1),並安排通過調用同一 JVM 或者另一個 JVM 中的 org.jnp.server.Main 的主入口點來啟動服務器。訪問 JNDI 名稱空間的類文件在 JBoss 發行版的 jnpclient.jar JAR 文件中。 清單 1. JNPServer 的 jndi.propertIEs java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory 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(); } 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,開發人員可以在短期內得到性能和易於使用的好處,同時又具有在將來需要時,可以容易地遷移到更重量級的解決方案的靈活性。