RMI 服务器:rmiregistry 或 LocateRegistry.createRegistry

发布于 2024-07-05 10:52:13 字数 122 浏览 7 评论 0原文

对于服务器端的RMI,我们需要启动rmiregistry程序,还是只调用LocateRegistry.createRegistry? 如果两者都可以的话,各有什么优点和缺点?

For RMI on server-side, do we need to start rmiregistry program, or just call LocateRegistry.createRegistry?
If both are possible, what are the advantages and disadvantages?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

为人所爱 2024-07-12 10:52:13

如果您正在编写一个独立的 java 应用程序,您可能希望启动自己的 rmiregistry,但如果您正在编写一个显然在 J2EE 容器内运行的 J2EE 应用程序,那么您希望“LocateRegistry”,因为应用程序服务器上已经有一个正在运行!

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!

桜花祭 2024-07-12 10:52:13

如果您使用 Spring 导出 RMI 服务,它会自动启动注册表(如果注册表尚未运行)。 请参阅 RmiServiceExporter

If you use Spring to export your RMI services, it automatically starts a registry if one is not already running. See RmiServiceExporter

迷迭香的记忆 2024-07-12 10:52:13

如果我们首先启动 rmiregistry,RmiServiceExporter 会将自身注册到正在运行的 rmiregistry。 在这种情况下,我们必须将系统属性“java.rmi.server.codebase”设置为可以找到“org.springframework.remoting.rmi.RmiInitationWrapper_Stub”类的位置。 否则,RmiServiceExporter 将不会启动并出现异常“
ClassNotFoundException 未找到类:org.springframework.remoting.rmi.RmiInitationWrapper_Stub; 嵌套异常是:...”

如果您的 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>

上面的示例显示了仅当 rmi 服务器、rmi 客户端和 rmi 注册表可以访问同一文件系统时如何自动设置系统属性,或者 spring 代码库通过其他方法共享。 (例如HTTP),您可以修改CodeBaseResolver以满足您的需要。

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: ..."

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.

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.

时光匆匆的小流年 2024-07-12 10:52:13

它们是同一件事...rmiregistry 是一个单独的程序,您可以从命令行或脚本运行它,而 LocateRegistry.createRegistry 以编程方式执行相同的操作。

根据我的经验,对于“真实”服务器,您将需要使用rmiregistry,这样您就知道无论客户端应用程序是否启动,它都始终在运行。 createRegistry 对于测试非常有用,因为您可以根据需要从测试中启动和停止注册表。

They're the same thing... rmiregistry is a separate program, which you can run from a command line or a script, while LocateRegistry.createRegistry does the same thing programatically.

In my experience, for "real" servers you will want to use rmiregistry so that you know it's always running regardless of whether or not the client application is started. createRegistry is very useful for testing, as you can start and stop the registry from your test as necessary.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文