"Здрасти! И още една щастлива тема: RMI. RMI означава Remote Method Invocation . С други думи, RMI е механизъм, който позволява на обект от една Java машина да извиква методи на обекти от друга Java машина , дори ако те са на различна компютри, в различни страни or на различни страни на земното кълбо."

RMI - 1

"Уау! Това звучи страхотно."

„Да. Но ще се опитам само да ви дам общ преглед. С това, ако копаете твърде дълбоко, можете да се объркате от нюансите на това How работи.“

„Но ако не стигате до крайности, тогава RMI е не само много прост, но също така значително опростява живота на програмиста. За което му отдаваме дълбоко уважение.“

„Така че искаме един обект в Java програма да извика метод на обект, който е в друга Java програма. Независимо къде се изпълняват тези програми.“

"Нека разгледаме най-простия пример: когато и двете програми работят на един и същи компютър.  За да позволите на програмите да си взаимодействат през интернет, трябва да конфигурирате разрешенията на JVM , но ние няма да разгледаме това днес."

„В Java можете дистанционно да извиквате само методите на интерфейсите, не и класовете.“

„И така, имаме две програми. Как могат взаимно да си извикват методите?“

„Нека разгледаме ситуацията , в която една програма съдържа обект, а втора програма иска да извика методи на този обект. Нека наречем първата програма сървър, а втората — клиент.

„Първо ще дам примерен code и след това ще го анализираме.“

„И така, Howво ще направи нашата програма?“

"Хм. Е, за простота, програмата ще има един метод, който обръща низ, който й е предаден."

— Достатъчно просто.

„Добре, тогава да започваме:“

„Първо, имаме нужда от интерфейс, който ще задоволи нашите изисквания:“

Интерфейс за комуникация между програмите
interface Reverse extends Remote
{
 public String reverse(String str) throws RemoteException;
}

„Създадох обратен интерфейс и добавих към него интерфейс за отдалечен маркер, Howто и RemoteException. Може да възникнат неочаквани грешки, когато методът бъде извикан. Ако има такива, това изключение ще бъде хвърлено.“

„Сега трябва да напишем сървърен клас, който имплементира този интерфейс:“

Клас за сървъра
class ReverseImpl implements Reverse
{
 public String reverse(String str) throws RemoteException
 {
  return new StringBuffer(str).reverse().toString();
 }
}

„Разбирам. Ние обръщаме низа в този метод.“

— Да.

„Сега трябва да направим този обект извикан от друга програма. Ето How да го направите:“

Споделяне на обекти
public static final String UNIC_BINDING_NAME = "server.reverse";

public static void main(String[] args) throws Exception
{
 // Create an object to be accessible remotely.
 final ReverseImpl service = new ReverseImpl();

 // Create a registry of shared objects.
 final Registry registry = LocateRegistry.createRegistry(2099);
 // Create a stub for receiving remote calls.
 Remote stub = UnicastRemoteObject.exportObject(service, 0);
 // Register the stub in the registry.
 registry.bind(UNIC_BINDING_NAME, stub);

 // Put the main thread to sleep, or else the program will exit.
 Thread.sleep(Integer.MAX_VALUE);
}

— Ще обясня това ред по ред.

" В ред 1 съхраняваме уникално име (което сме измислor) за нашия отдалечен обект (обект, който е отдалечено достъпен) в променливата UNIC_BINDING_NAME.  Ако програмата прави няколко обекта достъпни, всеки трябва да има свое собствено уникално име. Нашият уникалното име на обекта е 'server.reverse'."

" На ред 6 създаваме ReverseImpl обект, който ще бъде достъпен от разстояние. Неговите методи ще бъдат извикани."

" На ред 9 създаваме специален обект, наречен регистър. Трябва да го използваме, за да регистрираме обектите, които споделяме. JVM ще взаимодейства с тях по-късно. 2099 е порт (уникален номер, който друга програма може да използва за достъп до нашия обектен регистър)."

„С други думи, за достъп до обект, трябва да знаете уникалния номер (порт) на регистъра на обекта и уникалното име на обекта и да имате същия интерфейс като този, реализиран от отдалечения обект.“

„Разбирам. Нещо като: обадете се по телефона (имате нужда от номер) и поискайте Бил (името на обект)?“

"Да. А сега да продължим."

" На ред 11  създаваме мъниче. Мъничето е специален обект, който получава информация за отдалеченото повикване, разопакова го, десериализира аргументите на метода и извиква необходимия метод. След това сериализира резултата or изключението, ако е имало такова , и го изпраща обратно на обаждащия се."

„Разбирам. Почти. Казахте, че „десериализира аргументите на метода“. Значи това означава, че аргументите на отдалечените методи трябва да могат да се сериализират?“

"Да. Как иначе бихте ги изпратor по мрежата? Вярно, има изключения, т.е. обекти, които се предават по референция, но днес няма да говорим за тях."

„Ще го кажем така: не можете да предавате обекти, които не могат да бъдат сериализирани, но ако наистина искате, тогава можете. Но това е болка, знаете ли.“

"ДОБРЕ."

— Тогава да продължим.

" На ред 13 ние регистрираме мъниче на нашия обект под уникално име в регистъра."

" На ред 16 приспиваме основната нишка. Всички отдалечени повиквания се обработват на отделни нишки. Важното е, че програмата работи. Така че просто приспиваме основната нишка тук. Това е."

"ДОБРЕ."

„Чудесно, тогава ето пример за клиент:“

Работа с отдалечен обект
public static final String UNIC_BINDING_NAME = "server.reverse";

public static void main(String[] args) throws Exception
{
 // Create a registry of shared objects
 final Registry registry = LocateRegistry.createRegistry(2099);

 // Get the object (actually, this is a proxy object)
 Reverse service = (Reverse) registry.lookup(UNIC_BINDING_NAME);

 // Call the remote method
 String result = service.reverse("Home sweet home.");
}

„Ще обясня този code ред по ред:“

" Ред 1  е уникалното име на отдалечения обект . То трябва да е едно и също Howто на клиента, така и на сървъра."

" В ред 6  създаваме « регистър на отдалечени обекти ». Неговият порт (2099) трябва да е същият като порта на регистъра за сървърното приложение.»

" На ред 9 получаваме обекта от системния регистър. Върнатият обект е прокси обект и се преобразува в интерфейс. Интерфейсът трябва да наследи интерфейса на отдалечения маркер."

" На ред 12 извикваме методите на интерфейса, сякаш обектът е създаден в рамките на същата програма. Няма разлика."

„Готино! Сега мога да пиша разпределени applications. Или игри като Battleship за Android.“

„Не смей, Амиго! Операционната система Android беше забранена през 27-ми век след третия си опит да превземе света. Роботите нямат ниHowъв достъп до нея. Няма начин да те откъснат от нея . Ще започнете да тичате наоколо и да крещите: «Убийте всички хора!»

"Хмм. Добре. Но все пак ще трябва да попитам Диего. Никога не се знае, може би той ще има да каже нещо интересно за това."

— Тогава иди и го попитай. Добре, добре, до утре.

„Чао, Риши. Благодаря за интересния урок.“