Java RMI, интерфейс публикуется как удаленный на веб-сервере, в то время как он не должен

#java #rmi #serializable

#java #rmi #сериализуемый

Вопрос:

У меня неприятная проблема, но сначала позвольте мне объяснить контекст.

Проект — это всего лишь простой проект, поэтому я знакомлюсь с RMI. Проект представляет собой сервер фондового рынка и клиент, который извлекает данные о фондах с сервера.

Я разделил проект на 3 java-проекта. Сервер (имеющий MockStockMarket и Fund), клиент (имеющий классы GUI и класс для взаимодействия с сервером: BannerController) и проект с интерфейсами, которые нужны как клиенту, так и серверу (IStockMarket и iFund).

Я хочу, чтобы мой bannerController взаимодействовал с биржевым рынком, чтобы bannercontroller получал средства. Это делается с помощью getFunds() : ArrayList .

Как вы можете видеть, StockMarket должен быть удаленным, а Фонд должен быть сериализуемым.

Проблема в том, что по какой-то причине, когда я использую следующий код:

 IStockMarket market = new MockStockMarket();
Naming.rebind("rmi://localhost/StockMarket", market);
  

Как IStockMarket (как предполагалось), так И iFund (не как предполагалось) становятся удаленными. Это не то, чего я хочу.

Для справки: Fund реализует iFund, который расширяет Serializable (то есть ничего удаленного) , а MockStockMarket расширяет UnicastRemoteObject и реализует IStockMarket, который расширяет Remote.

Вот скриншот веб-сервера, публикующего оба интерфейса: http://imageshack.us/m/194/4755/rmibothinterfacespublis.png .

Для исходного кода:https://rapidshare.com/files/2085773800/stockmarket.zip

Ответ №1:

Привязка службы RMI к порту отличается от привязки файлов веб-сервера, публикующего файлы. На скриншоте, который вы прикрепили, показано, что ваш IStockMarket.class и IFund.class файлы предоставляются как HTTP-ресурсы, которые не имеют ничего общего с «привязкой» службы RMI. Не стесняйтесь добавлять больше деталей к вопросу, если моя интерпретация здесь неверна, и я попытаюсь ответить на них.

Комментарии:

1. Ну, когда я запускаю свой сервер, веб-сервер показывает мне, что эти 2 класса открыты. Но одного iFund не должно быть. Также, когда клиент получает объект iFund, он пытается использовать его как удаленный объект вместо простой десериализации.

Ответ №2:

Как IStockMarket (как предполагалось), так И iFund (не как предполагалось) становятся удаленными.

Нет, они этого не делают. Объекты «становятся удаленными» только при экспорте, а интерфейсы вообще не «становятся удаленными». Клиенту требуется iFund, предположительно, потому, что он отображается в интерфейсе IStockMarket. Похоже, вы используете функцию codebase. С точки зрения кодовой базы реестр тоже является клиентом. Итак, реестр загружен IFund.class и IStockMarket.class. Это не приводит к тому, что iFund «становится удаленным» каким-либо образом.

Ответ №3:

Хорошо, я нашел это на сайте oracle:http://download.oracle.com/javase/tutorial/rmi/implementing.html .

Веб-сервер публикует мой интерфейс iFund (не удаленный), потому что он передается через метод RMI. Моему клиенту нужен iFund для использования переданного объекта. Я думал, этого было достаточно для работы RMI.

Чего я не знал, так это того, что клиенту ТАКЖЕ необходимо загрузить реализацию класса, чтобы он мог десериализовать объект и использовать методы скопированного объекта. Чтобы это сработало, вы должны использовать securitymanager на стороне клиента. Что очень просто:

 if (System.getSecurityManager() == null) 
{
    System.setSecurityManager(new SecurityManager());
}
  

Комментарии:

1. Веб-сервер ничего не «публикует». Он возвращает его из вашей кодовой базы, куда вы его поместили, в ответ на запрос GET, выданный клиентом кодовой базы RMI.

2. Это было то, что вы опубликовали файлы, поместив их в кодовую базу. Они требуются там для удовлетворения загрузки класса удаленного интерфейса. Не похоже, что у вас есть какая-либо альтернатива.