其他
Java教程-Java RMI(远程方法调用)
理解存根和骨架
RMI使用存根和骨架对象进行与远程对象的通信。
存根
存根是一个对象,充当客户端的网关。所有的出站请求都通过它路由。它位于客户端,并代表远程对象。当调用者在存根对象上调用方法时,它执行以下任务:
1.它与远程虚拟机(JVM)建立连接。
专属福利
骨架
它读取远程方法的参数。 它在实际的远程对象上调用方法。 它将结果写入并传输(编组)给调用者。
理解分布式应用程序的要求
如果应用程序执行以下任务之一,它可以成为分布式应用程序。
应用程序需要定位远程方法。 应用程序需要与远程对象进行通信。 应用程序需要加载对象的类定义。
Java RMI示例
创建远程接口。 提供远程接口的实现。 使用rmic工具编译实现类并创建存根和骨架对象。 使用rmiregistry工具启动注册表服务。 创建并启动远程应用程序。 创建并启动客户端应用程序。
RMI示例
在这个示例中,我们按照6个步骤创建和运行了RMI应用程序。客户端应用程序只需要两个文件:远程接口和客户端应用程序。在RMI应用程序中,客户端和服务器都与远程接口进行交互。客户端应用程序调用代理对象上的方法,RMI将请求发送到远程JVM。返回值被发送回代理对象,然后传递给客户端应用程序。
import java.rmi.*;
public interface Adder extends Remote {
public int add(int x, int y) throws RemoteException;
}
2) 提供远程接口的实现
要么扩展UnicastRemoteObject类, 要么使用UnicastRemoteObject类的exportObject()方法。
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;
}
}
3) 使用rmic工具创建存根和骨架对象
rmic AdderRemote
4) 通过rmiregistry工具启动注册表服务
现在使用rmiregistry工具启动注册表服务。如果不指定端口号,它将使用默认端口号。在这个示例中,我们使用端口号5000。
rmiregistry 5000
5) 创建并运行服务器应用程序
现在需要在服务器进程中托管RMI服务。Naming类提供了获取和存储远程对象的方法。Naming类提供了5个方法。
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);
}
}
}
6) 创建并运行客户端应用程序
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) {
}
}
}
这个RMI示例的输出
带有数据库的RMI应用程序的实际示例
考虑一个场景,有两个在不同机器上运行的应用程序。假设MachineA位于美国,MachineB位于印度。MachineB想要获取MachineA应用程序的所有客户列表。
让我们按照以下步骤开发RMI应用程序。
1) 创建表格
package cn.javatiku;
public class Customer implements java.io.Serializable{
private int acc_no;
private String firstname,lastname,email;
private float amount;
//getters and setters
}
package cn.javatiku;
import java.rmi.*;
import java.util.*;
interface Bank extends Remote{
public List<Customer> getCustomers() throws RemoteException;
}
3) 创建提供Remote接口实现的类
package cn.javatiku;
import java.rmi.*;
import java.rmi.server.*;
import java.sql.*;
import java.util.*;
class BankImpl extends UnicastRemoteObject implements Bank{
BankImpl() throws RemoteException{}
public List<Customer> getCustomers(){
List<Customer> list=new ArrayList<Customer>();
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;
}
}
4) 使用rmic工具编译类并使用rmiregistry工具启动注册表服务
5) 创建并运行服务器
package cn.javatiku;
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 cn.javatiku;
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<Customer> list=b.getCustomers();
for(Customer c:list){
System.out.println(c.getAcc_no()+" "+c.getFirstname()+" "+c.getLastname()
+" "+c.getEmail()+" "+c.getAmount());
}
}
}
我就知道你会点赞+“在看”