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




Это одно и то же ... rmiregistry - это отдельная программа, которую вы можете запустить из командной строки или скрипта, а LocateRegistry.createRegistry делает то же самое программно.
По моему опыту, для «настоящих» серверов вы захотите использовать rmiregistry, чтобы вы знали, что он всегда работает независимо от того, запущено ли клиентское приложение или нет. createRegistry очень полезен для тестирования, так как вы можете запускать и останавливать реестр из своего теста по мере необходимости.
Обновление: в документации сказано, что createRegistry экспортирует реестр на Localhost. Однако реестр также может принимать соединения от внешних интерфейсов.
@Eagle экспортирует реестр работает в на локальный хост. Это не означает, что он слушает только 127.0.0.1.
Если вы пишете автономное Java-приложение, вам нужно запустить свой собственный rmiregistry, но если вы пишете приложение J2EE, которое, очевидно, работает внутри контейнера J2EE, тогда вам нужно «LocateRegistry», поскольку он уже запущен на сервере приложений!
Не соответствует действительности и немотивирован. Возможно, вы захотите использовать LocateRegistry и в отдельной программе.
Если вы используете Spring для экспорта своих служб RMI, он автоматически запускает реестр, если он еще не запущен. См. RmiServiceExporter
Можете ли вы отредактировать это, чтобы включить ссылку на документацию по этой функции?
Если мы сначала запустим 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 в соответствии с вашими потребностями.
Есть ли способ для createRegistry работать с интерфейсом помимо localhost?