1 、 RMI 主要构件:
服务器对象接口( server object interface ):是 java.rmi.Remote 接口的子接口,用来为服务器对象定义方法。
服务器的实现( server implementation ):是实现远程对象接口的一个类。
服务器对象( server object ):是服务器实现的一个实例。
RMI 注册处( RMI registry ):是注册远程对象并为本地对象提供命名服务的一个工具。
客户程序( client program ):是调用远程服务器对象的方法的一个程序。
服务器代理( server stub ):是位于客户主机的一个对象,其作用相当于远程服务器对象的一个代表。
服务器主架( server skeleton ):是位于服务器主机的一个对象,用于服务器代理与实际服务器对象的通信。
2 、 RMI 工作步骤:
a 、在 RMI 注册处注册一个服务器对象。
b 、客户从 RMI 注册处查找远程对象。
c 、一旦找到远程对象,就在客户中返回它的代理。
d 、远程对象可以像本地对象一样使用。客户和服务器之间的通信通过代理和主架处理。
JDK5 中,代理和主架可以自动生成。代理位于客户端主机,当客户调用服务器对象的一个方法时,实际调用的是封装在代理中的方法,代理再负责向服务器发送参数,接收来自服务器的结果并返回给客户。
而主架位于服务器端,与代理进行通信。接收来自客户的参数,把它们传输给服务器处理,并返回结果给代理。
在远程调用中,没有办法传递对象的引用,因为在一台机器上的地址对不同的 JVM 来说毫无意义。任何对象,只要它可以序列化,就可以用作远程调用的参数。代理将对象参数序列化、并发送到网络的流中,主架对流进行解读序列化,存到对象。
3 、客户是通过 RMI 注册处来定位远程对象的。 RMI 注册处为服务器注册对象以及为客户查找对象提供注册服务。 LocateRegistry 静态方法 getRegistry ()方法返回对 Registry 对象的引用。一旦获得 Registry 对象,就可以用 bind 、 rebind 方法与注册处中的唯一名称绑定,或者使用 lookup 方法定位对象。
4 、开发 RMI 应用程序简单步骤:
a 、定义服务器对象接口 : 必须是 java.rmi.Remote 接口的子接口,与 java.io.Serializable 一样, java.rmi.Remote 接口也是一个标记接口,不包含任何常数和方法,仅用来标记远程对象。
public interface ServerInterface extends Remote {
// 定义各种服务器端的方法
public void service() throws RemoteException;// 必须抛出的异常
}
b 、定义服务器实现类:必须扩展 java.rmi.server.UnicastRemoteObject ,现实前面的接口。
public class ServerInterfaceImpl extends UnicastRemoteObject
implements ServerInterface {
// 实现服务器对象接口的各种方法
public void service () throws RemoteException {
..........
}
}
c 、在某个类中创建并注册服务器对象:由服务器实现类创建一个服务器对象,并注册到注册处
......
ServerInterface server = new ServerInterfaceImpl();// 创建一个服务器对象
Registry registry = LocateRegistry.getRegistry();// 得到注册处的引用
registery.rebind(" 自定义的唯一的一个远程对象名称 ", server);// 注册对象
......
d 、开发客户程序:一个查找远程对象并调用其方法的客户程序
.........
Registry registry = LocateRegistry.getRegistry(host);//host: 服务器的主机地址
ServerInterface server =
(ServerInterfaceImpl) registry.lookup(" 服务端自定义的唯一的一个远程对象名称 ");
server.service();// 就可以像本地对象一样使用服务端对象了。
.........
5 、编译使用 RMI :
a 、启动注册处。在 DOS 中输入“ start rmiregistry 端口号”(端口号缺省)。
b 、启动服务器对象程序。
c 、启动客户端程序。
注:必须从 RMI 服务器的目录启动 rmiregistry ,否则有 ClassNotFoundException ;
服务器、注册处、客户端可以处于三台不同机器,但需要将服务器对象接口分别放置在两台机器上。 如果是客户端是 applet ,则要将所有的客户端文件放置在注册处主机。
6 、完整实例:
- package rmi;
- import java.rmi.Remote;
- import java.rmi.RemoteException;
- /**
- *从RMI服务器读取学生分数的服务器对象接口
- * @author Administrator
- */
- public interface StudentServerInterface extends Remote{
- /**
- * return the score for the specified name
- * @param name the student name
- * @return an double score or -1 if the student is not found
- */
- public double findScore(String name) throws RemoteException;
- }
package rmi;
import java.rmi.Remote;
import java.rmi.RemoteException;
/**
*从RMI服务器读取学生分数的服务器对象接口
* @author Administrator
*/
public interface StudentServerInterface extends Remote{
/**
* return the score for the specified name
* @param name the student name
* @return an double score or -1 if the student is not found
*/
public double findScore(String name) throws RemoteException;
}
- package rmi;
- import java.util.HashMap;
- import java.rmi.RemoteException;
- import java.rmi.server.UnicastRemoteObject;
- /**
- *RMI对象的服务器实现类
- * @author Administrator
- */
- public class StudentServerInterfaceImpl extends UnicastRemoteObject
- implements StudentServerInterface{
- private HashMap scores = new HashMap();
- public StudentServerInterfaceImpl() throws RemoteException{
- initializeStudent();
- }
- protected void initializeStudent(){
- scores.put("tufu" , new Double( 99.0 ));
- scores.put("tao" , new Double( 89.3 ));
- scores.put("bing" , new Double( 83.3 ));
- }
- /*Implement the findscore method from the student interface*/
- public double findScore(String name) throws RemoteException {
- Double d = (Double)scores.get(name);
- if (d == null ){
- System.out.println("Student " +name+ " is not found" );
- return - 1 ;
- }
- else {
- System.out.println("Student " +name+ "\'s score is " +d.doubleValue());
- return d.doubleValue();
- }
- }
- }
package rmi;
import java.util.HashMap;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
/**
*RMI对象的服务器实现类
* @author Administrator
*/
public class StudentServerInterfaceImpl extends UnicastRemoteObject
implements StudentServerInterface{
private HashMap scores = new HashMap();
public StudentServerInterfaceImpl() throws RemoteException{
initializeStudent();
}
protected void initializeStudent(){
scores.put("tufu", new Double(99.0));
scores.put("tao", new Double(89.3));
scores.put("bing", new Double(83.3));
}
/*Implement the findscore method from the student interface*/
public double findScore(String name) throws RemoteException {
Double d = (Double)scores.get(name);
if(d == null){
System.out.println("Student "+name+" is not found");
return -1;
}
else{
System.out.println("Student "+name+"\'s score is "+d.doubleValue());
return d.doubleValue();
}
}
}
- package rmi;
- import java.rmi.registry.Registry;
- import java.rmi.registry.LocateRegistry;
- /**
- *从服务器实现类创建一个服务器对象,并在RMI服务器注册它
- * @author Administrator
- */
- public class RegisterWithRMIServer {
- /*main method
- 负责启动服务器*/
- public static void main(String args[]){
- try {
- //创建服务器对象
- StudentServerInterface obj = new StudentServerInterfaceImpl();
- //获得RMI注册处的引用
- Registry registry = LocateRegistry.getRegistry();
- //在注册处注册对象
- registry.rebind("StudentServerInterfaceImpl" , obj);
- System.out.println("Student server " +obj+ " registered" );
- }catch (Exception e){
- e.printStackTrace();
- }
- }
- }
package rmi;
import java.rmi.registry.Registry;
import java.rmi.registry.LocateRegistry;
/**
*从服务器实现类创建一个服务器对象,并在RMI服务器注册它
* @author Administrator
*/
public class RegisterWithRMIServer {
/*main method
负责启动服务器*/
public static void main(String args[]){
try{
//创建服务器对象
StudentServerInterface obj = new StudentServerInterfaceImpl();
//获得RMI注册处的引用
Registry registry = LocateRegistry.getRegistry();
//在注册处注册对象
registry.rebind("StudentServerInterfaceImpl", obj);
System.out.println("Student server "+obj+" registered");
}catch(Exception e){
e.printStackTrace();
}
}
}
- package rmi.client;
- import java.rmi.registry.LocateRegistry;
- import java.rmi.registry.Registry;
- import javax.swing.*;
- import java.awt.*;
- import java.awt.event.*;
- import rmi.StudentServerInterface;
- /**
- *创建一个RMI客户,用来调用RMI服务端的方法
- * @author Administrator
- */
- public class StudentServerInterfaceClient extends JApplet{
- //Declare a student instance
- private StudentServerInterface student;
- private boolean isStandalone; //Is applet or application
- private JButton jbtGetScore = new JButton( "Get Score" );
- private JTextField jtfName = new JTextField();
- private JTextField jtfScore = new JTextField();
- public void init(){ //Applet的初始化方法
- initializeRMI(); //initial RMI
- JPanel jPanel1 = new JPanel();
- jPanel1.setLayout(new GridLayout( 2 , 2 ));
- jPanel1.add(new JLabel( "Name" ));
- jPanel1.add(jtfName);
- jPanel1.add(new JLabel( "Score" ));
- jPanel1.add(jtfScore);
- this .add(jbtGetScore,BorderLayout.SOUTH);
- this .add(jPanel1,BorderLayout.CENTER);
- jbtGetScore.addActionListener(new ActionListener(){
- public void actionPerformed(ActionEvent e){
- getScore();
- }
- });
- }
- private void initializeRMI(){
- String host = "" ;
- if (!isStandalone) host = getCodeBase().getHost(); //用Applet的方法获取调用该applet的主机
- try {
- Registry registry = LocateRegistry.getRegistry(host);
- student = (StudentServerInterface)registry.lookup("StudentServerInterfaceImpl" );
- System.out.println("Server Object " +student+ " found" );
- }catch (Exception e){
- e.printStackTrace();
- }
- }
- private void getScore(){
- try {
- double score = student.findScore(jtfName.getText().trim());
- if (score < 0 )
- jtfScore.setText("Not found" );
- else
- jtfScore.setText(new Double(score).toString());
- }catch (Exception e){
- e.printStackTrace();
- }
- }
- /*Main method*/
- public static void main(String args[]){
- StudentServerInterfaceClient applet =
- new StudentServerInterfaceClient();
- applet.isStandalone = true ;
- JFrame frame = new JFrame();
- frame.setTitle("StudentServerInterfaceClient" );
- frame.add(applet,BorderLayout.CENTER);//fram可以嵌入applet
- frame.setSize(250 , 150 );
- applet.init();
- frame.setLocationRelativeTo(null );
- frame.setDefaultCloseOperation(3 );
- frame.show();
- }
- }
package rmi.client;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import rmi.StudentServerInterface;
/**
*创建一个RMI客户,用来调用RMI服务端的方法
* @author Administrator
*/
public class StudentServerInterfaceClient extends JApplet{
//Declare a student instance
private StudentServerInterface student;
private boolean isStandalone; //Is applet or application
private JButton jbtGetScore = new JButton("Get Score");
private JTextField jtfName = new JTextField();
private JTextField jtfScore = new JTextField();
public void init(){ //Applet的初始化方法
initializeRMI(); //initial RMI
JPanel jPanel1 = new JPanel();
jPanel1.setLayout(new GridLayout(2,2));
jPanel1.add(new JLabel("Name"));
jPanel1.add(jtfName);
jPanel1.add(new JLabel("Score"));
jPanel1.add(jtfScore);
this.add(jbtGetScore,BorderLayout.SOUTH);
this.add(jPanel1,BorderLayout.CENTER);
jbtGetScore.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
getScore();
}
});
}
private void initializeRMI(){
String host = "";
if(!isStandalone) host = getCodeBase().getHost(); //用Applet的方法获取调用该applet的主机
try{
Registry registry = LocateRegistry.getRegistry(host);
student = (StudentServerInterface)registry.lookup("StudentServerInterfaceImpl");
System.out.println("Server Object "+student+" found");
}catch(Exception e){
e.printStackTrace();
}
}
private void getScore(){
try{
double score = student.findScore(jtfName.getText().trim());
if(score < 0)
jtfScore.setText("Not found");
else
jtfScore.setText(new Double(score).toString());
}catch(Exception e){
e.printStackTrace();
}
}
/*Main method*/
public static void main(String args[]){
StudentServerInterfaceClient applet =
new StudentServerInterfaceClient();
applet.isStandalone = true;
JFrame frame = new JFrame();
frame.setTitle("StudentServerInterfaceClient");
frame.add(applet,BorderLayout.CENTER);//fram可以嵌入applet
frame.setSize(250,150);
applet.init();
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(3);
frame.show();
}
}