这些日子一直在研究SOAP--WebService的东东,发现和JAVA-RMI很相似,他们两个都是基于RPC(Remote Procedure Call)风格。如果想学习SOAP-WebService的朋友,建议先看看JAVA-RMI的知识,自己动手做个HelloWorld,体会一下。一定会对你理解SOAP-WebService有帮助的。
一.先解释一下什么是RPC
一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议。RPC协议假定某些传输协议的存在,如TCP或UDP,为通信程序之间携带信息数据。在OSI网络通信模型中,RPC跨越了传输层和应用层。RPC使得开发包括网络分布式多程序在内的应用程序更加容易。
3.启动RMI注册服务,并注册远程对象(HelloServer.java)
RPC采用客户机/服务器模式。请求程序就是一个客户机,而服务提供程序就是一个服务器。首先,调用进程发送一个有进程参数的调用信息到服务进程,然后等待应答信息。在服务器端,进程保持睡眠状态直到调用信息的到达为止。当一个调用信息到达,服务器获得进程参数,计算结果,发送答复信息,然后等待下一个调用信息,最后,客户端调用过程接收答复信息,获得进程结果,然后调用执行继续进行。
二.下面详细讲解JAVA-RMI分布式应用
用RMI编写一个分布式应用,核心有以下三方面:
1.定位远程对象
-- 一个应用可以利用RMI的名字服务功能注册器远程对象。
-- 可以象操作本地普通对象一样传送并返回一个远程对象的引用
2.与远程对象通信:
-- 底层的通信由RMI实现,对于系统开发人员来说,远程调用和标准的Java方法调
用没有什么区别。
3.为需要传递的对象装载类的字节码
-- RMI允许调用者向远程对象传递一个对象,因此RMI提供这种装载对象的机制。
下图是JAVA-RMI过程调用图
RMI远程接口:
远程对象必须继承远程接口,确定那些方法是远程方法,为此定义远程接口,远程接口只负责提供方法名,不提供实现细节,因此必须由一个对象来实现接口。
一般来说,实现一个远程接口的类至少有以下步骤:
1.声明远程接口
2.为远程对象定义构造函数
3.实现远程方法
参数传递规则:
1.远程对象通常通过引用传递,一个远程对象的引用是一个stub,它是客户端的代理,它实现远程对象中的远程接口的内容。
2.本地对象通过串行化拷贝到目的,如果不作制定,对象的所有成员都将被拷贝。
下面是实现JAVA-RMI程序
分为以下四个步骤:
1.创建远程接口及声明远程方法(HelloInterface.java)
2.实现远程接口及远程方法(继承UnicastRemoteObject)(Hello.java)
3.启动RMI注册服务,并注册远程对象(HelloServer.java)
4.客户端查找远程对象,并调用远程方法(HelloClient.java)
3.启动RMI注册服务,并注册远程对象(HelloServer.java)
4.客户端查找远程对象,并调用远程方法(HelloClient.java)
最后执行程序:启动服务HelloServer;运行客户端HelloClient进行调用
1.创建远程接口及声明远程方法(HelloInterface.java)
package test.rmi;
import java.rmi.*;
/**
* 远程接口必须扩展接口java.rmi.Remote
*/
public interface HelloInterface extends Remote
{
/**
* 远程接口方法必须抛出 java.rmi.RemoteException
*/
public String say() throws RemoteException;
}
import java.rmi.*;
/**
* 远程接口必须扩展接口java.rmi.Remote
*/
public interface HelloInterface extends Remote
{
/**
* 远程接口方法必须抛出 java.rmi.RemoteException
*/
public String say() throws RemoteException;
}
2.实现远程接口及远程方法(继承UnicastRemoteObject)(Hello.java)
package test.rmi;
import java.rmi.*;
import java.rmi.server.*;
public class Hello extends UnicastRemoteObject implements HelloInterface {
private String message;
public Hello(String msg) throws RemoteException {
message = msg;
}
public String say() throws RemoteException{
System.out.println( "Called by HelloClient");
return message;
}
}
import java.rmi.*;
import java.rmi.server.*;
public class Hello extends UnicastRemoteObject implements HelloInterface {
private String message;
public Hello(String msg) throws RemoteException {
message = msg;
}
public String say() throws RemoteException{
System.out.println( "Called by HelloClient");
return message;
}
}
3.启动RMI注册服务,并注册远程对象(HelloServer.java)
package test.rmi;
import java.rmi.Naming;
import java.rmi.registry.LocateRegistry;
public class HelloServer
{
/**
* 启动 RMI 注册服务并进行对象注册
*/
public static void main(String[] argv)
{
try
{
//启动RMI注册服务,指定端口为1099 (1099为默认端口)
//也可以通过命令 $java_home/bin/rmiregistry 1099启动
//这里用这种方式避免了再打开一个DOS窗口
//而且用命令rmiregistry启动注册服务还必须事先用RMIC生成一个stub类为它所用
LocateRegistry.createRegistry(1099);
//创建远程对象的一个或多个实例,下面是hello对象
//可以用不同名字注册不同的实例
HelloInterface hello = new Hello( "Hello, world!");
//把hello注册到RMI注册服务器上,命名为Hello
Naming.rebind( "Hello", hello);
//如果要把hello实例注册到另一台启动了RMI注册服务的机器上
//Naming.rebind("//192.168.1.105:1099/Hello",hello);
System.out.println( "Hello Server is ready.");
}
catch (Exception e)
{
System.out.println( "Hello Server failed: " + e);
}
}
}
import java.rmi.Naming;
import java.rmi.registry.LocateRegistry;
public class HelloServer
{
/**
* 启动 RMI 注册服务并进行对象注册
*/
public static void main(String[] argv)
{
try
{
//启动RMI注册服务,指定端口为1099 (1099为默认端口)
//也可以通过命令 $java_home/bin/rmiregistry 1099启动
//这里用这种方式避免了再打开一个DOS窗口
//而且用命令rmiregistry启动注册服务还必须事先用RMIC生成一个stub类为它所用
LocateRegistry.createRegistry(1099);
//创建远程对象的一个或多个实例,下面是hello对象
//可以用不同名字注册不同的实例
HelloInterface hello = new Hello( "Hello, world!");
//把hello注册到RMI注册服务器上,命名为Hello
Naming.rebind( "Hello", hello);
//如果要把hello实例注册到另一台启动了RMI注册服务的机器上
//Naming.rebind("//192.168.1.105:1099/Hello",hello);
System.out.println( "Hello Server is ready.");
}
catch (Exception e)
{
System.out.println( "Hello Server failed: " + e);
}
}
}
4.客户端查找远程对象,并调用远程方法(HelloClient.java)
package test.rmi;
import java.rmi.Naming;
public class HelloClient
{
/**
* 查找远程对象并调用远程方法
*/
public static void main(String[] argv)
{
try
{
HelloInterface hello = (HelloInterface) Naming.lookup( "Hello");
//如果要从另一台启动了RMI注册服务的机器上查找hello实例
//HelloInterface hello = (HelloInterface)Naming.lookup("//192.
import java.rmi.Naming;
public class HelloClient
{
/**
* 查找远程对象并调用远程方法
*/
public static void main(String[] argv)
{
try
{
HelloInterface hello = (HelloInterface) Naming.lookup( "Hello");
//如果要从另一台启动了RMI注册服务的机器上查找hello实例
//HelloInterface hello = (HelloInterface)Naming.lookup("//192.
168.1.105:1099/Hello");
//调用远程方法
System.out.println(hello.say());
}
catch (Exception e)
{
System.out.println( "HelloClient exception: " + e);
}
}
}
//调用远程方法
System.out.println(hello.say());
}
catch (Exception e)
{
System.out.println( "HelloClient exception: " + e);
}
}
}
源代码已经写好了,把这四个java文件编译成class文件
G:\workspace\src\testrmi\src\test\rmi>javac *.java
(1)打开一个Dos窗口执行命令 java test.rmi.HelloServer 这就算启动了服务HelloServer
G:\workspace\src\testrmi>java test.rmi.HelloServer
Hello Server is ready.
运行成功则可以看到 Hello Server is ready
Hello Server is ready.
运行成功则可以看到 Hello Server is ready
(2)打开另一个Dos窗口执行命令 java test.rmi.HelloClient运行客户端程序
G:\workspace\src\testrmi>java test.rmi.HelloClient
Hello, world!
调用成功则可以看到 Hello, world!
G:\workspace\src\testrmi>java test.rmi.HelloClient
Hello, world!
调用成功则可以看到 Hello, world!