RMI的简单实现

第一次使用RMI实现java分布式,利用一个简单的例子进行测试。

首先需要一个实现了Remote的接口,这个接口提供远程对象的方法集

这个接口如下:

package com.hello;

import java.rmi.Remote;
import java.rmi.RemoteException;
import java.util.Date;

public interface HelloServer extends Remote 
{
	public String echo(String msg)throws RemoteException;
	public Date getTime()throws RemoteException;
}

在客户端和服务器上都应该有这样一个接口,只是可以使用的服务。

然后再服务端需要一个实现了HelloServer的类,并使其成为能够提供远程服务的远程对象,这里通过继承UnicastRemoteObject使其导出远程对象:

package com.hello;

import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
import java.util.Date;

public class HelloServerImpl extends UnicastRemoteObject implements HelloServer
{
	private String name;
	protected HelloServerImpl(String name) throws RemoteException 
	{
		this.name=name;
	}
	public String echo(String msg) throws RemoteException
	{
		System.out.println("调用了echo()方法");

		return "echo "+msg+" from "+name;
	}

	public Date getTime() throws RemoteException 
	{

		System.out.println("调用了getTime()方法");
		return new Date();
	}

}
接下来编写服务端程序

package com.hello;

import javax.naming.Context;
import javax.naming.InitialContext;

public class SimpleServer 
{
	public static void main(String[]args)
	{
		try
		{
			HelloServer service1=new HelloServerImpl("service1");
			HelloServer service2=new HelloServerImpl("service2");
			
			Context namingContext=new InitialContext();
			
			namingContext.rebind("rmi://localhost:1099/HelloServer1",service1);
			namingContext.rebind("rmi://localhost:1099/HelloServer2",service2);
			System.out.println("注册了两个对象");
		}
		catch(Exception e)
		{
			e.printStackTrace();
		}
	}
}

接下来编写客户端程序

package com.hello;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NameClassPair;
import javax.naming.NamingEnumeration;

public class SimpleClient 
{
	public static void main(String[]args)
	{
		String url="rmi://localhost:1099/";
		try
		{
			Context namingContext=new InitialContext();
			//获得远程对象的存根对象
			HelloServer service1=(HelloServer)namingContext.lookup(url+"HelloServer1");
			HelloServer service2=(HelloServer)namingContext.lookup(url+"HelloServer2");
			Class stubClass=service1.getClass();
			//测试存根类所属的类
			System.out.println("service1是 "+stubClass.getName());
			//测试存根类实现的接口
			Class[] interfaces=stubClass.getInterfaces();
			for(int i=0;i<interfaces.length;i++)
			{
				System.out.println("存根类实现了"+interfaces[i].getName());
			}
			System.out.println(service1.echo("hello"));
			System.out.println(service1.getTime());
			System.out.println(service2.echo("hello"));
			System.out.println(service2.getTime());
			NamingEnumeration<NameClassPair> e=namingContext.list("rmi:");
			while(e.hasMore())
			{
				System.out.println(e.next().getName());
			}
		}
		catch(Exception e)
		{
			e.printStackTrace();
		}
	}
}

在运行程序之前需要进入到HelloServer的bin目录下开启rmiregistry

命令:start rmiregistry

如果没有错误,就会弹出新的黑框;

接下来客户端还需要一个存根类,为了获得它需要在服务端的bin目录下用如下命令:

rmic com.hello.HelloServer

这个命令注意:HelloServer是完整的类名,并且没有.class后缀

如果成功的话会产生一个HelloServerImpl_Stub.class,将其与客户端class文件放在一起。

下来就可以运行程序了。

首先运行服务端,运行结果如下:


然后运行客户端,运行结果如下:


而此时的服务端状态如下:



说明客户端对远程对象的方法调用其执行过程确实是在服务端进行的。


注意:在jdk1.3以后就不用再手动生成存根类了,RMI会自己完成。


在真正的RMI实现里需要利用java.rmi.server.codebase进行动态加载存根类,为了实现它必须完成:

1.使用安全管理器

System.setProperty("java.security.policy",SimpleClient.class.getResource("client.policy").toString());

System.setSecurityManager(new RMISecurityManager());

2.建立一个供客户端下载的目录,目录的结构和包目录一致,假如你的HelloServer.class位于包com.hello下,则该目录结构也必须具有com和hello子目录。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值