Подтвердить что ты не робот

Сервер RMI: rmiregistry или LocateRegistry.createRegistry

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

4b9b3361

Ответ 1

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

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

Ответ 2

Если сначала запустить 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 может быть найден в общей файловой системе. Следующие утилиты и конфигурация 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 codebase используется другим способом (например, HTTP), вы можете изменить CodeBaseResolver в соответствии с вашими потребностями.

Ответ 3

Если вы пишете автономное приложение java, вы хотите запустить свою собственную rmiregistry, но если вы пишете приложение J2EE, которое явно работает внутри контейнера J2EE, вы хотите "LocateRegistry", поскольку в приложении уже есть приложение сервер!

Ответ 4

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