博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
RMI知识整理
阅读量:6649 次
发布时间:2019-06-25

本文共 7197 字,大约阅读时间需要 23 分钟。

hot3.png

(一、JDK1.4前的RMI)

RMI(即Remote Method Invoke 远程方法调用)。在Java中,只要一个类extends了java.rmi.Remote接口,即可成为存在于服务器端的远程对象,供客户端访问并提供一定的服务。JavaDoc描述:Remote 接口用于标识其方法可以从非本地虚拟机上调用的接口。任何远程对象都必须直接或间接实现此接口。只有在“远程接口”(扩展 java.rmi.Remote 的接口)中指定的这些方法才可远程使用。 

注意:extends了Remote接口的类或者其他接口中的方法若是声明抛出了RemoteException异常,则表明该方法可被客户端远程访问调用。 

同时,远程对象必须实现java.rmi.server.UniCastRemoteObject类,这样才能保证客户端访问获得远程对象时,该远程对象将会把自身的一个拷贝以Socket的形式传输给客户端,此时客户端所获得的这个拷贝称为“存根”,而服务器端本身已存在的远程对象则称之为“骨架”。其实此时的存根是客户端的一个代理,用于与服务器端的通信,而骨架也可认为是服务器端的一个代理,用于接收客户端的请求之后调用远程方法来响应客户端的请求。 

RMI 框架的基本原理大概如下图,应用了代理模式来封装了本地存根与真实的远程对象进行通信的细节。

(该图转自51CTO)

1. Server端:

HelloServer RMI服务器端
IHello RMI接口
HelloImpl RMI实现

 HelloServer.java

package com.rmidemo.server;import java.net.MalformedURLException;import java.rmi.AlreadyBoundException;import java.rmi.Naming;import java.rmi.RemoteException;import java.rmi.registry.LocateRegistry;public class HelloServer{	public static void main(String args[])	{		try		{			// 创建一个远程对象			IHello rhello = new HelloImpl();			// 本地主机上的远程对象注册表Registry的实例,并指定端口为8888,这一步必不可少(Java默认端口是1099),必不可缺的一步,缺少注册表创建,则无法绑定对象到远程注册表上			LocateRegistry.createRegistry(8888);			// 把远程对象注册到RMI注册服务器上,并命名为RHello			// 绑定的URL标准格式为:rmi://host:port/name(其中协议名可以省略,下面两种写法都是正确的)			Naming.bind("rmi://localhost:8888/RHello", rhello);			System.out.println("cout<<<<< INFO:远程IHello对象绑定成功!");		}		catch (RemoteException e)		{			System.out.println("创建远程对象发生异常!");			e.printStackTrace();		}		catch (AlreadyBoundException e)		{			System.out.println("发生重复绑定对象异常!");			e.printStackTrace();		}		catch (MalformedURLException e)		{			System.out.println("发生URL畸形异常!");			e.printStackTrace();		}	}}

IHello.java

package com.rmidemo.server;import java.rmi.Remote;import java.rmi.RemoteException;public interface IHello extends Remote{	/**	 * 简单的返回“Hello World!"字样	 * 	 * @return 返回“Hello World!"字样	 * @throws java.rmi.RemoteException	 */	public String helloWorld() throws RemoteException;	/**	 * 一个简单的业务方法,根据传入的人名返回相应的问候语	 * 	 * @param someBodyName	 *            人名	 * @return 返回相应的问候语	 * @throws java.rmi.RemoteException	 */	public String sayHelloToSomeBody(String someBodyName) throws RemoteException;}

HelloImpl.java

package com.rmidemo.server;import java.io.Serializable;import java.rmi.RemoteException;import java.rmi.server.UnicastRemoteObject;public class HelloImpl extends UnicastRemoteObject implements IHello, Serializable{	/**	 * serialVersionUID	 */	private static final long serialVersionUID = 3016980098018700517L;	protected HelloImpl() throws RemoteException	{		super();	}	@Override	public String helloWorld() throws RemoteException	{		System.out.println("call 1");		return "word";	}	@Override	public String sayHelloToSomeBody(String someBodyName) throws RemoteException	{		System.out.println("call 2");		return "666" + someBodyName;	}}

1. Client端:

HelloClient 客户端请求类
IHello 远程对象的接口

HelloClient.java:

package com.rmidemo.client;import java.net.MalformedURLException;import java.rmi.Naming;import java.rmi.NotBoundException;import java.rmi.RemoteException;import com.rmidemo.server.IHello;public class HelloClient{	public static void main(String[] args) throws MalformedURLException, RemoteException, NotBoundException	{		IHello remoteHello = (IHello) Naming.lookup("rmi://localhost:8888/RHello");		System.out.println(remoteHello.helloWorld());		System.out.println(remoteHello.sayHelloToSomeBody("666"));	}}

IHello.java:

package com.rmidemo.server;import java.rmi.Remote;import java.rmi.RemoteException;public interface IHello extends Remote{	/**	 * 简单的返回“Hello World!"字样	 * 	 * @return 返回“Hello World!"字样	 * @throws java.rmi.RemoteException	 */	public String helloWorld() throws RemoteException;	/**	 * 一个简单的业务方法,根据传入的人名返回相应的问候语	 * 	 * @param someBodyName	 *            人名	 * @return 返回相应的问候语	 * @throws java.rmi.RemoteException	 */	public String sayHelloToSomeBody(String someBodyName) throws RemoteException;}

 

启动服务端:——>

112858_salj_2338224.png

启动客户端:——>

112918_Pzd4_2338224.png

(一、JDK1.5后的RMI)

这里讲述的是基于JDK1.5的RMI程序搭建,更简单的说是一个 HelloWorld RMI。

1. 这里是基于JDK1.5的,节省了繁琐的手工编译(生成桩和骨架)。不像1.4之前的RMI。

2. 这里是把客户端和服务器端的两个程序,分布在两个独立的程序里面,而不是同一个package下面。是真正的分布式。

3. 这里不过多阐述原理,这只是一个Hello World!!

好,以下是步骤:

1. 在Eclipse里面创建一个server 端的project。然后,创建一个接口,这个接口是你要向client端开放的方法定义。它叫做:UserManagerInterface,而且必须继承Remote接口。

服务器端

Account.java 可供序列化的类
UserManagerInterface.java 接口
UserManagerImpl.java 接口实现
ServerMain.java 主类

Account.java:

package com.rmidemo.chenjun.bean;import java.io.Serializable;public class Account implements Serializable, Cloneable{	/**	 * serialVersionUID	 */	private static final long serialVersionUID = -8797228446371683285L;	private String username;	private String password;	public String getUsername()	{		return username;	}	public void setUsername(String username)	{		this.username = username;	}	public String getPassword()	{		return password;	}	public void setPassword(String password)	{		this.password = password;	}}

UserManagerInterface.java:

package com.rmidemo.chenjun.stub;import java.rmi.Remote;import java.rmi.RemoteException;import com.rmidemo.chenjun.bean.Account;public interface UserManagerInterface extends Remote{	public String getUserName() throws RemoteException;	public Account getAdminAccount() throws RemoteException;}

UserManagerImpl.java:

package com.rmidemo.chenjun.impl;import java.rmi.RemoteException;import com.rmidemo.chenjun.bean.Account;import com.rmidemo.chenjun.stub.UserManagerInterface;public class UserManagerImpl implements UserManagerInterface{	@Override	public String getUserName() throws RemoteException	{		return "uname";	}	@Override	public Account getAdminAccount() throws RemoteException	{		Account account = new Account();		account.setUsername("admin");		account.setPassword("admin");		return account;	}}

主类:ServerMain.java

package com.rmidemo.chenjun.app;import java.rmi.RemoteException;import java.rmi.registry.LocateRegistry;import java.rmi.registry.Registry;import java.rmi.server.UnicastRemoteObject;import com.rmidemo.chenjun.impl.UserManagerImpl;import com.rmidemo.chenjun.stub.UserManagerInterface;public class Main{	public static void main(String[] args) throws RemoteException	{		UserManagerImpl userManager = new UserManagerImpl();		UserManagerInterface userManagerInterface = (UserManagerInterface) UnicastRemoteObject.exportObject(userManager, 0);		Registry registry = LocateRegistry.createRegistry(2001);		registry.rebind("userManager", userManagerInterface);		System.out.println("server is ready");	}}
ClientMain.java 客户端主类 

直接贴代码:

package com.chenjun.rmiclient;import java.rmi.AccessException;import java.rmi.NotBoundException;import java.rmi.RemoteException;import java.rmi.registry.LocateRegistry;import java.rmi.registry.Registry;import com.rmidemo.chenjun.stub.UserManagerInterface;public class ClientApp{	public static void main(String[] args) throws AccessException, RemoteException, NotBoundException	{		Registry registry = LocateRegistry.getRegistry("localhost", 2001);		UserManagerInterface userManagerInterface = (UserManagerInterface) registry.lookup("userManager");		System.out.println("" 				+ userManagerInterface.getAdminAccount().getUsername() + userManagerInterface.getAdminAccount().getPassword());	}}

运行之前,把服务器端java工程右键->export

174619_QLJY_2338224.png

然后

174708_xhex_2338224.png

打成jar包,给客户端引用

如图,在客户端工程中引用这个打好的jar包:

174740_f0WA_2338224.png

依次启动服务器端、客户端,如图

174826_BAGq_2338224.png

 

 

转载于:https://my.oschina.net/u/2338224/blog/847864

你可能感兴趣的文章
《编写高质量代码:改善c程序代码的125个建议》——建议12-2:使用牛顿迭代法求除数的倒数...
查看>>
Lisp 家族迎来新成员,函数式语言 Lux 是什么?
查看>>
Github 开源 Atom 编辑器
查看>>
为现代 JavaScript 开发做好准备
查看>>
《CCNA无线640-722认证考试指南》——5.2节无线网络类型
查看>>
《设计之外——比修图更重要的111件事》—第1部分5 友善待人
查看>>
《21世纪机器人》一一2.1驾驶舱里,晨明号货运机:重启前30小时
查看>>
EDI —— Go 语言开发的基于 Web 的编辑器
查看>>
Jenkins 2.62 发布,可扩展的持续集成引擎
查看>>
侵犯他人商标,微软将 SkyDrive 改名 OneDrive
查看>>
《编译与反编译技术》—第2章2.4正规式和有穷自动机的等价性
查看>>
MySQL Group Replication 学习笔记—group replication 小结
查看>>
[译文]MySQL发生死锁肿么办?by何金龙
查看>>
《写给程序员的数据挖掘实践指南》——1.2并不只是对象
查看>>
如何在树莓派 2B 上安装 FreeBSD
查看>>
《Oracle PL/SQL必知必会》——1.3 试一试
查看>>
《玩转微信6.0》一第1章 邂逅微信
查看>>
《策略驱动型数据中心——ACI技术详解》——1.3 数据中心设计
查看>>
《Cucumber:行为驱动开发指南》——2.4 实现第一个步骤定义
查看>>
《PHP、MySQL和Apache入门经典(第5版)》一一1.6 故障排除
查看>>