Upload
jake
View
86
Download
0
Embed Size (px)
DESCRIPTION
Advanced Network Programming. Ren Jiansi [email protected]. Java RMI 技术. (Remote Method Invocation ). RMI 基本原理 : RMI 能让一个 Java 程序调用网络中另外一台计算机的 Java 对象的方法,效果就像这个远程计算机上的对象方法在本地机上一样。 RMI 采用客户 / 服务器通信方式 RMI 应用的开发步骤 : 1. 创建 远程接口 远程接口必须继承 java.rmi.Remote 类。 - PowerPoint PPT Presentation
Citation preview
Java RMI 技术(Remote Method
Invocation )
RMI 基本原理 : RMI 能让一个 Java 程序调用网络中另外一台计算机的 Java 对象的方法,效果就像这个远程计算机上的对象方法在本地机上一样。
RMI 采用客户 / 服务器通信方式 RMI 应用的开发步骤 :1. 创建远程接口 远程接口必须继承 java.rmi.Remote 类。 接口中方法必须抛出 java.rmi.RemoteException 异
常。2. 创建远程类 实现远程接口 远程类的命名是远程接口类名加上“ Impl”( 不是必
须 ) ,例如,远程接口 Upper 类对应的远程接口实现类名为 UpperImpl 。
3. 创建服务器程序 服务器程序的一大任务就是向 rmiregistry
注册表注册远程对象。4. 创建客户程序 运行 RMI 应用 :1. 启动注册表 start rmiregistry 默认监听 1099 端口 , 可使用命令 start rmiregistry 8000 监听别的端口如 8000 程序中服务器帮定对象和客户查找远程对象都要
变更端口 rmi://localhost:8000/…2. 启动服务器程序 start java SimpleServer3. 启动客户程序 java SimpleClient
例 1: 开发一个远程方法 upperCase(String str) ,它把客户(调用者)提供的字符串传送给服务者,服务者把它全部转变成大写字符串后返回给客户。
1. 创建远程接口 Upper.java
import java.rmi.*;
public interface Upper extends Remote { String upperCase(String s) throws RemoteException;}
2. 创建远程类 UpperImpl.javaimport java.rmi.*;import java.rmi.server.UnicastRemoteObject;public class UpperImpl extends UnicastRemoteObject implements Uppe
r{ public UpperImpl() throws RemoteException { } public String upperCase(String s) throws RemoteE
xception { return s.toUpperCase(); // 字符串类的方法 }}
3. 创建服务器程序 UpperServer.javaimport java.rmi.*;import javax.naming.*;public class UpperServer{ public static void main( String args[] ){ try { Upper service = new UpperImpl(); Context namingContext=new InitialContext(); namingContext.rebind( "rmi:Upper1", service); System.out.println(" 服务器注册了一个 Upper 对
象 " ); } catch (Exception e) { e.printStackTrace(); }}}
4. 创建客户程序 UpperClient.javaimport java.rmi.*;import javax.naming.*;public class UpperClient {public static void main(String[] arg) { String url="rmi://localhost/";try { Context namingContext=new InitialContext(); Upper service=(Upper)namingContext.lookup(url
+"Upper1");// 利用参数“ abc” 远程调用方法 upperCase()System.out.println(service.upperCase("abc")); } catch (Exception e) {e.printStackTrace();} }}
例 2:
1. 创建远程接口 HelloService.javaimport java.util.Date;
import java.rmi.*;
public interface HelloService extends Remote{
public String echo(String msg) throws RemoteException;
public Date getTime() throws RemoteException;
}
2. 创建远程类 HelloServiceImpl.javaimport java.util.Date;import java.rmi.*;import java.rmi.server.UnicastRemoteObjec
t;public class HelloServiceImpl extends Unica
stRemoteObject implements HelloService{ private String name; public HelloServiceImpl(String name)throw
s RemoteException{ this.name=name; }
public String echo(String msg)throws RemoteException{
System.out.println(name+": 调用 echo() 方法 ");
return "echo:"+msg +" from "+name;
}
public Date getTime()throws RemoteException{
System.out.println(name+": 调用 getTime() 方法 ");
return new Date();
}
}
3. 创建服务器程序 SimpleServer.java
import java.rmi.*;
import javax.naming.*;
public class SimpleServer{
public static void main( String args[] ){
try{
HelloService service1 = new HelloServiceImpl("service1");
HelloService service2 = new HelloServiceImpl("service2");
Context namingContext=new InitialContext(); namingContext.rebind( "rmi:HelloService
1", service1 ); namingContext.rebind( "rmi:HelloService
2", service2 ); System.out.println( " 服务器注册了两个 Hel
loService 对象 " ); }catch(Exception e){ e.printStackTrace(); } }}
4. 创建客户程序 SimpleClient.javaimport java.rmi.*;import javax.naming.*;public class SimpleClient{ public static void main( String args[] ){ String url="rmi://localhost/"; try{ Context namingContext=new InitialContex
t(); HelloService service1=(HelloService)nami
ngContext.lookup(url+"HelloService1"); HelloService
service2=(HelloService)namingContext.lookup(url+"HelloService2");
System.out.println(service1.echo("hello"));
System.out.println(service1.getTime());
System.out.println(service2.echo("hello"));
System.out.println(service2.getTime());
}catch( Exception e){
e.printStackTrace();
}
}
}
SimpleServer 端的打印结果如下 :
SimpleClient 端的打印结果如下 :
CORBA CORBA(Common Object Request
Broker Architecture ,公共对象请求代理结构 ) 是 OMG ( Object Management Group ,对象管理组织)制定的一个基于开放标准的分布式计算解决方案,它的主要目的是支持用户在计算机硬件、操作系统、程序设计语言和网络通信协议异构的情况下方便地开发健壮的、可伸缩的、面向对象的分布式应用。
CORBA 和 Java 都采用面向对象技术,因此,可以很容易地用 Java 语言开发 CORBA 应用,或将 Java 应用以及 JavaBean 对象集成到CORBA 应用环境中; CORBA 和 Java 都适用于开发分布式应用,所不同的是: CORBA 偏重于通用的分布式应用开发,而 Java 注重于 WWW环境中的分布式应用开发。 CORBA 采用客户 /服务器模式。
CORBA 独立于任何编程语言 , 独立于任何操作系统平台。在 Linux 中用 Java编写的 CORBA对象可以与Windows 操作系统中用 C++编写的CORBA 对象通信。
IDL 语言是一种接口定义语言。 IDL 语言不同于所有已有的程序设计语言,它是一种描述性语言,也就是说,用它描述得到的接口是不能直接被编译执行。 IDL 独立于任何其他编程语言。
创建 CORBA 程序的步骤 : 1. 创建 IDL接口 2. 创建 IDL接口的实现类 3. 创建服务器程序 创建并注册 CORBA 对象 orbd.exe 是 JDK 提供的一个 CORBA 的命名服务器
程序 4. 创建客户程序运行 CORBA 程序 : 1. 编译 IDL接口 idlj -fall HelloService.idl 2. 启动命名服务器程序 start orbd -ORBInitialPort 1050 1050 为命名服务器监听的端口
3. 启动服务器程序start java hello.HelloServer -ORBInitialPort 10
50 -ORBInitialHost localhost
4. 运行客户程序 java hello.HelloClient -ORBInitialPort 1050 -ORBInitialHost localhost
例 1: 利用 Java与 CORBA技术开发一个远程方法 upperCase(string str) ,它把客户(调用者)传送来的字符串全部转变成大写字符串后返回给客户。
1. 创建 IDL接口 UpperModule.idl module UpperModule { interface Upper { string upperCase(in string str); }; };
2. 创建 IDL接口的实现类 UpperImpl.javapackage UpperModule;public class UpperImpl extends UpperPOA { public UpperImpl() { } public String upperCase (String str) {// 返回结果 : return str.toUpperCase(); }}
3. 创建服务器程序 UpperServer.javapackage UpperModule;import java.io.*;import org.omg.CORBA.*;import org.omg.CosNaming.*;import org.omg.PortableServer.*;import org.omg.PortableServer.POA;import org.omg.CosNaming.NamingContextP
ackage.*;public class UpperServer{ public static void main(String args[]) { try{
// 初始化 ORB 对象 ORB orb = ORB.init(args, null);
// 建立接口实现类 UpperImpl 对象,并与 ORB连接
UpperImpl upperImpl= new UpperImpl();
//取得 RootPOA引用 ,并激活 POAManager
POA rootpoa = POAHelper.narrow( orb.resolve_initial_references("RootPOA"));
rootpoa.the_POAManager().activate();
//取得对象引用org.omg.CORBA.Object ref = rootpoa.
servant_to_reference(upperImpl);
Upper href = UpperHelper.narrow(ref);
//获得命名服务的 Context
org.omg.CORBA.Object objRef = orb.resolve_initial_references("NameService");
NamingContextExt ncRef = NamingContextExtHelper.narrow(objRef);
//绑定对象引用String name = "Upper";
NameComponent path[] = ncRef.to_name( name );
ncRef.rebind(path, href);
System.out.println("UpperServer ready ....");
// 等待客户调用orb.run();
}
catch(Exception e)
{
System.err.println("ERROR: " + e);
e.printStackTrace(System.out);
}
}
}
4. 创建客户程序 UpperClient.java
package UpperModule;
import java.io.*;
import org.omg.CORBA.*;
import org.omg.CosNaming.*;
import org.omg.CosNaming.NamingContextPackage.*;
public class UpperClient
{ public static void main(String args[])
{ try {
String str;
// 初始化 ORB 对象 ORB orb = ORB.init(args, null);
// 使用命名服务获得 NamingContext 。 NameService 是所有 ORB 命名的总称。
org.omg.CORBA.Object objRef =
orb.resolve_initial_references("NameService");
// 用 NamingContextExt 代替 NamingContext
NamingContextExt ncRef =
NamingContextExtHelper.narrow(objRef);
// 用名称解析对象引用 String name = "Upper";
Upper upper= UpperHelper.narrow(ncRef.resolve_str(name));
// 调用远程方法 upperCase() str= upper.upperCase("abc"); System.out.println(str); } catch(Exception e) {System.out.println("ERROR : " + e); e.printStackTrace(System.out);} }}
例 2: 1. 创建 IDL接口 HelloService.idl
module hello{ interface HelloService{ string sayHello(); };};
2. 创建 IDL接口的实现类 HelloServiceImpl.javapackage hello;import org.omg.CosNaming.*;import org.omg.CosNaming.NamingContextPackage.*;
import org.omg.CORBA.*;import org.omg.PortableServer.*;import org.omg.PortableServer.POA;import java.util.Properties;public class HelloServiceImpl extends HelloS
ervicePOA { public String sayHello() { return "\nHello world !!\n"; }}
3. 创建服务器程序 HelloServer.javapackage hello;import org.omg.CosNaming.*;import org.omg.CosNaming.NamingContextP
ackage.*;import org.omg.CORBA.*;import org.omg.PortableServer.*;import org.omg.PortableServer.POA;import java.util.Properties;public class HelloServer { public static void main(String args[]) { try{
// 创建和初始化 ORB
ORB orb = ORB.init(args, null);
//获得根 POA 的引用,并且激活 POAManager
POA rootpoa =POAHelper.narrow(orb.resolve_initial_references("RootPOA"));
rootpoa.the_POAManager().activate();
// 创建一个 HelloServiceImpl 对象,并且把它与 ORB关联
HelloServiceImpl helloServiceImpl = new HelloServiceImpl();
//获得 HelloServiceImpl 对象的 CORBA 类型的对象引用
org.omg.CORBA.Object ref = rootpoa.servant_to_reference(helloServiceImpl);
HelloService href = HelloServiceHelper.narrow(ref);
//获得命名服务的 Context org.omg.CORBA.Object objRef = orb.resolve_initial_references("NameServ
ice"); NamingContextExt ncRef = NamingContextEx
tHelper.narrow(objRef);
// 把 HelloService 对象与“ HelloService” 名字绑定
String name = "HelloService"; NameComponent path[] = ncRef.to_name( n
ame ); ncRef.rebind(path, href); System.out.println("HelloServer ready and
waiting ..."); //等待客户端访问 HelloService 对象 orb.run(); }catch (Exception e) { System.err.println("ERROR: " + e); e.printStackTrace(System.out); } }}
4. 创建客户程序 HelloClient.javapackage hello;import org.omg.CosNaming.*;import org.omg.CosNaming.NamingContextP
ackage.*;import org.omg.CORBA.*;public class HelloClient{ static HelloService helloServiceImpl; public static void main(String args[]){ try{ // 创建和初始化 ORB ORB orb = ORB.init(args, null);
//获得命名服务的 Context org.omg.CORBA.Object objRef = orb.resolve_initial_references("NameServic
e"); NamingContextExt ncRef = NamingContex
tExtHelper.narrow(objRef); //获得名为“ HelloService” 的 HelloService
对象的远程引用 String name = "HelloService"; helloServiceImpl = HelloServiceHelper.nar
row(ncRef.resolve_str(name));
// 调用 HelloService 对象的远程方法 System.out.println(helloServiceImpl.sayHe
llo());
}catch (Exception e) {
System.out.println("ERROR : " + e) ;
e.printStackTrace(System.out);
}
}
}