JavaRush /Blogue Java /Random-PT /RMI: prática de uso

RMI: prática de uso

Publicado no grupo Random-PT
Olá! Hoje veremos um tópico bastante interessante - RMI . Isso significa Invocação de Método Remoto . RMI: prática de uso - 1Com o RMI, você pode ensinar dois programas a se comunicarem, mesmo que estejam em computadores diferentes. Parece legal? :) Mas não é tão difícil de fazer! Na palestra de hoje entenderemos em que partes consiste a interação RMI e como configurá-la. A primeira coisa que precisamos é de um cliente e um servidor . Você não precisa se aprofundar muito na terminologia informática. No caso do RMI, são simplesmente dois programas. Um deles conterá algum objeto, e o segundo chamará métodos deste objeto. Chamar métodos de um objeto em um programa que está localizado em outro programa - nunca fizemos isso antes! É hora de experimentar! :) Para não se afogar na selva, deixe nosso programa ser simples. Em geral, os servidores costumam realizar algum tipo de cálculo que o cliente solicita. Será o mesmo para nós. Teremos um programa de calculadora simples como servidor. Ela terá apenas um método - multiply(). Ele multiplicará os dois números enviados pelo programa cliente e retornará o resultado. Primeiro de tudo precisamos de uma interface:
import java.rmi.Remote;
import java.rmi.RemoteException;

public interface Calculator extends Remote {

   int multiply(int x, int y) throws RemoteException;
}
Por que precisamos de uma interface? O fato é que o trabalho do RMI se baseia na criação de proxies, que você estudou em uma das palestras anteriores . E o trabalho com proxies, como você provavelmente se lembra, é realizado precisamente no nível das interfaces, não nas classes. Existem 2 requisitos importantes para nossa interface!
  1. Deve herdar a interface do token remoto.
  2. Todos os seus métodos devem lançar uma RemoteException (isso não é feito automaticamente no IDE, você tem que escrevê-lo manualmente!).
Agora precisamos criar uma classe de servidor que implementará nossa interface Calculator. RMI: prática de uso - 2Tudo aqui também é bastante simples:
import java.rmi.RemoteException;

public class RemoteCalculationServer implements Calculator {

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

}
Não há muito o que comentar aqui :) Agora precisamos escrever um programa de servidor que irá configurar e executar nossa classe de calculadora de servidor. Isso parecerá assim:
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);

   }
}
Vamos descobrir :) Na primeira linha criamos algum tipo de variável string:
public static final String UNIQUE_BINDING_NAME = "server.calculator";
Esta string é o nome exclusivo do objeto remoto . Com este nome o programa cliente poderá encontrar nosso servidor: você verá isso mais tarde. A seguir criamos nosso objeto calculadora:
final RemoteCalculationServer server = new RemoteCalculationServer();
Tudo está claro aqui. O seguinte é mais interessante:
final Registry registry = LocateRegistry.createRegistry(2732);
Essa coisa chamada Registro é um registro de objetos excluídos . “Excluídos” não no sentido de que os apagamos do computador, mas no fato de que os objetos deste registro podem ser acessados ​​​​remotamente a partir de outros programas :) LocateRegistry.createRegistry()Passamos para o método o número 2732. Este é o número da porta. Se você não sabe o que é uma porta, pode lê-la aqui , mas por enquanto basta lembrar que este é um número exclusivo pelo qual outros programas podem encontrar nosso registro de objetos (você também verá isso abaixo). Vamos continuar. Vamos ver o que acontece na próxima linha:
Remote stub = UnicastRemoteObject.exportObject(server, 0);
Nesta linha criamos um stub . Um stub encapsula todo o processo de chamada remota dentro de si. Pode-se dizer que este é o elemento mais importante do RMI. O que ela esta fazendo?
  1. Recebe todas as informações sobre uma chamada remota para um método.
  2. Se o método tiver parâmetros, o stub os desserializa. Preste atenção neste ponto! Os parâmetros que você passa aos métodos para chamadas remotas devem ser serializáveis ​​(afinal, eles serão transmitidos pela rede). Não temos esse problema - apenas transmitimos números. Mas se você transferir objetos, não se esqueça disso!
  3. Depois disso, ele chama o método desejado.
Passamos UnicastRemoteObject.exportObject()nosso objeto calculadora do servidor para o método. Desta forma tornamos possível chamar seus métodos remotamente. Só nos resta uma coisa a fazer:
registry.bind(UNIQUE_BINDING_NAME, stub);
Nós “registramos” nosso stub no registro de objeto remoto com o nome que criamos no início. Agora o cliente pode encontrá-lo! Você deve ter notado que no final colocamos o thread principal do programa em suspensão:
Thread.sleep(Integer.MAX_VALUE);
Só precisamos manter o servidor funcionando por muito tempo. Executaremos dois métodos no IDEa ao mesmo tempo main(): primeiro o do servidor (na classe que ServerMainjá escrevemos) e depois o do cliente (na classe ClientMainque escreveremos abaixo). É importante que o programa do servidor não fique inativo enquanto iniciamos o cliente, então simplesmente o colocamos em hibernação por um longo tempo. Ainda funcionará :) Agora podemos executar main()nosso método de servidor. Deixe-o rodar e espere o programa cliente chamar algum método :) Agora vamos escrever um programa cliente! Ele enviará números ao nosso servidor para multiplicar.
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);
   }
}
Ela parece descomplicada. O que está acontecendo aqui? Primeiro, o cliente deve estar ciente do nome exclusivo do objeto cujos métodos irá chamar remotamente. Portanto, no programa cliente também criamos uma variável, public static final String UNIQUE_BINDING_NAME = "server.calculator"; a seguir no método main()obtemos acesso ao registro de objetos remotos. Para isso, precisamos chamar o método LocateRegistry.getRegistry()e passar lá o número da porta na qual nosso registro foi criado no programa ServerMain - porta 2732 (esse número foi escolhido como exemplo, você pode tentar usar outro):
final Registry registry = LocateRegistry.getRegistry(2732);
Agora tudo o que precisamos fazer é obter o objeto desejado do registro! É fácil porque sabemos seu nome único!
Calculator calculator = (Calculator) registry.lookup(UNIQUE_BINDING_NAME);
Preste atenção ao tipo de fundição. Convertemos o objeto resultante em uma interface Calculatorem vez de em uma classe concreta RemoteCalculationServer . Como dissemos no início da palestra, o RMI é baseado no uso de um proxy, portanto a chamada remota está disponível apenas para métodos de interfaces, não para classes. No final, chamamos remotamente um método multiply()em nosso objeto e imprimimos o resultado no console.
int multiplyResult = calculator.multiply(20, 30);
System.out.println(multiplyResult);
Lançamos o método main()na classe ServerMainhá muito tempo, é hora de lançar o método main()no programa cliente ClientMain! Saída do console: 600 É isso aí! Nosso programa (mesmo dois!) Cumpriu com sucesso sua função :) Se você tiver tempo e vontade, pode diversificar um pouco. Por exemplo, certifique-se de que a calculadora suporta todas as quatro operações padrão, e não números, mas um objeto são passados ​​como parâmetros CalculationInstance(int x, int y). Como material adicional, você pode consultar artigos e exemplos - aqui: Nos vemos nas próximas aulas! :)
Comentários
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION