RMI(即Remote Method Invoke 远程方法调用)。在Java中,只要一个类extends了java.rmi.Remote接口,即可成为存在于服务器端的远程对象,供客户端访问并提供一定的服务。JavaDoc描述:Remote 接口用于标识其方法可以从非本地虚拟机上调用的接口。任何远程对象都必须直接或间接实现此接口。只有在“远程接口”(扩展 java.rmi.Remote 的接口)中指定的这些方法才可远程使用。
目前简单根据网上的代码例子在本地上测试了一把,明白了java中可以通过哪种方式实现远程方法的调用,当然了,不同的java版本,可能在远程方法的调用的细节上会有些不同。网上提供的是jdk1.6版本的代码,我采用jdk1.8同样可以能够成功运行。
网上是采用创建两个工程将服务端代码和客户端代码分开运行,在我的代码中就是简单的将所有的代码放在一起。其实测试起来没多大区别。只是有点需要强调。在服务端传递到客户端的远程对象,在客户端也得有对应的.java文件或者.class文件。
服务端代码:
创建一个接口,这个接口是你要向client端开放的方法定义
package com.rmi.test;
import java.rmi.Remote;
import java.rmi.RemoteException;
/**
* Created by jiangchangwei on 2017/8/11.
*/
public interface UserManagerInterface extends Remote {
public String getUserName() throws RemoteException;
public Account getAdminAccount() throws RemoteException;
}
定义一个类,这个对象怎样通过序列化方式传递到客户端
package com.rmi.test;
import java.io.Serializable;
/**
* Created by jiangchangwei on 2017/8/11.
*/
public class Account implements Serializable, Cloneable{
/**
*
*/
private static final long serialVersionUID = -1858518369668584532L;
private String username;
private String password;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
需要实现你已经开放的接口
package com.rmi.test;
import java.rmi.RemoteException;
/**
* Created by jiangchangwei on 2017/8/11.
*/
public class UserManagerImpl implements UserManagerInterface {
public UserManagerImpl() throws RemoteException {
//super();
// TODO Auto-generated constructor stub
//UnicastRemoteObject.exportObject(this);
}
/**
*
*/
private static final long serialVersionUID = -3111492742628447261L;
public String getUserName() throws RemoteException {
// TODO Auto-generated method stub
return "Tommy Lee";
}
public Account getAdminAccount() throws RemoteException {
// TODO Auto-generated method stub
Account account=new Account();
account.setUsername("admin");
account.setPassword("admin");
return account;
}
}
定义一个主程序入口,注册你已经实现的RMI接口,包括开放端口等。
package com.rmi.test;
import java.rmi.AlreadyBoundException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;
/**
* Created by jiangchangwei on 2017/8/11.
*/
public class Entry {
public static void main(String []args) throws AlreadyBoundException, RemoteException {
UserManagerImpl userManager=new UserManagerImpl();
UserManagerInterface userManagerI=(UserManagerInterface) UnicastRemoteObject.exportObject(userManager,0);
// Bind the remote object's stub in the registry
Registry registry = LocateRegistry.createRegistry(2001);
registry.rebind("userManager", userManagerI);
System.out.println("server is ready");
}
}
客户端代码:
client调用server端方法
package com.rmi.test;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
/**
* Created by jiangchangwei on 2017/8/11.
*/
public class Entry2 {
public static void main(String []args){
try {
Registry registry = null;
registry = LocateRegistry.getRegistry("localhost",2001);
UserManagerInterface userManager = (UserManagerInterface) registry.lookup("userManager");
System.out.println(""+userManager.getAdminAccount().getUsername()
+userManager.getAdminAccount().getPassword());
} catch (RemoteException e) {
e.printStackTrace();
}catch(NotBoundException e) {
e.printStackTrace();
}
}
}
总结:平常自己开发时远程方法调用用到挺少的,通过本博客,主要是为了记录远程方法调用的方式。远程方法调用给我的感觉是,将一些序列化的对象放到一个仓库中,然后我们可以在仓库中读取这些对象,然后进行相应的操作。