📅  最后修改于: 2020-10-13 06:55:35             🧑  作者: Mango
RMI(远程方法调用)是一种API,提供了一种在Java中创建分布式应用程序的机制。 RMI允许对象调用在另一个JVM中运行的对象上的方法。
RMI使用两个对象存根和框架在应用程序之间提供远程通信。
RMI使用存根和骨架对象与远程对象进行通信。
远程对象是可以从另一个JVM调用其方法的对象。让我们了解存根和骨架对象:
存根是一个对象,充当客户端的网关。所有传出的请求都通过它路由。它位于客户端,代表远程对象。当调用方调用存根对象上的方法时,它将执行以下任务:
骨架是一个对象,充当服务器端对象的网关。所有传入的请求都通过它路由。当框架接收到传入的请求时,它将执行以下任务:
如果有任何应用程序执行这些任务,则可以是分布式应用程序。
RMI应用程序具有所有这些功能,因此称为分布式应用程序。
给出了6个编写RMI程序的步骤。
在此示例中,我们遵循了所有6个步骤来创建和运行rmi应用程序。客户端应用程序仅需要两个文件,远程接口和客户端应用程序。在rmi应用程序中,客户端和服务器都与远程接口进行交互。客户端应用程序调用代理对象上的方法,RMI将请求发送到远程JVM。返回值被发送回代理对象,然后发送回客户端应用程序。
要创建远程接口,请扩展Remote接口并使用远程接口的所有方法声明RemoteException。在这里,我们正在创建一个扩展Remote接口的Remote接口。只有一个名为add()的方法,它声明RemoteException。
import java.rmi.*;
public interface Adder extends Remote{
public int add(int x,int y)throws RemoteException;
}
现在提供远程接口的实现。为了提供Remote接口的实现,我们需要
import java.rmi.*;
import java.rmi.server.*;
public class AdderRemote extends UnicastRemoteObject implements Adder{
AdderRemote()throws RemoteException{
super();
}
public int add(int x,int y){return x+y;}
}
下一步是使用rmi编译器创建存根和骨架对象。 Rmic工具调用RMI编译器并创建存根和骨架对象。
rmic AdderRemote
现在,通过使用rmiregistry工具启动注册表服务。如果未指定端口号,它将使用默认端口号。在此示例中,我们使用端口号5000。
rmiregistry 5000
现在,rmi服务需要托管在服务器进程中。 Naming类提供了获取和存储远程对象的方法。 Naming类提供5种方法。
public static java.rmi.Remote lookup(java.lang.String) throws java.rmi.NotBoundException, java.net.MalformedURLException, java.rmi.RemoteException; | It returns the reference of the remote object. |
public static void bind(java.lang.String, java.rmi.Remote) throws java.rmi.AlreadyBoundException, java.net.MalformedURLException, java.rmi.RemoteException; | It binds the remote object with the given name. |
public static void unbind(java.lang.String) throws java.rmi.RemoteException, java.rmi.NotBoundException, java.net.MalformedURLException; | It destroys the remote object which is bound with the given name. |
public static void rebind(java.lang.String, java.rmi.Remote) throws java.rmi.RemoteException, java.net.MalformedURLException; | It binds the remote object to the new name. |
public static java.lang.String[] list(java.lang.String) throws java.rmi.RemoteException, java.net.MalformedURLException; | It returns an array of the names of the remote objects bound in the registry. |
在此示例中,我们通过名称sonoo绑定了远程对象。
import java.rmi.*;
import java.rmi.registry.*;
public class MyServer{
public static void main(String args[]){
try{
Adder stub=new AdderRemote();
Naming.rebind("rmi://localhost:5000/sonoo",stub);
}catch(Exception e){System.out.println(e);}
}
}
在客户端,我们通过Naming类的lookup()方法获取存根对象,并在该对象上调用该方法。在此示例中,我们在同一台计算机上运行服务器和客户端应用程序,因此我们使用本地主机。如果要从另一台计算机访问远程对象,请将localhost更改为远程对象所在的主机名(或IP地址)。
import java.rmi.*;
public class MyClient{
public static void main(String args[]){
try{
Adder stub=(Adder)Naming.lookup("rmi://localhost:5000/sonoo");
System.out.println(stub.add(34,4));
}catch(Exception e){}
}
}
For running this rmi example,
1) compile all the java files
javac *.java
2)create stub and skeleton object by rmic tool
rmic AdderRemote
3)start rmi registry in one command prompt
rmiregistry 5000
4)start the server in another command prompt
java MyServer
5)start the client application in another command prompt
java MyClient
考虑一个场景,有两个应用程序在不同的机器上运行。假设MachineA和MachineB,machineA位于美国,而MachineB位于印度。 MachineB希望获取MachineA应用程序的所有客户的列表。
让我们按照以下步骤开发RMI应用程序。
首先,我们需要在数据库中创建表。在这里,我们正在使用Oracle10数据库。
package com.javatpoint;
public class Customer implements java.io.Serializable{
private int acc_no;
private String firstname,lastname,email;
private float amount;
//getters and setters
}
注意:客户类别必须是可序列化的。
package com.javatpoint;
import java.rmi.*;
import java.util.*;
interface Bank extends Remote{
public List getCustomers()throws RemoteException;
}
package com.javatpoint;
import java.rmi.*;
import java.rmi.server.*;
import java.sql.*;
import java.util.*;
class BankImpl extends UnicastRemoteObject implements Bank{
BankImpl()throws RemoteException{}
public List getCustomers(){
List list=new ArrayList();
try{
Class.forName("oracle.jdbc.driver.OracleDriver");
Connection con=DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:xe","system","oracle");
PreparedStatement ps=con.prepareStatement("select * from customer400");
ResultSet rs=ps.executeQuery();
while(rs.next()){
Customer c=new Customer();
c.setAcc_no(rs.getInt(1));
c.setFirstname(rs.getString(2));
c.setLastname(rs.getString(3));
c.setEmail(rs.getString(4));
c.setAmount(rs.getFloat(5));
list.add(c);
}
con.close();
}catch(Exception e){System.out.println(e);}
return list;
}//end of getCustomers()
}
package com.javatpoint;
import java.rmi.*;
public class MyServer{
public static void main(String args[])throws Exception{
Remote r=new BankImpl();
Naming.rebind("rmi://localhost:6666/javatpoint",r);
}}
package com.javatpoint;
import java.util.*;
import java.rmi.*;
public class MyClient{
public static void main(String args[])throws Exception{
Bank b=(Bank)Naming.lookup("rmi://localhost:6666/javatpoint");
List list=b.getCustomers();
for(Customer c:list){
System.out.println(c.getAcc_no()+" "+c.getFirstname()+" "+c.getLastname()
+" "+c.getEmail()+" "+c.getAmount());
}
}}