RMI сервер: rmiregistry или LocateRegistry.createRegistry - PullRequest
13 голосов
/ 19 сентября 2008

Для RMI на стороне сервера, нам нужно запустить rmiregistry программу или просто вызвать LocateRegistry.createRegistry? Если оба варианта возможны, каковы преимущества и недостатки?

Ответы [ 4 ]

7 голосов
/ 19 сентября 2008

Это одно и то же ... rmiregistry - это отдельная программа, которую вы можете запустить из командной строки или скрипта, в то время как LocateRegistry.createRegistry делает то же самое программно.

По моему опыту, для "реальных" серверов вы захотите использовать rmiregistry, чтобы вы знали, что он всегда работает независимо от того, запущено клиентское приложение или нет. createRegistry очень полезен для тестирования, так как вы можете запускать и останавливать реестр при необходимости.

4 голосов
/ 12 июня 2009

Если мы сначала запустим 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 в соответствии с вашими потребностями.

0 голосов
/ 20 сентября 2008

Если вы используете Spring для экспорта своих служб RMI, он автоматически запускает реестр, если он еще не запущен. См. RmiServiceExporter

0 голосов
/ 19 сентября 2008

Если вы пишете отдельное Java-приложение, вы захотите запустить собственное rmiregistry, но если вы пишете J2EE-приложение, которое, очевидно, запускается внутри контейнера J2EE, тогда вы хотите «LocateRegistry», так как оно уже запущено в приложении. сервер!

...