首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

EJB 3.0 遠程客戶端開發指南:JNDI 查找與 TravelAgent 實戰

     編輯:Java 相關知識

在企業級 Java 應用中,遠程客戶端訪問 Enterprise Bean 是基礎且關鍵的環節。本文以 TravelAgent EJB 為例,詳細講解如何編寫獨立 Java 客戶端應用,通過 JNDI 定位遠程接口,完成 Cabin 實體的創建與查詢操作,並深入剖析不同應用服務器的 JNDI 配置差異。

一、客戶端核心代碼結構

客戶端主要完成三件事:獲取 JNDI 上下文、查找遠程接口、調用業務方法。以下是標準實現:

package com.titan.clients;

import com.titan.travelagent.TravelAgentRemote;
import com.titan.domain.Cabin;
import javax.naming.*;
import javax.rmi.PortableRemoteObject;
import java.util.Properties;

public class Client {
    public static void main(String[] args) {
        try {
            Context jndiContext = getInitialContext();
            Object ref = jndiContext.lookup("TravelAgentBean/remote");
            TravelAgentRemote dao = (TravelAgentRemote)
                PortableRemoteObject.narrow(ref, TravelAgentRemote.class);

            // 創建 Cabin 實體
            Cabin cabin = new Cabin();
            cabin.setId(1);
            cabin.setName("Master Suite");
            cabin.setDeckLevel(1);
            cabin.setShipId(1);
            cabin.setBedCount(3);
            dao.createCabin(cabin);

            // 通過主鍵查詢
            Cabin found = dao.findCabin(1);
            System.out.println("Name: " + found.getName());
            System.out.println("DeckLevel: " + found.getDeckLevel());
            System.out.println("ShipId: " + found.getShipId());
            System.out.println("BedCount: " + found.getBedCount());

        } catch (NamingException ne) {
            ne.printStackTrace();
        }
    }

    public static Context getInitialContext() throws NamingException {
        Properties props = new Properties();
        // 此處需填入廠商特定的 JNDI 屬性
        return new InitialContext(props);
    }
}

二、JNDI 上下文獲取的廠商差異

getInitialContext() 的具體實現強依賴應用服務器廠商,以下是主流服務器的典型配置:

1. WebSphere

Properties props = new Properties();
props.put(Context.PROVIDER_URL, "iiop:///");
props.put(Context.INITIAL_CONTEXT_FACTORY,
    "com.ibm.ejs.ns.jndi.CNInitialContextFactory");
return new InitialContext(props);

2. JBoss / WildFly

Properties props = new Properties();
props.put(Context.INITIAL_CONTEXT_FACTORY,
    "org.jnp.interfaces.NamingContextFactory");
props.put(Context.URL_PKG_PREFIXES,
    "org.jboss.naming:org.jnp.interfaces");
props.put(Context.PROVIDER_URL, "jnp://localhost:1099");
return new InitialContext(props);

3. Java EE 組件內部調用(Servlet、EJB、App Client)

若客戶端本身運行在 Java EE 容器中,無需顯式設置屬性,容器會自動注入預配置的 JNDI 環境:

public static Context getInitialContext() throws NamingException {
    return new InitialContext(); // 無參構造即可
}

此時查找名稱通常綁定在 java:comp/env/ejb/ 名字空間下,例如:

Object ref = jndiContext.lookup("java:comp/env/ejb/TravelAgentRemote");

三、PortableRemoteObject.narrow() 的必要性

JNDI lookup() 返回的是 java.lang.Object,必須通過 PortableRemoteObject.narrow() 窄化為具體的遠程接口類型。這是因為 RMI-IIOP 基於 CORBA,而 CORBA 不支持直接強制轉型(某些語言無轉型概念),因此需要顯式窄化操作。此機制自 EJB 1.1 引入,沿用至 EJB 3.0 遠程客戶端。

四、查找名稱的綁定與部署

JNDI 查找名稱(如 TravelAgentBean/remote)由部署人員在部署描述文件或管理控制台中指定,與代碼中的邏輯名稱解耦。部署時需將邏輯名稱映射到具體的 EJB 遠程接口。EJB 3.0 也支持通過 @RemoteBinding 等注解直接指定 JNDI 名稱,簡化配置。

五、最佳實踐總結

  • 獨立客戶端:必須顯式配置廠商特定 JNDI 屬性,使用 PortableRemoteObject.narrow()。
  • 容器內組件:優先使用無參 InitialContext,查找名稱綁定在 java:comp/env/ejb/,利用依賴注入(@EJB)更簡潔。
  • 可移植性:將 JNDI 相關屬性外部化到配置文件,避免硬編碼。
  • 異常處理:妥善捕獲 NamingException,記錄日誌並提供友好錯誤提示。

掌握 JNDI 查找機制與廠商差異,是構建健壯、可移植 EJB 客戶端應用的基石。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved