2008-09-19 191 views

回答

7

它們是一樣的東西...... rmiregistry是一個單獨的程序,您可以從命令行或腳本運行,而LocateRegistry.createRegistry以編程方式執行相同的操作。

根據我的經驗,對於「真實」服務器,您將希望使用rmiregistry,以便無論客戶端應用程序是否啓動,您都知道它始終在運行。 createRegistry對測試非常有用,因爲您可以根據需要從註冊表中啓動和停止註冊表。

+0

有沒有辦法讓createRegistry在除「localhost」之外的界面上工作? – Eagle 2013-05-02 21:16:16

+0

更新:文檔說''createRegistry''在Localhost上導出註冊表。但是,註冊表也能夠接受來自外向接口的連接。 – Eagle 2013-05-06 14:39:22

+0

@Eagle導出在本地主機上運行的Registry *。沒有暗示它只能聽127.0.0.1。 – EJP 2017-07-05 03:28:45

0

如果你正在編寫一個獨立的java應用程序,你會想開始你自己的rmiregistry,但是如果你正在編寫一個顯然運行在J2EE容器內的J2EE應用程序,那麼你想要「LocateRegistry」,因爲已經有一個運行在應用服務器!

0

如果您使用Spring導出您的RMI服務,它會自動啓動註冊表(如果尚未運行)。請參見RmiServiceExporter

4

如果我們先啓動rmiregistry,則RmiServiceExporter將自己註冊到正在運行的rmiregistry。在這種情況下,我們必須將系統屬性'java.rmi.server.codebase'設置爲可以找到'org.springframework.remoting.rmi.RmiInvocationWrapper_Stub'類的位置。否則,RmiServiceExporter不會被啓動,得到了異常「 ClassNotFoundException的類未找到:org.springframework.remoting.rmi.RmiInvocationWrapper_Stub;嵌套的例外是:......」

如果RMI服務器,RMI客戶端和rmiregistry的可以訪問相同的文件系統,您可能希望將系統屬性自動配置爲可在共享文件系統上找到spring.jar的位置。以下實用程序類和彈簧配置顯示瞭如何實現這一點。

abstract public class CodeBaseResolver { 
    static public String resolveCodeBaseForClass(Class<?> clazz) { 
    Assert.notNull(clazz); 
    final CodeSource codeSource = clazz.getProtectionDomain().getCodeSource(); 
    if (codeSource != null) { 
     return codeSource.getLocation().toString(); 
    } else { 
     return ""; 
    } 
    } 
} 

public class SystemPropertyConfigurer { 
    private Map<String, String> systemProperties; 
    public void setSystemProperties(Map<String, String> systemProperties) { 
    this.systemProperties = systemProperties; 
    } 

    @PostConstruct 
    void init() throws BeansException { 
    if (systemProperties == null || systemProperties.isEmpty()) { 
     return; 
    } 
    for (Map.Entry<String, String> entry : systemProperties.entrySet()) { 
     final String key = entry.getKey(); 
     final String value = SystemPropertyUtils.resolvePlaceholders(entry.getValue()); 
     System.setProperty(key, value); 
    } 
    } 
} 


<bean id="springCodeBase" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean"> 
    <property name="staticMethod" value="xx.CodeBaseResolver.resolveCodeBaseForClass" /> 
    <property name="arguments"> 
    <list> 
     <value>org.springframework.remoting.rmi.RmiInvocationWrapper_Stub</value> 
    </list> 
    </property> 
</bean> 

<bean id="springCodeBaseConfigurer" class="xx.SystemPropertyConfigurer" 
    depends-on="springCodeBase"> 
    <property name="systemProperties"> 
    <map> 
     <entry key="java.rmi.server.codebase" value-ref="springCodeBase" /> 
    </map> 
    </property> 
</bean> 

<bean id="rmiServiceExporter" class="org.springframework.remoting.rmi.RmiServiceExporter" depends-on="springCodeBaseConfigurer"> 
    <property name="serviceName" value="XXX" /> 
    <property name="service" ref="XXX" /> 
    <property name="serviceInterface" value="XXX" /> 
    <property name="registryPort" value="${remote.rmi.port}" /> 
</bean> 

上面的例子說明了如何系統屬性被自動設置僅當RMI服務器,RMI客戶機和RMI註冊表可以訪問相同的文件系統。如果不是這樣,或者Spring代碼庫通過其他方法(例如HTTP)共享,那麼您可以修改CodeBaseResolver以適應您的需要。