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();
            }
        }

    }

总结:平常自己开发时远程方法调用用到挺少的,通过本博客,主要是为了记录远程方法调用的方式。远程方法调用给我的感觉是,将一些序列化的对象放到一个仓库中,然后我们可以在仓库中读取这些对象,然后进行相应的操作。