RMI即Remote Method Invocation,远程方法调用,一种计算机之间利用远程对象互相调用实现双方通讯的一种通讯机制。使用这种机制,某一台计算机上的对象可以调用另外一台计算机上的对象来获取远程数据,原先的程序在同一操作系统的方法调用,变成了不同操作系统之间程序的方法调用!在Hessian章节中也大致讲解了远程调用相关的知识,再给大家举个形象一点的例子,比如你有一台支持java的手机 还有一台台式机 手机上又一个非常复杂的运算   如果用手机来计算的话可能需要很长时间 不过如果用台式机的话几秒就能算出结果,这个时候就是rmi大显神通的时候 使用rmi从手机发送请求 然后交给台式机计算 然后台式机返回计算后的结果,这就是在不同的机器上面不同的JVM中实现了方法的远程调用!前面我们使用了Hessian,它是要部署在服务器里面才能运行的,并且它还需要辅助的jar包支持,下面我们来看一下java里面自己支持的RMI,它是最原始的远程方法调用,服务可以是BS、也可以是CS平台!下面来学习学习吧:

1、新建一个java工程(RMIServer),跟Hessian一样,编写我们的实体类和创建远程接口和相应的方法:

实体类,因为要进行远程传输,所以必须实现Serializable接口:

package com.server.bean; 
                       
import java.io.Serializable; 
                       
/**
 * 服务建立一个Model层,注意因为此对象需要现实进行远程传输,所以必须继承Serializable
 * @author harderxin
 *
 */ 
public class User implements Serializable{ 
                           
    /**
     * 
     */ 
    private static final long serialVersionUID = 7175134832651443717L; 
    //用户编号 
    private int id; 
    //用户名 
    private String userName; 
    //密码 
    private String password; 
                       
    public int getId() { 
        return id; 
    } 
                       
    public void setId(int id) { 
        this.id = id; 
    } 
                       
    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; 
    } 
                           
    public User(int id, String userName, String password) { 
        super(); 
        this.id = id; 
        this.userName = userName; 
        this.password = password; 
    } 
                       
    @Override 
    public int hashCode() { 
        final int prime = 31; 
        int result = 1; 
        result = prime * result + id; 
        result = prime * result 
                + ((password == null) ? 0 : password.hashCode()); 
        result = prime * result 
                + ((userName == null) ? 0 : userName.hashCode()); 
        return result; 
    } 
                       
    @Override 
    public boolean equals(Object obj) { 
        if (this == obj) 
            return true; 
        if (obj == null) 
            return false; 
        if (getClass() != obj.getClass()) 
            return false; 
        User other = (User) obj; 
        if (id != other.id) 
            return false; 
        if (password == null) { 
            if (other.password != null) 
                return false; 
        } else if (!password.equals(other.password)) 
            return false; 
        if (userName == null) { 
            if (other.userName != null) 
                return false; 
        } else if (!userName.equals(other.userName)) 
            return false; 
        return true; 
    } 
}

创建远程接口和相应的方法,需要继承java中的Remote

package com.server.service; 
                   
import java.rmi.Remote; 
import java.rmi.RemoteException; 
import java.util.List; 
import com.server.bean.User; 
                   
//该类为远程调用接口,必须继承Remote类 
public interface UserService extends Remote{ 
                       
    public List<User> getUser()throws RemoteException; 
                       
}

创建远程接口实现类,实现类需要继承java中的UnicastRemoteObject

package com.server.service.impl; 
               
import java.rmi.RemoteException; 
import java.rmi.server.UnicastRemoteObject; 
import java.util.ArrayList; 
import java.util.List; 
               
import com.server.bean.User; 
import com.server.service.UserService; 
               
/**
 * 建立UserServiceImpl实现远程接口,
 * 注意此为远程对象实现类,需要继承UnicastRemoteObject
 * @author dell
 *
 */ 
public class UserServiceImpl extends UnicastRemoteObject implements UserService{ 
               
    /**
     * 
     */ 
    private static final long serialVersionUID = -4329943273988736513L; 
               
    public UserServiceImpl() throws RemoteException { 
        super(); 
    } 
               
    public List<User> getUser() throws RemoteException{ 
        //我们可以在这个方法中与数据库打交道 
        List<User> list=new ArrayList<User>(); 
        list.add(new User(1,"Mary","123456")); 
        list.add(new User(2,"Jack","236547")); 
        list.add(new User(3,"Joy","362541")); 
        return list; 
    } 
}

2、编写我们的服务端启动类,注册通讯端口和通讯路径,能够让我们的客户端进行访问:

package com.server.start; 
           
import java.rmi.Naming; 
import java.rmi.registry.LocateRegistry; 
           
import com.server.service.UserService; 
import com.server.service.impl.UserServiceImpl; 
           
public class Server { 
    public static void main(String[] args) { 
        try { 
            UserService userService=new UserServiceImpl(); 
            //注册通讯端口 
            LocateRegistry.createRegistry(8081); 
            //注册通讯路径 
            Naming.rebind("rmi://127.0.0.1:8081/UserService", userService); 
            System.out.println("server start....."); 
        } catch (Exception e) { 
            e.printStackTrace(); 
        } 
    } 
           
}

执行main函数,我们的服务即启动了!将接口类UserService和实体类User打成jar包,放到我们的客户端中,让客户端去访问调用,或者也可以在客户端编写和服务端接口、实体一样的类(包名称也要相同,不建议这样做)

下面开始编写我们的客户端进行访问

3、新建一个java工程(RMIClient),导入从服务端打的jar包,编写我们的测试类:

package com.server.start; 
       
import java.rmi.Naming; 
import java.util.List; 
       
import com.server.bean.User; 
import com.server.service.UserService; 
       
public class ClientTest { 
    public static void main(String[] args) { 
        try { 
            //调用远程对象,注意RMI路径与接口必须与服务器配置一致   
            UserService userService=(UserService)Naming.lookup("rmi://127.0.0.1:8081/UserService"); 
            //执行服务端方法 
            List<User> users=userService.getUser(); 
            //遍历输出 
            for(User user:users){ 
                System.out.println("id="+user.getId()+",name="+user.getUserName()+",pwd="+user.getPassword()); 
            } 
        } catch (Exception e) { 
            e.printStackTrace(); 
        } 
    } 
       
}

运行测试类,得到结果:

id=1,name=Mary,pwd=123456
 id=2,name=Jack,pwd=236547
 id=3,name=Joy,pwd=362541


这样,我们就实现了远程方法的调用,我们也可以把这个测试类放在另一台机器上面进行测试,只要我们把客户端的路径和服务器配置一致,就能得到我们相应的结果,我们的客户端不做相应的逻辑处理,只是用来显示就ok了,把那些个逻辑就交给服务端去处理吧,哈哈.....


这里只是简单的讲解了java里面的RMI以及它的一些用法,至于原理和更加深入的探索,就到网上去做更多的了解吧!