RMIサーバー:rmiregistry または LocateRegistry.createRegistry
-
01-07-2019 - |
質問
サーバー側の RMI の場合、開始する必要がありますか? rmiregistry
プログラムするか、単に電話するだけです LocateRegistry.createRegistry
?両方が可能である場合、メリットとデメリットは何ですか?
解決
それらは同じものです... rmiregistry
は別個のプログラムであり、コマンドラインまたはスクリプトから実行できます。 LocateRegistry.createRegistry
同じことをプログラム的に実行します。
私の経験では、「実際の」サーバーには次のようなものを使用する必要があります。 rmiregistry
これにより、クライアント アプリケーションが開始されているかどうかに関係なく、常に実行されていることがわかります。 createRegistry
必要に応じてテストからレジストリを開始および停止できるため、テストに非常に役立ちます。
他のヒント
最初に 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 を変更できます。
スタンドアロンの Java アプリケーションを作成している場合は、独自の rmiregistry を開始する必要がありますが、明らかに J2EE コンテナ内で実行される J2EE アプリケーションを作成している場合は、アプリケーション サーバー上ですでに実行されているものがあるため、「LocateRegistry」を実行する必要があります。
Spring を使用して RMI サービスをエクスポートすると、レジストリがまだ実行されていない場合は自動的にレジストリが開始されます。見る RmiServiceExporter