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

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

Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
13
0
12 681
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

Ответ принят как подходящий

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

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

Есть ли способ для createRegistry работать с интерфейсом помимо localhost?

Eagle 03.05.2013 01:16

Обновление: в документации сказано, что createRegistry экспортирует реестр на Localhost. Однако реестр также может принимать соединения от внешних интерфейсов.

Eagle 06.05.2013 18:39

@Eagle экспортирует реестр работает в на локальный хост. Это не означает, что он слушает только 127.0.0.1.

user207421 05.07.2017 06:28

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

Не соответствует действительности и немотивирован. Возможно, вы захотите использовать LocateRegistry и в отдельной программе.

user207421 03.01.2018 19:57

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

Можете ли вы отредактировать это, чтобы включить ссылку на документацию по этой функции?

Nathan Feger 18.03.2009 20:53

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

Другие вопросы по теме