CodeGym /Java Blog /Random /Java RMI
John Squirrels
Antas
San Francisco

Java RMI

Nai-publish sa grupo
Hi! Ngayon ay isasaalang-alang natin ang isang medyo kawili-wiling paksa: Java RMI. Ito ay kumakatawan sa Remote Method Invocation. Maaari mong gamitin ang RMI upang payagan ang dalawang programa na makipag-usap sa isa't isa, kahit na sila ay nasa magkaibang mga computer. Astig ba yan? :) At hindi ito napakahirap gawin! Sa aralin ngayon, susuriin natin ang mga elemento ng pakikipag-ugnayan ng RMI at malalaman kung paano ito i-configure. Ang unang bagay na kailangan namin ay isang kliyente at isang server. Hindi talaga namin kailangan na sumisid ng malalim sa terminolohiya ng computer. Pagdating sa RMI, dalawang programa lang ito. Ang isa sa kanila ay magsasama ng isang bagay, at ang isa ay tatawag ng mga pamamaraan sa bagay na iyon. Mga paraan ng pagtawag sa isang bagay na umiiral sa ibang programa — ngayon ay isang bagay na hindi pa namin nagagawa! Panahon na upang subukan ito! :) Para maiwasang magulo, let' s panatilihing simple ang aming programa. Sa pangkalahatan, ang isang server ay nagsasagawa ng ilang mga kalkulasyon na hiniling ng isang kliyente. At gayon din ang mangyayari sa atin. Ang aming server ay magiging isang simpleng calculator program. Ito ay magkakaroon lamang ng isang paraan:multiply() . Magpaparami ito ng dalawang numero na ipinadala dito ng programa ng kliyente, at pagkatapos ay ibabalik ang resulta. Una sa lahat, kailangan namin ng isang interface:

import java.rmi.Remote;
import java.rmi.RemoteException;

public interface Calculator extends Remote {

   int multiply(int x, int y) throws RemoteException;
}
Bakit kailangan natin ng interface? Dahil umaasa ang RMI sa paggawa ng mga proxy, na pinag-aralan mo sa mga nakaraang aralin . Tulad ng malamang na naaalala mo, nakikipagtulungan kami sa mga proxy sa pamamagitan ng mga interface, hindi mga klase. Mayroong 2 mahalagang kinakailangan para sa aming interface!
  1. Dapat itong pahabain ang Remote interface.
  2. Ang lahat ng mga pamamaraan nito ay dapat magtapon ng RemoteException (hindi ito awtomatikong gagawin ng IDE - kailangan mong idagdag ito nang manu-mano!).
Ngayon kailangan naming lumikha ng isang klase ng server na nagpapatupad ng aming interface ng Calculator . RMI sa pagsasanay - 2Dito, masyadong, ang lahat ay medyo simple:

import java.rmi.RemoteException;

public class RemoteCalculationServer implements Calculator {

   @Override
   public int multiply(int x, int y) throws RemoteException {
       return x*y;
   }

}
Wala talagang anumang bagay na maikomento dito :) Ngayon ay kailangan nating magsulat ng isang server program na magko-configure at magpapatakbo ng ating calculator object. Magiging ganito ang hitsura:

import java.rmi.AlreadyBoundException;
import java.rmi.Remote;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;

public class ServerMain {

   public static final String UNIQUE_BINDING_NAME = "server.calculator";

   public static void main(String[] args) throws RemoteException, AlreadyBoundException, InterruptedException {

       final RemoteCalculationServer server = new RemoteCalculationServer();

       final Registry registry = LocateRegistry.createRegistry(2732);

       Remote stub = UnicastRemoteObject.exportObject(server, 0);
       registry.bind(UNIQUE_BINDING_NAME, stub);

       Thread.sleep(Integer.MAX_VALUE);

   }
}
Alamin natin ito :) Sa unang linya, ipinapahayag namin ang ilang String variable:

public static final String UNIQUE_BINDING_NAME = "server.calculator";
Ang string na ito ay ang natatanging pangalan ng remote na bagay. Ginagamit ng aming client program ang pangalang ito upang mahanap ang aming server: makikita mo ito sa ibang pagkakataon. Susunod, nilikha namin ang aming calculator object:

final RemoteCalculationServer server = new RemoteCalculationServer();
Malinaw ang lahat dito. Ano ang susunod na mas kawili-wili:

final Registry registry = LocateRegistry.createRegistry(2732);
Ang Registry object na ito ay isang registry ng mga malalayong bagay. Ito ay mga bagay na maaaring ma-access ng ibang mga programa nang malayuan :) Ipinasa namin ang numerong 2732 sa LocateRegistry.createRegistry() na pamamaraan. Ito ang port number — isang natatanging numero na gagamitin ng ibang mga program para mahanap ang aming object registry (muli, makikita mo ito sa ibaba). Paglipat pakanan... Tingnan natin kung ano ang mangyayari sa susunod na linya:

Remote stub = UnicastRemoteObject.exportObject(server, 0);
Lumilikha kami ng stub sa linyang ito. Isang stub ang bumalot sa buong remote na tawag. Maaari mong isaalang-alang ito ang pinakamahalagang elemento ng RMI. Ano ang ginagawa nito?
  1. Natatanggap nito ang lahat ng impormasyon tungkol sa isang malayuang tawag ng ilang paraan.
  2. Kung ang pamamaraan ay may mga parameter, ang stub ay magde-deserialize sa kanila. Bigyang-pansin ang puntong ito! Ang mga argumento na ipinapasa mo sa malayuang tinatawag na mga pamamaraan ay dapat na serializable (pagkatapos ng lahat, sila ay ipapadala sa network). Wala itong problema sa amin — nagpapadala lang kami ng mga numero. Ngunit kung nagpapadala ka ng mga bagay, huwag kalimutan ang kinakailangang ito!
  3. Pagkatapos nito, tinawag ng stub ang nais na paraan.
Ipinapasa namin ang object ng calculator server namin sa UnicastRemoteObject.exportObject() method. Ito ay kung paano namin ginagawang posible na malayuang tawagan ang mga pamamaraan nito. May isang bagay na lang na dapat gawin:

registry.bind(UNIQUE_BINDING_NAME, stub);
"Inirerehistro" namin ang aming stub sa remote object registry sa ilalim ng pangalang ginawa namin sa pinakadulo simula. Ngayon ay mahahanap na ito ng kliyente! Marahil ay napansin mo na inilagay namin sa dulo ang pangunahing thread ng programa:

Thread.sleep(Integer.MAX_VALUE);
Kailangan lang namin ang server na tumakbo nang mahabang panahon. Sa IDE, sabay-sabay nating ilulunsad ang dalawang pangunahing() na pamamaraan: una, ang pangunahing() na pamamaraan ng server (sa klase ng ServerMain , na naisulat na natin), at pangalawa, ang pangunahing() na pamamaraan ng kliyente (sa klase ng ClientMain , na isusulat namin sa ibaba). Mahalagang hindi na-terminate ang server program habang sinisimulan natin ang client, kaya pinatulog na lang natin ito ng mahabang panahon. Sa anumang kaganapan, ito ay patuloy na tatakbo :) Ngayon ay maaari na nating patakbuhin ang pangunahing() na pamamaraan ng aming server. Hayaan itong tumakbo at hintayin ang client program na tumawag ng ilang paraan :) Ngayon ay isulat natin ang client program! Magpapadala ito ng mga numero sa aming server para sa pagpaparami.

import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;

public class ClientMain {

   public static final String UNIQUE_BINDING_NAME = "server.calculator";

   public static void main(String[] args) throws RemoteException, NotBoundException {

       final Registry registry = LocateRegistry.getRegistry(2732);

       Calculator calculator = (Calculator) registry.lookup(UNIQUE_BINDING_NAME);

       int multiplyResult = calculator.multiply(20, 30);

       System.out.println(multiplyResult);
   }
}
Mukhang simple lang. Ngunit ano ang nangyayari dito? Una, dapat malaman ng kliyente ang natatanging pangalan ng bagay na ang mga pamamaraan ay tatawagin nito nang malayuan. Alinsunod dito, sa programa ng kliyente, nilikha namin ang pampublikong static na panghuling String UNIQUE_BINDING_NAME = "server.calculator"; variable. Susunod, sa pangunahing() na pamamaraan, nakakakuha kami ng access sa rehistro ng mga malalayong bagay. Upang gawin ito, kailangan naming tawagan ang LocateRegistry.getRegistry() na paraan at ipasa ang port number na ginamit upang likhain ang aming registry sa ServerMain program (port 2732; ang numerong ito ay halimbawa lamang — maaari mong subukang gumamit ng ibang numero):

final Registry registry = LocateRegistry.getRegistry(2732);
Ngayon kailangan lang nating makuha ang ninanais na bagay mula sa pagpapatala! Madali lang ito, dahil alam natin ang kakaibang pangalan nito!

Calculator calculator = (Calculator) registry.lookup(UNIQUE_BINDING_NAME);
Bigyang-pansin ang uri ng paghahagis. Inihagis namin ang natanggap na bagay sa interface ng Calculator , hindi sa klase ng RemoteCalculationServer . Tulad ng sinabi namin sa simula ng aralin, umaasa ang RMI sa isang proxy, kaya ang mga malalayong tawag ay magagamit lamang para sa mga pamamaraan ng isang interface, hindi sa mga pamamaraan ng isang klase. Sa wakas, malayuan naming tinatawag ang multiply() na paraan sa aming bagay at ilalabas ang resulta sa console.

int multiplyResult = calculator.multiply(20, 30);
System.out.println(multiplyResult);
Ang pangunahing() na pamamaraan ng klase ng ServerMain ay tumatakbo nang mahabang panahon. Ngayon ay oras na upang patakbuhin ang pangunahing() na pamamaraan sa programa ng kliyente ( ClientMain )! Output ng console:

600
Ayan yun! Ginawa ng aming programa (dalawang programa, talaga!) ang dapat gawin :) Kung mayroon kang oras at pagnanais, maaari mo itong pagandahin nang kaunti. Halimbawa, gawin ang calculator na suportahan ang apat na karaniwang pagpapatakbo ng aritmetika, at ipasa ang mga numero hindi bilang mga primitive na uri, ngunit bilang CalculationInstance(int x, int y) na mga bagay. Magkita-kita tayo sa susunod na aralin! :)
Mga komento
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION