java RMI 服务器:rmiregistry 或 LocateRegistry.createRegistry
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/99242/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
RMI server: rmiregistry or LocateRegistry.createRegistry
提问by Randy Sugianto 'Yuku'
For RMI on server-side, do we need to start rmiregistryprogram, or just call LocateRegistry.createRegistry?
If both are possible, what are the advantages and disadvantages?
对于服务器端的 RMI,我们需要启动rmiregistry程序,还是直接调用LocateRegistry.createRegistry?如果两者都可能,有什么优点和缺点?
采纳答案by user17250
They're the same thing... rmiregistryis a separate program, which you can run from a command line or a script, while LocateRegistry.createRegistrydoes the same thing programatically.
它们是同一件事……rmiregistry是一个单独的程序,您可以从命令行或脚本运行它,同时LocateRegistry.createRegistry以编程方式执行相同的操作。
In my experience, for "real" servers you will want to use rmiregistryso that you know it's always running regardless of whether or not the client application is started. createRegistryis very useful for testing, as you can start and stop the registry from your test as necessary.
根据我的经验,对于“真正的”服务器,您将希望使用它,rmiregistry以便您知道无论客户端应用程序是否启动,它始终在运行。createRegistry对测试非常有用,因为您可以根据需要从测试中启动和停止注册表。
回答by William Wong
If we start rmiregistry first, RmiServiceExporter would register itself to the running rmiregistry. In this case, we have to set the system property 'java.rmi.server.codebase' to where the 'org.springframework.remoting.rmi.RmiInvocationWrapper_Stub' class can be found. Otherwise, the RmiServiceExporter would not be started and got the exception " ClassNotFoundException class not found: org.springframework.remoting.rmi.RmiInvocationWrapper_Stub; nested exception is: ..."
如果我们先启动 rmiregistry,RmiServiceExporter 会将自己注册到正在运行的 rmiregistry。在这种情况下,我们必须将系统属性“java.rmi.server.codebase”设置为可以找到“org.springframework.remoting.rmi.RmiInvocationWrapper_Stub”类的位置。否则,将不会启动 RmiServiceExporter 并得到异常“未找到 ClassNotFoundException 类:org.springframework.remoting.rmi.RmiInvocationWrapper_Stub;嵌套异常是:...”
If your rmi server, rmi client and rmiregistry can access the same filesystem, you may want the system property to be automatically configured to where the spring.jar can be found on the shared filesystem. The following utility classes and spring configuration show how this can be achieved.
如果您的 rmi 服务器、rmi 客户端和 rmiregistry 可以访问相同的文件系统,您可能希望系统属性自动配置为在共享文件系统上可以找到 spring.jar 的位置。以下实用程序类和 spring 配置显示了如何实现这一点。
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>
The above example shows how system property be set automatically only when rmi server, rmi client and rmi registry can access the same filesystem. If that is not true or spring codebase is shared via other method (e.g. HTTP), you may modify the CodeBaseResolver to fit your need.
上面的例子展示了如何仅当 rmi 服务器、rmi 客户端和 rmi 注册表可以访问相同的文件系统时才自动设置系统属性。如果这不是真的,或者 spring 代码库是通过其他方法(例如 HTTP)共享的,您可以修改 CodeBaseResolver 以满足您的需要。
回答by Autobyte
If you are writing a standalone java application you would want to start your own rmiregistry but if you are writing a J2EE app that obviously runs inside a J2EE container then you want to "LocateRegistry" as there is already one running on the app server!
如果您正在编写一个独立的 Java 应用程序,您可能想要启动自己的 rmiregistry,但如果您正在编写一个显然在 J2EE 容器内运行的 J2EE 应用程序,那么您想要“LocateRegistry”,因为应用程序服务器上已经有一个运行了!
回答by Kevin Wong
If you use Spring to export your RMI services, it automatically starts a registry if one is not already running. See RmiServiceExporter
如果您使用 Spring 导出您的 RMI 服务,它会自动启动一个尚未运行的注册表。见RmiServiceExporter

