Вопрос

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

Это было полезно?

Решение

Они одно и то же... rmiregistry — это отдельная программа, которую можно запустить из командной строки или сценария, при этом LocateRegistry.createRegistry делает то же самое программно.

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

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

Если мы сначала запустим rmiregistry, RmiServiceExporter зарегистрируется в работающем rmiregistry.В этом случае нам необходимо установить для системного свойства java.rmi.server.codebase значение, в котором можно найти класс org.springframework.remoting.rmi.RmiIndictionWrapper_Stub.В противном случае, rmiserviceexporter не будет запущен и получил исключение "ClassNotFoundException Class не найден:org.springframework.remoting.rmi.RmiIndictionWrapper_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 в соответствии со своими потребностями.

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top