Java RMI 远程调用

今天看一天的RMI终于搞懂了,到底是怎么回事了。

RMI网上有很多说明,大概就是这样的。
  1、  编写并且编译接口的Java代码
  2、  编写并且编译接口实现的Java代码
  3、  从接口实现类中生成 Stub 和 Skeleton 类文件
  4、  编写远程服务的主运行程序
  5、  编写RMI的客户端程序
  6、  安装并且运行RMI系统

先讲一种网上最常见的(参考资料来源Java RMI Tutorial)
首先编写服务断对外提供的接口,必须继承 java.rmi.Remote。
接口代码如下:
import java.rmi.*;
/**
 * Remote Interface for the "Hello, world!" example.
 */
public interface HelloInterface extends Remote {
  /**
   * Remotely invocable method.
   * @return the message of the remote object, such as "Hello, world!".
   * @exception RemoteException if the remote invocation fails.
   */
  public String say() throws RemoteException;
}


再来就是对该接口的实现,这里有两种方式(一种是必须实现该接口,必继承java.rmi.server.UnicastRemoteObject,另一种是只实现该接口,但是必须调用UnicastRemoteObject.exportObject方法),采用第一种代码如下:
import java.rmi.*;
import java.rmi.server.*;
/**
 * Remote Class for the "Hello, world!" example.
 */
public class Hello extends UnicastRemoteObject implements HelloInterface {
  private String message;
  /**
   * Construct a remote object
   * @param msg the message of the remote object, such as "Hello, world!".
   * @exception RemoteException if the object handle cannot be constructed.
   */
  public Hello (String msg) throws RemoteException {
    message = msg;
  }
  /**
   * Implementation of the remotely invocable method.
   * @return the message of the remote object, such as "Hello, world!".
   * @exception RemoteException if the remote invocation fails.
   */
  public String say() throws RemoteException {
    return message;
  }
}

分别编译文件。

编译完成后,要从接口实现类中生成 Stub 和 Skeleton 类文件,这时就要用到
rmic Hello
命令,如果出现错误,请讲Hello.class的路径设置到classpath路径下。

然后编写客户器端代码:
  /**
   * Client program for the "Hello, world!" example.
   * @param argv The command line arguments which are ignored.
   */
  public static void main (String[] argv) {
    try {
      HelloInterface hello = 
        (HelloInterface) Naming.lookup ("//172.0.0.1/Hello");
      System.out.println (hello.say());
    } catch (Exception e) {
      System.out.println ("HelloClient exception: " + e);
    }
  }

然后编译。

然后编写服务端代码,
  /**
   * Server program for the "Hello, world!" example.
   * @param argv The command line arguments which are ignored.
   */
  public static void main (String[] argv) {
    try {
      Naming.rebind ("Hello", new Hello ("Hello, world!"));
      System.out.println ("Hello Server is ready.");
    } catch (Exception e) {
      System.out.println ("Hello Server failed: " + e);
    }
  }

然后编译,

开始启动服务器,这里是最麻烦的,
首先开启RMI Registry(注册表),
输入命令行:rmiregistry &
完成后放在一边保持不动,重新开启一个终端。
然后运行:
java HelloServer &
完成后放在一边保持不动,再重新开启一个终端。
最后再
java HelloClient。
终于成功显示。

这样太麻烦了,还容易出错,有没有简单方法呢?
有下面 我就来介绍介绍:
前面还是一样的,我重新写了代码:如下
import java.rmi.Remote;
import java.rmi.RemoteException;

public interface TestInterfactRemote extends Remote {
	 
	 public String echo(String message) throws RemoteException; 
}

import java.rmi.RemoteException;

public class TestInterfaceRemoteImpl implements TestInterfactRemote {

			public String echo(String message) throws RemoteException {
				if("quit".equalsIgnoreCase(message.toString())){
					System.out.println("Server will be shutdown");
					System.exit(0);
				}
				System.out.println("Message from client:"+ message);
				return "server response" + message;
			} 
}


不同的地方在于服务端和客户端,仔细看:
public class Server {
	     public Server() {  
		        try {
		        	int port = 9527;
		        	String name = "testDemo";
		            TestInterfactRemote testInterfactRemote = new TestInterfaceRemoteImpl();
		            //完成对象的绑定
		            UnicastRemoteObject.exportObject(testInterfactRemote, port);
		            //完成注册表的开启
		            Registry registry = LocateRegistry.createRegistry(1099);
		            //这里没有用Naming绑定,运用的是registry提供的绑定方法
		            registry.rebind(name, testInterfactRemote);
		        } catch (Exception e) {  
		            e.printStackTrace();  
		       }  
		    }  
		   
		     public static void main(String args[]) {  
		         new Server();  
		     }  
}

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;

import test.TestInterfactRemote;

 public class Client {  
	     public static void main(String args[]) {  
	         try {
	        	 //获得登记注册表的位置
	        	 Registry registry = LocateRegistry.getRegistry("localhost");
	        	 String name = "testDemo";
	        	 //运用注册表进行对象的查找
	             TestInterfactRemote testInterfactRemote = (TestInterfactRemote) registry.lookup(name);
	             BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
	             String input = br.readLine();
	             String reponse = testInterfactRemote.echo(input);
	             System.out.println(reponse);
	         } catch (Exception e) {  
	            e.printStackTrace();  
	         }  
	     }  
	 }  


直接编译完成后运行试试结果是怎么样的?

这样很简单吧!又好理解。




你可能感兴趣的:(java)